Python实现MP4长视频切割为5分钟分片并逐片转写的方法
基于现有技术栈的长MP4切割+逐片转写实现
这套方案完全复用你已经验证过的代码逻辑,不需要额外引入重型依赖,改完即可直接运行,核心改动分为三部分:
1. 补全基础依赖与目录配置
- 首先修改顶部的导入语句:因为现在需要读取完整视频做切割,原来仅导入的
AudioFileClip无法满足视频读取需求,需要补充导入VideoFileClip,将原来的from moviepy.editor import AudioFileClip改为from moviepy.editor import AudioFileClip, VideoFileClip - 在原有
os.chdir的路径配置之后,新增两项基础配置:- 定义分片时长常量:
SEGMENT_LENGTH = 5 * 60 # 单位为秒,后续调整分片时长直接修改这个值即可 - 自动创建分片存储目录:
os.makedirs("video_segments", exist_ok=True),该目录会专门存放切好的5分钟独立mp4文件,exist_ok=True参数可以避免目录已存在时报错,避免切好的文件和原视频、转写结果混放。
- 定义分片时长常量:
2. 嵌入视频切割逻辑模块
替换原来直接读取原视频全量提取音频的流程,先完成原视频的分片切割,代码可直接加在原文件读取的对应位置:
# 读取原长视频文件 with VideoFileClip(mp4_video_file_name) as full_video: # 获取视频总时长 total_duration = full_video.duration # 计算总共需要切多少个5分钟的分片 total_segments = math.ceil(total_duration / SEGMENT_LENGTH) # 逐段切割并导出 for seg_idx in range(total_segments): # 计算当前分片的开始、结束时间 start = seg_idx * SEGMENT_LENGTH end = min((seg_idx + 1) * SEGMENT_LENGTH, total_duration) # 截取对应时间范围的视频片段 segment = full_video.subclip(start, end) # 生成分片文件路径,命名格式为 原文件名_segment序号.mp4 segment_save_path = os.path.join("video_segments", f"{FILE}_segment{seg_idx}.mp4") # 导出分片mp4,加参数优化导出速度、减少冗余日志 segment.write_videofile( segment_save_path, codec="libx264", audio_codec="aac", verbose=False, logger=None )
切割生成的mp4会完整保留原视频的全部音视频流,不会出现音画不同步的问题,不需要额外做对齐处理。
3. 调整转写流程,逐分片执行处理
你原来编写的“按1分钟切片调用谷歌接口识别”的核心逻辑可以完全复用,只需要调整成遍历切割好的分片、对每个分片单独提取音频执行识别即可,不需要改动已验证可用的识别调用部分:
- 先把单文件转写的流程封装成通用函数,避免重复写代码:
def process_single_segment(mp4_segment_path, final_result_file, recognizer): # 从分片mp4中提取音轨 audio = AudioFileClip(mp4_segment_path) # 生成临时wav文件,供speech_recognition读取 temp_wav = os.path.splitext(mp4_segment_path)[0] + "_temp.wav" audio.write_audiofile(temp_wav, verbose=False, logger=None) # 读取临时wav的总时长 with contextlib.closing(wave.open(temp_wav, 'r')) as f: frames = f.getnframes() rate = f.getframerate() wav_duration = frames / float(rate) # 沿用原有1分钟切片识别逻辑(适配谷歌识别的接口时长限制) total_min = math.ceil(wav_duration / 60) segment_text = "" for i in range(total_min): with sr.AudioFile(temp_wav) as source: audio_chunk = recognizer.record(source, offset=i*60, duration=60) chunk_text = recognizer.recognize_google(audio_chunk, language="en-US") segment_text += chunk_text + " " # 清理临时文件,避免占用磁盘空间 os.remove(temp_wav) audio.close() # 把当前分片的转写结果追加写入总结果文件 with open(final_result_file, "a", encoding="utf-8") as f: f.write(f"\n--- 分片 {os.path.basename(mp4_segment_path)} 内容 ---\n") f.write(segment_text)
- 所有视频分片切割完成后,遍历分片目录里的所有mp4文件,逐个调用上面的函数处理:
# 初始化语音识别器 recognizer = sr.Recognizer() # 定义最终总转写结果的保存路径 full_transcript_save = FILE + "_full_transcription.txt" # 遍历分片目录下的所有mp4文件,按序号顺序处理 for seg_name in sorted(os.listdir("video_segments")): if seg_name.endswith(".mp4"): seg_full_path = os.path.join("video_segments", seg_name) print(f"开始转写分片: {seg_name}") process_single_segment(seg_full_path, full_transcript_save, recognizer) print("所有分片切割、转写流程执行完成。")
实操注意点
- 如果使用的moviepy版本较新,
subclip方法需要改成subclipped,按照控制台提示的方法名调整即可 - 原来的代码在循环中频繁打开、关闭结果文件,容易出现文件句柄占用的问题,现在统一在函数内做文件读写,稳定性更高
- 如果遇到谷歌识别接口偶发报错,可以在调用
recognize_google的位置加简单的异常捕获,识别失败时标记对应段落为识别失败,不会因为单段错误中断整个批处理流程 - 切割过程不会修改原文件,所有生成的分片、临时wav都单独存放在对应目录,后续需要清理临时文件时操作成本很低
内容的提问来源于stack exchange,提问作者hellomynameisA
相关产品推荐
相关产品推荐

