如何用PHP Laravel将字幕文本传给Python并生成带字幕视频?
解决PHP传字幕文本到MoviePy时srt.parse解析错误及字幕显示异常问题
问题核心
- PHP传递的字幕文本被
srt.parse识别为单条字幕,无法拆分时间轴与内容 - 字幕仅在视频开头显示,时间轴解析完全错误
- 目标:无需生成srt文件,直接通过文本传输生成带正确字幕的视频
现有代码的关键问题
- PHP端字幕格式不符合srt规范:
原代码将所有时间轴和文本挤在一行,而标准srt要求每条字幕的时间轴、文本单独成行,且字幕间用空行分隔。 - Python端解析逻辑错误:
- 错误使用
subtitle.proprietary字段(该字段用于存储srt中的非标准内容),而非正确的subtitle.content - 仅提取
timedelta.seconds,丢失毫秒精度,导致时间轴计算错误
- 错误使用
- 命令行参数传递风险:
未对json编码后的字符串做引号包裹,可能被shell拆分参数,导致Python接收不完整的文本
解决步骤
1. 修正PHP端的字幕格式与参数传递
将字幕文本调整为标准srt结构,并用双引号包裹json编码后的字符串,确保shell完整传递:
public function store() { // 标准srt格式:每条字幕分行,时间轴与文本分开,字幕间空行 $str = <<<TEXT 1 00:00:00,319 --> 00:00:01,879 As someone with an AI background, 2 00:00:01,879 --> 00:00:04,277 I think you can probably explain to us, 3 00:00:04,277 --> 00:00:06,916 you know, this whole hype of generative AI, right? TEXT; // 用双引号包裹json字符串,避免shell拆分参数 $py_output = exec('python "C:\\xampp\\htdocs\\xampp...\\main.py" "' . json_encode($str) . '"'); var_dump($py_output); return view('videotest.store'); }
2. 修正Python端的解析与字幕生成逻辑
- 使用
json.loads解析传递的文本,保留原始换行 - 正确提取
subtitle.content作为字幕文本 - 计算时间轴时使用
timedelta.total_seconds()获取包含毫秒的完整时间 - 改用for循环遍历字幕,避免while循环的索引错误
import sys import json from moviepy.editor import VideoFileClip, TextClip, CompositeVideoClip import srt # 补充缺失的srt库导入 # 解析传递的json字符串,还原原始文本 textList = json.loads(sys.argv[1]) subtitle_generator = srt.parse(textList) subtitles = list(subtitle_generator) mp4filename = "C:\\xampp\\htdocs\\xampp..\\myvideo.mp4" def create_subtitle_clips(subtitles, videosize, fontsize=24, font='Arial', color='yellow'): subtitle_clips = [] for sub in subtitles: # 计算包含毫秒的完整开始/结束时间 start_time = sub.start.total_seconds() end_time = sub.end.total_seconds() duration = end_time - start_time video_width, video_height = videosize # 使用content字段获取正确的字幕文本 text_clip = TextClip( sub.content, fontsize=fontsize, font=font, color=color, bg_color='black', size=(video_width*3/4, None), method='caption' ).set_start(start_time).set_duration(duration) text_position = ('center', video_height * 4 / 5) subtitle_clips.append(text_clip.set_position(text_position)) return subtitle_clips video = VideoFileClip(mp4filename) begin, end = mp4filename.split(".mp4") output_video_file = f"{begin}_subtitled5.mp4" # 用f-string简化字符串拼接 subtitle_clips = create_subtitle_clips(subtitles, video.size) final_video = CompositeVideoClip([video] + subtitle_clips) # 添加编码参数,避免潜在的写入错误 final_video.write_videofile(output_video_file, codec='libx264', audio_codec='aac')
3. 额外注意事项
- 确保Python环境已安装
srt库:pip install srt - 检查文件路径是否正确,避免因路径错误导致视频无法读取/写入
- 如果字幕仍有显示问题,可调整
TextClip的size、method参数,或测试单条字幕的生成效果排查问题
内容的提问来源于stack exchange,提问作者RCeyda
相关产品推荐
相关产品推荐

