VTT字幕时间戳修改问题:Python代码写入位置错误求助
解决VTT字幕时间戳替换后内容写入位置错误的问题
嘿,我明白你遇到的麻烦了——你的代码现在把修改后的时间戳行一股脑写在文件开头,既没保留不需要修改的行,也没替换对应位置的原内容对吧?咱们来搞定这个问题。
问题根源
你原来用了r+模式打开文件,然后seek(0)后直接写入修改后的行,但这种方式有两个问题:
- 只处理了时间戳行,完全丢掉了字幕序号、台词内容这些不需要修改的行;
- 从文件开头写入会直接覆盖原有内容,导致所有新内容堆在开头,结构完全乱掉。
解决方案:先处理所有行,再一次性写入
正确的思路是先把文件里的每一行都读出来,处理需要修改的时间戳行,保留其他行,最后把完整的处理结果一次性写入文件。这样既能保证所有行都在正确位置,也不会覆盖出错。
这里给你补全并优化后的代码:
from sys import argv script, filename = argv # 把输入的调整系数转成浮点数,避免字符串运算错误 adjustment = float(input("Adjustment multiplier: ")) # 先读取所有行并处理,把结果存在列表里 processed_lines = [] with open(filename, "r") as video: for line in video: # 保留换行符的处理,避免最后格式混乱 stripped_line = line.rstrip('\n') # 判断是否是时间戳行(用-->来判断更准确) if "-->" in stripped_line: # 分割开始和结束时间戳 start_str, end_str = stripped_line.split(" --> ") # 定义工具函数:把时间字符串转成毫秒数 def time_to_ms(time_str): hours, mins, sec_ms = time_str.split(':') secs, ms = sec_ms.split('.') return int(hours)*3600000 + int(mins)*60000 + int(secs)*1000 + int(ms) # 计算调整后的毫秒数 adjusted_start_ms = time_to_ms(start_str) * adjustment adjusted_end_ms = time_to_ms(end_str) * adjustment # 定义工具函数:把毫秒数转回VTT格式的时间字符串 def ms_to_time(ms): hours = int(ms // 3600000) ms %= 3600000 mins = int(ms // 60000) ms %= 60000 secs = int(ms // 1000) remaining_ms = int(ms % 1000) # 用格式化字符串保证两位数的时/分/秒,三位数的毫秒 return f"{hours:02d}:{mins:02d}:{secs:02d}.{remaining_ms:03d}" # 生成新的时间戳行 new_timestamp_line = f"{ms_to_time(adjusted_start_ms)} --> {ms_to_time(adjusted_end_ms)}" processed_lines.append(new_timestamp_line) else: # 非时间戳行直接保留(比如字幕序号、台词内容) processed_lines.append(stripped_line) # 把处理后的所有内容写入文件(w模式会清空原文件后写入,保证内容正确) with open(filename, "w") as video: # 把列表里的行用换行符连接,最后再加一个换行保证文件格式正确 video.write('\n'.join(processed_lines) + '\n')
关键优化点
- 用
with语句管理文件,不用手动调用close(),既安全又省心; - 优化了时间戳行的判断逻辑(用
-->),比原来的l[:2] == "00"更准确,不会误判其他开头是00的行; - 把所有处理后的行存在列表里,最后一次性写入,保证整个文件的结构和原文件一致,只是替换了时间戳;
- 补全了时间戳和毫秒的转换逻辑,确保格式完全符合VTT要求。
内容的提问来源于stack exchange,提问作者Will Howard




