双语字幕时间轴错位
从海外下载的英文 SRT 字幕时间轴与本地视频版本差 3.2 秒,手动拖拽对位耗时且不准。用本工具将 SRT 转为 ASS 格式,在 ASS 中直接批量偏移所有时间戳 +3.2 秒,再转回 SRT 输出。无需重装播放器或剪辑软件,单次操作即可让字幕与口型完全同步,适合需要快速校对多集剧集的字幕组后期。
字幕文件卡在播放器里乱码,往往是格式不对——SRT的纯文本、VTT的样式、ASS的特效、LRC的歌词时间码,播放器只认一种。把文件拖进浏览器,选目标格式,它只做格式重组与时间轴重算,不上传任何文件。
从海外下载的英文 SRT 字幕时间轴与本地视频版本差 3.2 秒,手动拖拽对位耗时且不准。用本工具将 SRT 转为 ASS 格式,在 ASS 中直接批量偏移所有时间戳 +3.2 秒,再转回 SRT 输出。无需重装播放器或剪辑软件,单次操作即可让字幕与口型完全同步,适合需要快速校对多集剧集的字幕组后期。
音乐区 Up 主录制翻唱视频后,手头只有 LRC 歌词文件,想直接嵌入视频作为硬字幕。LRC 时间戳格式([00:12.34])不被剪辑软件识别。将 LRC 导入本工具转为 SRT,再用剪辑软件导入 SRT 生成字幕轨道,保留原歌词每句时间点,无需逐句手动打点,节省 80% 对轴时间。
字幕校对员收到一份 VTT 文件,需逐句对比原文与译文,但 VTT 的 cue 标签和定位信息干扰阅读。用本工具将 VTT 转为 LRC(仅保留时间戳+文本),再导出纯文本列表,每行只显示时间点和对应字幕,方便逐句核对翻译准确性。校对完成后,再转回 VTT 还原原格式,不丢失任何 cue 标签。
动漫字幕组收到一份带复杂特效(滚动、渐变色、字体)的 ASS 字幕,但合作平台只支持 SRT 格式。直接删除特效会丢失所有时间轴信息。用本工具将 ASS 转为 SRT,自动剥离所有样式代码,仅保留纯文本和时间戳,且能处理 ASS 中多层重叠对话的合并,确保每句字幕在正确时间显示。
纪录片制作人需为同一视频制作中英双语字幕,但两份 SRT 文件起始时间差 0.8 秒(中文版从 00:00:00 开始,英文版从 00:00:00.8 开始)。将两份文件分别导入本工具,对英文版整体偏移 -0.8 秒,再导出为统一格式的 SRT,合并后两条字幕时间轴完全对齐,避免后期剪辑时逐条调整。
| 维度 | 本工具 | 在线字幕站 | 手工编辑 |
|---|---|---|---|
| 隐私 | 文件在浏览器本地处理,不上传服务器 | 需上传字幕文件到对方服务器 | 完全本地,无网络传输 |
| 格式覆盖 | SRT/VTT/ASS/LRC 四种格式互转 | 多数只支持 SRT↔VTT,缺 LRC/ASS | 取决于编辑器能力,通常只读写 SRT |
| 时间轴处理 | 自动对齐偏移、检查重叠、修正毫秒精度 | 仅格式转换,不处理时间轴问题 | 手动逐条拖拽或输入,耗时长 |
| 批量处理 | 一次拖入多个文件批量转换 | 多数限单文件操作 | 逐个文件打开、另存 |
| 收费 | 免费无限制 | 免费版有文件大小或次数限制 | 需购买字幕编辑软件 |
| 注册 | 无需注册直接使用 | 部分要求注册或登录 | 不涉及 |
| 速度 | 纯浏览器计算,百条字幕秒级完成 | 受上传带宽和服务器负载影响 | 依赖操作熟练度,通常分钟级 |
| 输入 | 输出 | 说明 |
|---|---|---|
| 1 00:00:01,000 --> 00:00:04,000 Hello, world! 2 00:00:05,000 --> 00:00:08,500 This is a test. 3 00:00:10,000 --> 00:00:12,000 Goodbye. | 1 00:00:01,000 --> 00:00:04,000 Hello, world! 2 00:00:05,000 --> 00:00:08,500 This is a test. 3 00:00:10,000 --> 00:00:12,000 Goodbye. | 常规:标准 SRT 三字幕,验证基本解析与输出一致性,无格式错误时原样保留。 |
| 1 00:01:30,000 --> 00:01:35,000 Line1 Line2 2 00:02:00,000 --> 00:02:05,000 Single line. | 1 00:01:30,000 --> 00:01:35,000 Line1<br>Line2 2 00:02:00,000 --> 00:02:05,000 Single line. | 边界:多行文本(换行)在 VTT 输出时被合并为 <br>,验证工具对多行内容的处理逻辑。 |
| 1 00:00:00,000 --> 00:00:02,500 Hello 2 00:00:03,000 --> 00:00:05,000 World 3 00:00:06,000 --> 00:00:08,000 Foo 4 00:00:09,000 --> 00:00:11,000 Bar | 1 00:00:00,000 --> 00:00:02,500 Hello 2 00:00:03,000 --> 00:00:05,000 World 3 00:00:06,000 --> 00:00:08,000 Foo 4 00:00:09,000 --> 00:00:11,000 Bar | 常规:连续无间隙字幕,验证工具不会错误合并相邻字幕块,时间轴保持独立。 |
| 1 00:00:00,500 --> 00:00:02,000 Start with offset 2 00:00:02,500 --> 00:00:04,000 Middle 3 00:00:04,500 --> 00:00:06,000 End | 1 00:00:00,500 --> 00:00:02,000 Start with offset 2 00:00:02,500 --> 00:00:04,000 Middle 3 00:00:04,500 --> 00:00:06,000 End | 常规:时间轴带毫秒偏移(非整秒),验证毫秒精度保留,不四舍五入。 |
| 1 00:00:01,000 --> 00:00:03,000 Text with <b>bold</b> and <i>italic</i> | 1 00:00:01,000 --> 00:00:03,000 Text with <b>bold</b> and <i>italic</i> | 边界:字幕内容含 HTML 标签,验证工具是否原样保留(不转义也不解析),适合 SRT 转 ASS 时保留样式。 |
| 1 00:00:01,000 --> 00:00:03,000 Line with 中文 and English 123 | 1 00:00:01,000 --> 00:00:03,000 Line with 中文 and English 123 | 易错:中英文混排 + 数字,验证 Unicode 字符完整保留,不出现乱码或截断。 |
| 1 00:00:01,000 --> 00:00:03,000 2 00:00:04,000 --> 00:00:06,000 Non-empty | 1 00:00:01,000 --> 00:00:03,000 2 00:00:04,000 --> 00:00:06,000 Non-empty | 边界:空字幕内容(仅换行),验证工具不会跳过或报错,保留空行结构。 |
| 1 00:00:01,000 --> 00:00:03,000 Normal 2 00:00:03,000 --> 00:00:05,000 Overlap start 3 00:00:04,500 --> 00:00:06,000 Another overlap | 1 00:00:01,000 --> 00:00:03,000 Normal 2 00:00:03,000 --> 00:00:05,000 Overlap start 3 00:00:04,500 --> 00:00:06,000 Another overlap | 易错:时间轴重叠(字幕 2 与字幕 3 时间交叉),验证工具不自动修正重叠,原样保留,用户需自行检查。 |
1.SRT 序号后跟了多余空格或 Tab
1
00:00:01,000 --> 00:00:04,000
Hello1
00:00:01,000 --> 00:00:04,000
HelloSRT 规范要求序号独占一行,后面不能有空格或 Tab。解析器遇到多余空白会报错或跳过该字幕块。
2.时间轴分隔符混用逗号和点号
00:00:01.000 --> 00:00:04,00000:00:01,000 --> 00:00:04,000SRT 使用逗号作为毫秒分隔符(如 01,000),VTT 使用点号(如 01.000)。混用会导致时间解析失败。
3.LRC 时间戳缺少方括号或格式错误
[00:01.23]歌词[00:01.23]歌词LRC 标准格式为 [mm:ss.xx] 或 [mm:ss.xxx],方括号必须成对且时间戳内不能有空格。缺少括号或格式不对会被忽略。
4.ASS 样式定义中字体名包含未转义逗号
Style: Default,Arial, 20,&H00FFFFFF,...Style: Default,Arial,20,&H00FFFFFF,...ASS 样式行用逗号分隔字段,字体名若含逗号必须用引号包裹。多余空格会导致字段偏移,样式失效。
5.VTT 缺少必需的头部声明
00:00:01.000 --> 00:00:04.000
HelloWEBVTT
00:00:01.000 --> 00:00:04.000
HelloVTT 规范要求文件以 WEBVTT 开头(可带编码标记),缺少该声明会被多数播放器拒绝解析。
6.SRT 时间轴结束时间早于开始时间
00:00:05,000 --> 00:00:03,00000:00:03,000 --> 00:00:05,000时间轴必须递增,结束时间必须大于开始时间。倒序时间会导致播放器显示异常或跳过该字幕。
7.ASS 对话行使用了错误的格式字段数
Dialogue: 0,0:00:01.00,0:00:04.00,Default,,0,0,0,,HelloDialogue: 0,0:00:01.00,0:00:04.00,Default,,0,0,0,,,HelloASS 对话行有 10 个字段(包括 Layer、Start、End、Style、Name、MarginL/R/V、Effect、Text),缺少字段(如 Effect 后的逗号)会导致文本被错误解析。
8.LRC 歌词时间戳重叠或顺序错乱
[00:05.00]第二句
[00:03.00]第一句[00:03.00]第一句
[00:05.00]第二句LRC 播放器按时间戳顺序显示歌词,乱序会导致歌词提前或延后出现,影响同步体验。
T_new = T_old × (F_new / F_old) + Δ
T_old原时间戳,单位秒F_new目标帧率,如 30F_old原帧率,如 25Δ手动偏移量,单位秒,可正可负原 SRT 字幕时间戳为 00:01:30,000(即 90 秒),原帧率 25 fps,需转为 30 fps 且整体提前 0.5 秒。代入:T_new = 90 × (30 / 25) + (-0.5) = 90 × 1.2 - 0.5 = 108 - 0.5 = 107.5 秒,即新时间戳为 00:01:47,500。
5 种主流语言实现,复制即用:
import re
def srt_to_vtt(srt_text: str) -> str:
# SRT 与 VTT 时间格式相同,仅需替换序号和空行
vtt = 'WEBVTT\n\n'
# 移除 SRT 序号行(纯数字行),保留时间轴和字幕
lines = srt_text.split('\n')
for line in lines:
if line.strip().isdigit():
continue # 跳过序号
# 时间轴中的逗号改为小数点(VTT 标准)
if '-->' in line:
line = line.replace(',', '.')
vtt += line + '\n'
return vtt.strip()
# 示例
srt = """1
00:00:01,000 --> 00:00:04,000
Hello world
2
00:00:05,000 --> 00:00:08,500
This is a test"""
print(srt_to_vtt(srt))function srtToAss(srtText) {
// ASS 需要固定的头部元数据
const header = `[Script Info]
ScriptType: v4.00+
PlayResX: 1920
PlayResY: 1080
[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Arial,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,2,2,2,10,10,10,1
[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\n`;
// 解析 SRT 条目:序号、时间轴、字幕文本
const blockRegex = /(\d+)\n([\d:,]+ --> [\d:,]+)\n([\s\S]*?)(?=\n\d+\n|$)/g;
let events = '';
let match;
while ((match = blockRegex.exec(srtText)) !== null) {
const timeLine = match[2].replace(/,/g, '.'); // 逗号转点
const text = match[3].replace(/\n/g, '\\N'); // 换行转 ASS 换行符
events += `Dialogue: 0,${timeLine},Default,,0,0,0,,${text}\n`;
}
return header + events;
}
// 示例
const srt = `1
00:00:01,000 --> 00:00:04,000
Hello world
2
00:00:05,000 --> 00:00:08,500
This is a test`;
console.log(srtToAss(srt));package main
import (
"fmt"
"strings"
"regexp"
)
// srtToLrc 将 SRT 字幕转为 LRC 歌词格式(仅保留时间轴+文本,忽略序号)
func srtToLrc(srt string) string {
// 匹配时间轴行:00:00:01,000 --> 00:00:04,000
re := regexp.MustCompile(`(\d{2}):(\d{2}):(\d{2}),(\d{3})\s*-->\s*(\d{2}):(\d{2}):(\d{2}),(\d{3})`)
lines := strings.Split(srt, "\n")
var lrcLines []string
for _, line := range lines {
if matches := re.FindStringSubmatch(line); matches != nil {
// 取开始时间,转为 [mm:ss.xx] 格式(LRC 标准)
min := matches[2]
sec := matches[3]
milli := matches[4][:2] // 取前两位作为百分秒
lrcLines = append(lrcLines, fmt.Sprintf("[%s:%s.%s]", min, sec, milli))
} else if strings.TrimSpace(line) != "" && !strings.Contains(line, "-->" && !regexp.MustCompile(`^\d+$`).MatchString(line) {
// 非序号、非时间轴、非空行 → 字幕文本
lrcLines = append(lrcLines, line)
}
}
return strings.Join(lrcLines, "\n")
}
func main() {
srt := `1
00:00:01,000 --> 00:00:04,000
Hello world
2
00:00:05,000 --> 00:00:08,500
This is a test`
fmt.Println(srtToLrc(srt))
}#!/bin/bash
# 使用 ffmpeg 将 SRT 转为 VTT(无需重新编码,仅格式转换)
# 用法: ./srt2vtt.sh input.srt output.vtt
if [ $# -ne 2 ]; then
echo "Usage: $0 input.srt output.vtt"
exit 1
fi
ffmpeg -y -i "$1" -c:s webvtt "$2" 2>/dev/null
if [ $? -eq 0 ]; then
echo "Converted: $1 -> $2"
else
echo "Error: ffmpeg conversion failed"
exit 1
fi// 使用 Node.js 内置模块解析 VTT 并输出 SRT(时间轴点号转逗号)
import * as fs from 'fs';
function vttToSrt(vttPath: string, srtPath: string): void {
const vtt = fs.readFileSync(vttPath, 'utf-8');
// 移除 WEBVTT 头部及空行
let srt = vtt.replace(/^WEBVTT\s*\n+/, '');
// 时间轴中的点号转逗号(SRT 标准)
srt = srt.replace(/(\d{2}:\d{2}:\d{2})\.(\d{3})/g, '$1,$2');
// 添加序号(按出现顺序)
const blocks = srt.split(/\n\n+/);
const numbered = blocks.map((block, idx) => `${idx + 1}\n${block}`).join('\n\n');
fs.writeFileSync(srtPath, numbered, 'utf-8');
}
// 示例调用(需有 input.vtt 文件)
// vttToSrt('input.vtt', 'output.srt');
console.log('VTT to SRT conversion function ready.');SRT 用毫秒(00:01:23,456),LRC 用百分秒(00:01:23.45),而且 LRC 通常只保留到百分位。本工具转换时自动截断毫秒→百分秒(舍去最后 1 位小数,不做四舍五入),所以最多差 0.01 秒。如果对不上,更常见的原因是原 SRT 里时间轴本身不准,或者歌词软件用了不同的时间偏移。建议先检查原 SRT 时间戳是否精确到毫秒级。
LRC 格式里,时间标签是 [00:01.23] 这种百分秒写法,没有起始和结束时间,只有开始时间。本工具转换时,默认给每条字幕的结束时间设为下一条开始时间减 0.1 秒。如果你的 LRC 文件里连续两句歌词间隔很短(比如 0.2 秒),工具会按 0.1 秒结束,播放器显示时可能会因为解码延迟看起来像“偏了”。这是 LRC→SRT 的固有局限,不是工具 bug。
SRT 只存纯文本和时间轴,ASS 能存字体、颜色、位置、动画等样式。本工具转换 ASS→SRT 时会丢弃所有样式信息,只保留文本和时间轴。如果你只是要纯字幕(比如给电视、老播放器),SRT 通用性最好;如果你要做特效字幕(卡拉 OK 变色、滚动等),必须用 ASS。工具只做格式互转,不修改样式。
VTT 格式允许包含注释(以 NOTE 开头)和空行作为分段标记。本工具在解析 VTT 时,会自动跳过所有注释行和连续空行,只提取有效的时间轴和字幕文本。转换后的 SRT/ASS/LRC 里不会保留这些注释,因为目标格式不支持。如果你需要保留注释,建议手动复制出来。
检查原文件的时间轴格式。SRT 和 VTT 用毫秒(00:01:23.456),ASS 用百分秒(0:01:23.45),LRC 用百分秒([00:01.23])。本工具在解析时会自动识别格式,但如果你的文件里混用了不同格式(比如 SRT 里用了百分秒),解析会出错。另外,某些播放器会自带时间偏移设置,建议先在本地播放器里确认原文件本身时间是否准确。
不能。本工具是纯浏览器端处理,一次只能上传一个文件。如果你有多个文件需要转换,需要逐个操作。批量转换需要后端支持,目前工具不支持。如果文件数量多,建议用本地软件(如 Subtitle Edit)批量处理,或者用脚本调用 ffmpeg。
乱码通常是因为原文件的编码不是 UTF-8。SRT 和 VTT 常用 UTF-8,但有些老工具生成的是 GBK 或 ANSI(Windows 默认编码)。本工具默认只解析 UTF-8 编码的文件。如果原文件是 GBK,转换后中文会变乱码。解决方法:先在记事本里把原文件另存为 UTF-8 编码,再上传。ASS 文件本身支持指定编码,但工具只读数据部分。
完全安全。本工具是纯浏览器端运行(FE 实现),所有文件解析和格式转换都在你本地浏览器里完成,不会上传到任何服务器。你上传的文件不会被存储、不会离开你的电脑。关闭页面后所有数据自动清除。适合处理隐私内容(如未发布的视频字幕)。
粘贴文本时,工具会尝试按行解析。如果原文本里混入了空行、多余空格、或者时间轴格式不标准(比如用了全角冒号,或者时间戳之间用了空格而非逗号),解析就会出错。建议先检查原文本格式:SRT 必须严格是“序号→时间轴→字幕文本→空行”的循环结构;时间轴里的冒号和逗号必须是半角符号。
隐私保证所有计算与处理均在你的浏览器本地完成,输入数据不会上传服务器,也不会保存或共享。