news 2026/4/21 5:27:30

python_字幕文本、音频、视频一键组合

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
python_字幕文本、音频、视频一键组合

python_字幕文本、音频、视频一键组合

importosimportreimportrandomimportpyJianYingDraftasdraftfrompyJianYingDraftimport(TrackType,TextStyle,ClipSettings,TextBackground,KeyframeProperty,trange)defsplit_subtitle(subtitle):"""将字幕按指定标点符号拆分短句,保留标点符号在句尾"""separators=r'([,。!,!?;])'parts=re.split(separators,subtitle)sentences=[]foriinrange(0,len(parts)-1,2):ifparts[i]orparts[i+1]:# 避免空字符串sentences.append(parts[i]+parts[i+1])# 处理可能剩余的部分(如果字幕不以标点结尾)iflen(parts)%2==1andparts[-1].strip():sentences.append(parts[-1].strip())returnsentencesdefcreate_jianying_draft(draft_name,subtitle_texts,audio_paths,video_paths,draft_folder_path,background_image=None,background_music=None,add_camera_movement=True):""" 创建剪映草稿,支持视频、音频、字幕同步处理,根据视频横竖屏自适应调整,支持字幕拆分和运镜效果 参数说明: draft_name: 草稿名称 subtitle_texts: 字幕文本列表 audio_paths: 音频路径列表 video_paths: 视频路径列表 draft_folder_path: 剪映草稿文件夹路径 background_image: 背景图片路径(可选) background_music: 背景音乐路径(可选) add_camera_movement: 是否添加运镜效果(可选,默认True) """# 定义6种运镜效果的关键帧设置函数defadd_zoom_in(segment,duration):"""从远到近(放大)"""segment.add_keyframe(KeyframeProperty.uniform_scale,0,1)segment.add_keyframe(KeyframeProperty.uniform_scale,time_offset=duration,value=1.25)segment.add_keyframe(KeyframeProperty.position_x,time_offset=0,value=0)segment.add_keyframe(KeyframeProperty.position_x,time_offset=duration,value=0)segment.add_keyframe(KeyframeProperty.position_y,time_offset=0,value=0)segment.add_keyframe(KeyframeProperty.position_y,time_offset=duration,value=0)defadd_zoom_out(segment,duration):"""从近到远(缩小)"""segment.add_keyframe(KeyframeProperty.uniform_scale,time_offset=0,value=1.25)segment.add_keyframe(KeyframeProperty.uniform_scale,time_offset=duration,value=1)segment.add_keyframe(KeyframeProperty.position_x,time_offset=0,value=0)segment.add_keyframe(KeyframeProperty.position_x,time_offset=duration,value=0)segment.add_keyframe(KeyframeProperty.position_y,time_offset=0,value=0)segment.add_keyframe(KeyframeProperty.position_y,time_offset=duration,value=0)defadd_move_up(segment,duration):"""从下到上"""segment.add_keyframe(KeyframeProperty.uniform_scale,time_offset=0,value=1.25)segment.add_keyframe(KeyframeProperty.uniform_scale,time_offset=duration,value=1.25)segment.add_keyframe(KeyframeProperty.position_x,time_offset=0,value=0)segment.add_keyframe(KeyframeProperty.position_x,time_offset=duration,value=0)segment.add_keyframe(KeyframeProperty.position_y,time_offset=0,value=-0.25)segment.add_keyframe(KeyframeProperty.position_y,time_offset=duration,value=0.25)defadd_move_down(segment,duration):"""从上到下"""segment.add_keyframe(KeyframeProperty.uniform_scale,time_offset=0,value=1.25)segment.add_keyframe(KeyframeProperty.uniform_scale,time_offset=duration,value=1.25)segment.add_keyframe(KeyframeProperty.position_x,time_offset=0,value=0)segment.add_keyframe(KeyframeProperty.position_x,time_offset=duration,value=0)segment.add_keyframe(KeyframeProperty.position_y,time_offset=0,value=0.25)segment.add_keyframe(KeyframeProperty.position_y,time_offset=duration,value=-0.25)defadd_move_left(segment,duration):"""从右到左"""segment.add_keyframe(KeyframeProperty.uniform_scale,time_offset=0,value=1.25)segment.add_keyframe(KeyframeProperty.uniform_scale,time_offset=duration,value=1.25)segment.add_keyframe(KeyframeProperty.position_x,time_offset=0,value=-0.25)segment.add_keyframe(KeyframeProperty.position_x,time_offset=duration,value=0.25)segment.add_keyframe(KeyframeProperty.position_y,time_offset=0,value=0)segment.add_keyframe(KeyframeProperty.position_y,time_offset=duration,value=0)defadd_move_right(segment,duration):"""从左到右"""segment.add_keyframe(KeyframeProperty.uniform_scale,time_offset=0,value=1.25)segment.add_keyframe(KeyframeProperty.uniform_scale,time_offset=duration,value=1.25)segment.add_keyframe(KeyframeProperty.position_x,time_offset=0,value=0.25)segment.add_keyframe(KeyframeProperty.position_x,time_offset=duration,value=-0.25)segment.add_keyframe(KeyframeProperty.position_y,time_offset=0,value=0)segment.add_keyframe(KeyframeProperty.position_y,time_offset=duration,value=0)# 运镜效果列表camera_effects=[add_zoom_in,add_zoom_out,add_move_up,add_move_down,add_move_left,add_move_right]# 校验输入参数长度一致性iflen(subtitle_texts)!=len(audio_paths)orlen(audio_paths)!=len(video_paths):raiseValueError("字幕文本列表、音频路径列表、视频路径列表长度必须一致")# 校验视频路径有效性ifnotvideo_paths:raiseValueError("视频路径列表不能为空")# 检查所有文件是否存在missing_files=[]forvideo_pathinvideo_paths:ifnotos.path.exists(video_path):missing_files.append(f"视频:{video_path}")foraudio_pathinaudio_paths:ifnotos.path.exists(audio_path):missing_files.append(f"音频:{audio_path}")ifbackground_imageandnotos.path.exists(background_image):missing_files.append(f"背景图片:{background_image}")ifbackground_musicandnotos.path.exists(background_music):missing_files.append(f"背景音乐:{background_music}")ifmissing_files:raiseFileNotFoundError(f"以下文件不存在:\n"+"\n".join(missing_files))# 初始化草稿文件夹draft_folder=draft.DraftFolder(draft_folder_path)# 检查草稿是否已存在ifdraft_folder.has_draft(draft_name):raiseFileExistsError(f"草稿 '{draft_name}' 已存在,不允许覆盖")# 获取第一个视频的信息以确定尺寸和横竖屏first_video=draft.VideoMaterial(video_paths[0])width,height=first_video.width,first_video.height# 根据视频横竖屏设置字幕参数ifwidth>height:# 横屏font_size=6.0subtitle_y=-0.8else:# 竖屏font_size=13.0subtitle_y=-0.3# 创建新草稿script=draft_folder.create_draft(draft_name,width,height,allow_replace=False# 不允许覆盖已有草稿)# 添加所需轨道track_builder=script.add_track(TrackType.video,"视频轨道")\.add_track(TrackType.audio,"音频轨道")\.add_track(TrackType.text,"字幕轨道")ifbackground_image:# 背景图片放到底层(相对索引值大表示更靠后)track_builder.add_track(TrackType.video,"背景图片轨道",relative_index=3)ifbackground_music:track_builder.add_track(TrackType.audio,"背景音乐轨道")current_time=0# 当前时间点(微秒)total_duration=0# 总时长(微秒)separators=r'([,。!,!?;])'# 处理每个片段(视频、音频、字幕)foriinrange(len(subtitle_texts)):audio_path=audio_paths[i]video_path=video_paths[i]subtitle_text=subtitle_texts[i]# 创建音频片段并获取时长audio_material=draft.AudioMaterial(audio_path)audio_duration=audio_material.duration time_range=trange(current_time,audio_duration)audio_segment=draft.AudioSegment(audio_path,time_range)script.add_segment(audio_segment,"音频轨道")# 创建视频片段(根据音频时长调整速度)video_material=draft.VideoMaterial(video_path)video_duration=video_material.duration speed=video_duration/audio_duration# 计算所需速度以匹配音频时长video_segment=draft.VideoSegment(video_path,time_range,speed=speed)# 设置视频居中显示video_segment.clip_settings=ClipSettings(transform_x=0,transform_y=0,)# 添加关键帧确保视频保持比例video_segment.add_keyframe(KeyframeProperty.uniform_scale,time_offset=0,value=1.0)# 随机添加运镜效果ifadd_camera_movement:effect=random.choice(camera_effects)effect(video_segment,audio_duration)script.add_segment(video_segment,"视频轨道")# 拆分字幕为短句并添加sentences=split_subtitle(subtitle_text)total_length=len(subtitle_text)# 如果没有拆分出短句(无标点符号),使用原字幕ifnotsentences:sentences=[subtitle_text]# 计算每个短句的显示时间并添加current_sub_time=current_timeforsentenceinsentences:# 计算短句长度占比(避免除零错误)iftotal_length==0:ratio=1.0/len(sentences)else:ratio=len(sentence)/total_length# 计算当前短句的显示时长sentence_duration=int(audio_duration*ratio)# 确保至少有100ms的显示时间sentence_duration=max(sentence_duration,100000)# 100,000微秒 = 0.1秒# 计算当前短句的时间范围sentence_time_range=trange(current_sub_time,sentence_duration)# 添加字幕片段text_segment=draft.TextSegment(re.sub(separators,'',sentence),# 移除标点符号sentence_time_range,font=draft.FontType.文轩体,style=TextStyle(color=(1.0,1.0,1.0),# 白色文字size=font_size,# 根据横竖屏设置字体大小align=1,# 居中对齐auto_wrapping=True,# 开启自动换行max_line_width=0.8,# 每行最大宽度为屏幕宽度的80%),background=TextBackground(color="#000000",# 黑色背景alpha=0.5,# 背景透明度round_radius=0.1,# 背景圆角height=0.15,# 背景高度width=0.8# 背景宽度),clip_settings=ClipSettings(transform_y=subtitle_y)# 根据横竖屏设置位置)script.add_segment(text_segment,"字幕轨道")# 更新当前字幕时间current_sub_time+=sentence_duration# 更新时间current_time+=audio_duration total_duration=current_time# 处理背景图片ifbackground_image:image_segment=draft.VideoSegment(background_image,trange(0,total_duration))script.add_segment(image_segment,"背景图片轨道")# 处理背景音乐ifbackground_music:music_material=draft.AudioMaterial(background_music)music_duration=music_material.duration current_music_time=0# 循环添加背景音乐直到达到总时长whilecurrent_music_time<total_duration:remaining_time=total_duration-current_music_time segment_duration=min(music_duration,remaining_time)music_segment=draft.AudioSegment(background_music,trange(current_music_time,segment_duration),volume=0.3,# 降低背景音乐音量source_timerange=trange(0,segment_duration))script.add_segment(music_segment,"背景音乐轨道")current_music_time+=segment_duration# 保存草稿script.save()# 打印成功提示print(f"剪映草稿{draft_name}创建成功!")# 使用示例:create_jianying_draft(draft_name="示例草稿19",subtitle_texts=["在一座古老小镇,每到清明便细雨纷纷。年轻画师林羽,每到此时总会对着一幅未完成的画发呆。","这幅画始于七年前,画中女子荷风微摆衣角,宛如仙子。","七年前,林羽与名叫婉清的姑娘相遇,二人一见钟情。"],audio_paths=['D:\\Desktop\\test_folder\\jianying_materials_2\\audios\\01.mp3','D:\\Desktop\\test_folder\\jianying_materials_2\\audios\\02.mp3','D:\\Desktop\\test_folder\\jianying_materials_2\\audios\\03.mp3'],video_paths=['D:\\Desktop\\test_folder\\jianying_materials_2\\videos\\04.mp4','D:\\Desktop\\test_folder\\jianying_materials_2\\videos\\05.mp4','D:\\Desktop\\test_folder\\jianying_materials_2\\videos\\06.mp4'],# background_image="D:\\Desktop\\test_folder\\jianying_materials_2\\影刀logo图片_横版.png",background_image="D:\\Desktop\\test_folder\\jianying_materials_2\\影刀logo图片_竖版.png",background_music="D:\\Desktop\\test_folder\\jianying_materials_2\\background_music.mp3",draft_folder_path="D:\\download_software\\JianyingPro Drafts")
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 13:05:39

基于SpringBoot学生成绩管理系统毕业设计项目源码

题目简介基于 SpringBoot 的学生成绩管理系统&#xff0c;直击 “成绩录入效率低、数据统计不精准、学情分析滞后、权限管控不清晰” 的核心痛点&#xff0c;依托 SpringBoot 轻量级框架优势&#xff0c;构建 “成绩录入 数据统计 学情分析 权限管控” 的一体化管理平台。系…

作者头像 李华
网站建设 2026/4/19 13:13:59

YashanDB数据库的集成与互操作性问题探讨

在现代企业信息系统中&#xff0c;数据库技术扮演着核心的数据管理角色。随着业务场景的多样化和系统的复杂化&#xff0c;数据库的集成与互操作性问题日益突出。对于YashanDB这一多形态支持、具备高性能与高可用特性的数据库系统而言&#xff0c;如何实现与各种应用环境及异构…

作者头像 李华
网站建设 2026/4/19 13:13:59

RAG - 高阶检索范式 - 基于表示 - ColBERT - 迟交互机制

原文 https://arxiv.org/pdf/2004.12832 ColBERT ColBERT: Efficient and Effective Passage Search via Contextualized Late Interaction over BERT 基于 BERT 的上下文感知延迟交互实现高效且有效的段落检索 给定一个q和一个d之后的通用流程Efficient&#xff1a;高效的 Eff…

作者头像 李华
网站建设 2026/4/19 13:13:52

使用reppoints实现微波天线与GSM天线目标检测【改进版】

1. 使用reppoints实现微波天线与GSM天线目标检测【改进版】 1.1. 引言 &#x1f680; 在无线通信基础设施维护中&#xff0c;微波天线和GSM天线的自动检测与识别是一项重要任务。传统方法往往依赖于人工巡检&#xff0c;效率低下且容易出错。随着计算机视觉技术的发展&#x…

作者头像 李华
网站建设 2026/4/19 15:20:25

15、编程语言性能与服务器设计深度剖析

编程语言性能与服务器设计深度剖析 1. 函数性能测试 在对不同函数进行性能测试时,我们关注了读取文件以及字符串长度计算等操作。相关函数的测试结果如下表所示: | Function | SML (microsec) | C (microsec) | | — | — | — | | readall | 4980 | 4609 | | length |…

作者头像 李华
网站建设 2026/4/19 15:19:18

锐捷RGSP | IP Source Guard技术原理与应用

一、IP Source Guard概述 1. IP Source Guard技术背景 在园区网的运维过程中经常会有以下这样的情况 网络中存在非法的DHCP服务器并且分配错误的IP地址和网关,导致很多终端无法上网 DHCP环境下,个别终端手工配置IP地址导致IP地址混乱甚至网络异常 局域网IP冲突会给网络的运…

作者头像 李华