manus-skills/.kortix/opencode/skills/media/youtube-clipper/references/subtitle-formatting.md
zhukang 1c7abd81d1 All 310 Manus skill-hub community skills as a Kortix marketplace registry
- 310 registry:skill items, 1528 files, 7 categories (hub tags)
- registry.json generated by @kortix/registry buildRegistry
- nested SKILL.md in sn-da-* renamed SUBSKILL.md (no phantom skills)
- provenance + licenses: SOURCES.md
2026-09-15 13:37:20 +08:00

7.7 KiB
Raw Permalink Blame History

字幕格式规范

本文档介绍 YouTube Clipper 中使用的字幕格式及其转换方法。

支持的格式

1. VTT (WebVTT)

WebVTT 是 Web 视频字幕标准格式。

格式示例

WEBVTT

1
00:00:00.000 --> 00:00:03.500
This is the first subtitle

2
00:00:03.500 --> 00:00:07.000
This is the second subtitle

特点

  • 头部必须是 WEBVTT
  • 时间戳使用点 (.) 分隔毫秒
  • 支持样式和位置信息
  • YouTube 默认字幕格式

完整示例

WEBVTT

STYLE
::cue {
  background-color: rgba(0,0,0,0.8);
  color: white;
}

1
00:00:00.000 --> 00:00:03.500 align:start position:0%
<v Speaker>This is the first subtitle</v>

NOTE This is a comment

2
00:00:03.500 --> 00:00:07.000
This is the second subtitle
with multiple lines

2. SRT (SubRip)

SRT 是最常用的字幕格式,兼容性好。

格式示例

1
00:00:00,000 --> 00:00:03,500
This is the first subtitle

2
00:00:03,500 --> 00:00:07,000
This is the second subtitle

特点

  • 没有头部
  • 时间戳使用逗号 (,) 分隔毫秒
  • 不支持样式(但 FFmpeg 可以覆盖)
  • 兼容性最好

多行文本

1
00:00:00,000 --> 00:00:03,500
This is the first line
This is the second line
This is the third line

2
00:00:03,500 --> 00:00:07,000
Single line subtitle

VTT 与 SRT 对比

特性 VTT SRT
头部 必须(WEBVTT) 无
毫秒分隔符 点 (.) 逗号 (,)
样式支持 是 否
位置控制 是 否
注释支持 是 否
兼容性 Web 通用

格式转换

VTT → SRT

Python 实现

import re

def vtt_to_srt(vtt_content):
    # 1. 移除 WEBVTT 头部
    srt_content = re.sub(r'^WEBVTT.*?\n\n', '', vtt_content, flags=re.DOTALL)

    # 2. 移除样式信息
    srt_content = re.sub(r'STYLE.*?\n\n', '', srt_content, flags=re.DOTALL)

    # 3. 移除 NOTE
    srt_content = re.sub(r'NOTE.*?\n\n', '', srt_content, flags=re.DOTALL)

    # 4. 转换时间戳分隔符: . → ,
    srt_content = re.sub(
        r'(\d{2}:\d{2}:\d{2})\.(\d{3})',
        r'\1,\2',
        srt_content
    )

    # 5. 移除位置信息
    srt_content = re.sub(
        r'(-->.*?)\s+(align|position|line|size):.*',
        r'\1',
        srt_content
    )

    # 6. 移除说话人标签 <v Speaker>
    srt_content = re.sub(r'<v [^>]+>', '', srt_content)
    srt_content = re.sub(r'</v>', '', srt_content)

    return srt_content

命令行工具

# 使用 ffmpeg
ffmpeg -i input.vtt output.srt

# 使用 sed
sed 's/\./,/3' input.vtt > output.srt  # 简单转换(不完整)

SRT → VTT

Python 实现

def srt_to_vtt(srt_content):
    # 1. 添加 WEBVTT 头部
    vtt_content = "WEBVTT\n\n" + srt_content

    # 2. 转换时间戳分隔符: , → .
    vtt_content = re.sub(
        r'(\d{2}:\d{2}:\d{2}),(\d{3})',
        r'\1.\2',
        vtt_content
    )

    return vtt_content

双语字幕

SRT 格式

双语字幕在 SRT 中使用多行文本:

1
00:00:00,000 --> 00:00:03,500
This is English subtitle
这是中文字幕

2
00:00:03,500 --> 00:00:07,000
Another English line
另一行中文

样式建议

烧录到视频时的样式:

ffmpeg -i video.mp4 \
  -vf "subtitles=bilingual.srt:force_style='FontSize=24,MarginV=30'" \
  output.mp4

推荐参数:

  • FontSize=24: 适合 1080p 视频
  • MarginV=30: 底部边距 30 像素
  • 英文在上,中文在下

时间戳格式

完整格式

HH:MM:SS.mmm --> HH:MM:SS.mmm
  • HH: 小时(00-99)
  • MM: 分钟(00-59)
  • SS: 秒(00-59)
  • mmm: 毫秒(000-999)

示例

00:00:00.000  # 0 秒
00:00:03.500  # 3.5 秒
00:01:30.250  # 1 分 30.25 秒
01:23:45.678  # 1 小时 23 分 45.678 秒

注意事项

  1. 小时部分是可选的,但为了兼容性,建议总是包含
  2. VTT 使用点 (.),SRT 使用逗号 (,)
  3. 毫秒必须是 3 位数(不足补 0)

时间调整

场景:视频剪辑后调整字幕

剪辑视频 02:00-02:10 后,字幕时间戳需要调整:

原始字幕

1
00:02:00,000 --> 00:02:03,500
First subtitle

2
00:02:03,500 --> 00:02:07,000
Second subtitle

调整后字幕

1
00:00:00,000 --> 00:00:03,500
First subtitle

2
00:00:03,500 --> 00:00:07,000
Second subtitle

Python 实现

def adjust_subtitle_time(subtitles, offset_seconds):
    """
    调整字幕时间戳

    Args:
        subtitles: 字幕列表
        offset_seconds: 偏移量(秒),即剪辑起始时间

    Returns:
        调整后的字幕列表
    """
    adjusted = []

    for sub in subtitles:
        adjusted_sub = {
            'start': max(0, sub['start'] - offset_seconds),
            'end': max(0, sub['end'] - offset_seconds),
            'text': sub['text']
        }

        # 仅保留在有效范围内的字幕
        if adjusted_sub['end'] > 0:
            adjusted.append(adjusted_sub)

    return adjusted

字幕编码

推荐编码

UTF-8(无 BOM)

检查编码

file -i subtitle.srt
# 输出: subtitle.srt: text/plain; charset=utf-8

转换编码

# GBK → UTF-8
iconv -f GBK -t UTF-8 input.srt > output.srt

# 移除 BOM
sed -i '1s/^\xEF\xBB\xBF//' subtitle.srt

字幕验证

检查项目

  1. 时间戳格式: 是否符合规范
  2. 时间顺序: 起始时间 < 结束时间
  3. 重叠检测: 相邻字幕是否重叠
  4. 编码检查: 是否 UTF-8
  5. 空行检查: 字幕间是否有空行分隔

Python 验证脚本

def validate_srt(srt_path):
    errors = []

    with open(srt_path, 'r', encoding='utf-8') as f:
        content = f.read()

    # 分割字幕块
    blocks = content.strip().split('\n\n')

    prev_end_time = 0

    for i, block in enumerate(blocks):
        lines = block.split('\n')

        if len(lines) < 3:
            errors.append(f"Block {i+1}: Invalid format (< 3 lines)")
            continue

        # 检查序号
        try:
            seq = int(lines[0])
            if seq != i + 1:
                errors.append(f"Block {i+1}: Invalid sequence number ({seq})")
        except ValueError:
            errors.append(f"Block {i+1}: Invalid sequence number")

        # 检查时间戳
        timestamp_pattern = r'(\d{2}:\d{2}:\d{2},\d{3}) --> (\d{2}:\d{2}:\d{2},\d{3})'
        match = re.match(timestamp_pattern, lines[1])

        if not match:
            errors.append(f"Block {i+1}: Invalid timestamp format")
            continue

        start_str, end_str = match.groups()
        start_time = time_to_seconds(start_str)
        end_time = time_to_seconds(end_str)

        # 检查时间逻辑
        if start_time >= end_time:
            errors.append(f"Block {i+1}: Start time >= End time")

        if start_time < prev_end_time:
            errors.append(f"Block {i+1}: Overlaps with previous subtitle")

        prev_end_time = end_time

    return errors

常见问题

Q: FFmpeg 无法读取字幕,提示编码错误

A: 确保字幕是 UTF-8 编码,且没有 BOM:

iconv -f GBK -t UTF-8 input.srt > output.srt
sed -i '1s/^\xEF\xBB\xBF//' output.srt

Q: 字幕显示乱码

A: 检查编码:

file -i subtitle.srt
# 如果不是 UTF-8,转换编码

Q: VTT 字幕在某些播放器无法显示

A: 尝试转换为 SRT 格式,兼容性更好。

Q: 双语字幕中文字太挤

A: 增加字体大小和边距:

subtitles=sub.srt:force_style='FontSize=28,MarginV=40'

参考链接