如何用Python实现字幕两位毫秒转三位有效毫秒(仿Subtitle Edit)
解决两位帧编号转三位毫秒的SRT字幕转换问题
首先明确:你看到的两位“毫秒”其实是24帧/秒(fps)下的帧编号,Subtitle Edit是把帧号转换成了对应的毫秒(公式:毫秒 = 帧号 × 1000 / 帧率),而非简单补零。比如示例里的00:00:06,10,10帧在24fps下对应的毫秒是10 × 1000/24 ≈ 417,也就是00:00:06,417,和处理后的结果完全匹配。
下面是用pysubs2实现该逻辑的代码,直接处理原始帧编号并转换为正确的毫秒:
import pysubs2 from pysubs2.time import make_time def convert_frames_to_ms(frame_num, fps=24): # 将帧号转换为毫秒,默认采用Subtitle Edit的24fps设置 return int(round(frame_num * 1000 / fps)) # 手动解析SRT文件,规避pysubs2对两位帧的错误解析 subs = pysubs2.SSAFile() with open("my_subtitles.srt", "r", encoding="utf-8") as f: lines = [line.strip() for line in f if line.strip()] i = 0 while i < len(lines): # 读取字幕序号 idx = lines[i] i += 1 # 处理时间戳行 timestamp_line = lines[i] i += 1 start_str, end_str = timestamp_line.split(" --> ") # 解析开始时间:拆分HH:MM:SS,FF格式,FF为帧号 start_h, start_m, start_s_f = start_str.split(":") start_s, start_f = start_s_f.split(",") start_ms = convert_frames_to_ms(int(start_f)) start_time = make_time(h=int(start_h), m=int(start_m), s=int(start_s), ms=start_ms) # 解析结束时间,处理末尾可能存在的点(如示例中的00:00:08,05.) end_h, end_m, end_s_f = end_str.split(":") end_s, end_f = end_s_f.split(",") end_f = end_f.rstrip(".") end_ms = convert_frames_to_ms(int(end_f)) end_time = make_time(h=int(end_h), m=int(end_m), s=int(end_s), ms=end_ms) # 读取字幕文本(支持多行) text_lines = [] while i < len(lines) and not lines[i].isdigit(): text_lines.append(lines[i]) i += 1 text = "\n".join(text_lines) # 将处理后的条目添加到字幕对象 subs.append(pysubs2.SSAEvent(start=start_time, end=end_time, text=text)) # 保存为标准三位毫秒格式的SRT文件 subs.save("Output_subtitles.srt", format_="srt")
关键说明:
- 帧率适配:如果你的字幕采用其他帧率(如30fps),只需修改
convert_frames_to_ms函数的fps参数即可。 - 手动解析逻辑:跳过pysubs2默认的时间戳解析(会把两位帧当成百分之一秒),直接读取原始字符串提取帧号,保证转换逻辑和Subtitle Edit一致。
- 异常处理:自动处理结束时间末尾的多余点,兼容你提供的示例格式。
运行代码后,你的示例字幕会生成和Subtitle Edit完全一致的三位毫秒时间戳格式。
内容的提问来源于stack exchange,提问作者komiratna521
相关产品推荐
相关产品推荐

