news 2026/5/3 13:19:20

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/5/1 7:30:48

使用ffmpeg把ogg,flac等格式转化成mp3

下载安装ffmpeg&#xff1a;https://blog.csdn.net/summer_Ashe/article/details/132820248 参考上面 不在赘述&#xff0c; 安装好之后打开cmd&#xff0c; 执行下面bash命令input.ogg是输入的ogg歌曲名称&#xff0c;output.mp3改成你想要的名字 ffmpeg -i input.ogg -co…

作者头像 李华
网站建设 2026/4/30 18:13:33

笔记本电脑的散热系统发展与仿真分析

&#x1f393;作者简介&#xff1a;科技自媒体优质创作者 &#x1f310;个人主页&#xff1a;莱歌数字-CSDN博客 &#x1f48c;公众号&#xff1a;莱歌数字 &#x1f4f1;个人微信&#xff1a;yanshanYH 211、985硕士&#xff0c;职场15年 从事结构设计、热设计、售前、产品设…

作者头像 李华
网站建设 2026/5/1 7:33:50

YashanDB数据库的国际化与本地化支持

YashanDB 是一款支持多种功能的数据库&#xff0c;尽管在我的知识库中并没有具体详细的文档或信息关于它的国际化&#xff08;i18n&#xff09;与本地化&#xff08;l10n&#xff09;特性&#xff0c;但可以从一般数据库设计的角度来讨论这一话题。国际化&#xff08;i18n&…

作者头像 李华
网站建设 2026/5/1 4:08:24

YashanDB数据库的核心指标监控与优化指南

在现代数据库系统中&#xff0c;查询速度是影响业务性能的关键因素。如何优化查询速度直接关系到系统的响应效率和用户体验。针对YashanDB数据库&#xff0c;本文将从系统架构、存储引擎、执行引擎、事务管理及高可用机制等多个维度&#xff0c;系统性地分析其核心指标监控重点…

作者头像 李华
网站建设 2026/5/1 7:08:11

33、进程间通信与调试全解析

进程间通信与调试全解析 1. 消息队列 当消息存于队列时,接收消息是按优先级而非顺序进行的。例如执行 ./posix-msgq-ex 命令,会得到如下结果: got pri 3 No more messages. len=18 got pri 1 This is my first message. len=26 got pri 1 This is my second message. …

作者头像 李华
网站建设 2026/5/2 14:44:46

41、多处理器性能与Linux调试技巧

多处理器性能与Linux调试技巧 1. 多处理器相关知识 在如今的计算环境中,多核CPU几乎适用于各种架构。为了简化讨论,这里主要以AMD和英特尔基于英特尔架构的实现为例,不过相关问题适用于所有架构。 1.1 多核CPU概述 英特尔和AMD的第一代多核CPU是双核的。从功能上看,双核…

作者头像 李华