强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

FFmpeg 多媒体处理教程 / 字幕处理

字幕处理

概述

字幕(Subtitle)是多媒体内容的重要组成部分,FFmpeg 支持多种字幕格式的处理,包括提取、转换、烧录等操作。本章详细介绍字幕的格式、处理方法和最佳实践。

字幕格式概览

常见字幕格式

格式 扩展名 类型 说明
SRT .srt 文本 最简单的字幕格式
ASS .ass 文本 Advanced SubStation Alpha,支持样式
SSA .ssa 文本 SubStation Alpha,ASS 的前身
WebVTT .vtt 文本 Web 字幕格式
TTXT .txml 文本 Timed Text XML
VobSub .sub/.idx 位图 DVD 字幕格式
PGS .sup 位图 Blu-ray 字幕格式
DVB - 位图 数字电视字幕

格式对比

格式 样式支持 定位 动画 兼容性
SRT 基本 极好
ASS 高级
SSA 高级
WebVTT 基本
VobSub 固定
PGS 固定

SRT 字幕格式

SRT 格式说明

1
00:00:01,000 --> 00:00:04,000
这是第一行字幕

2
00:00:05,000 --> 00:00:08,000
这是第二行字幕

SRT 操作

# 提取 SRT 字幕
ffmpeg -i input.mkv -map 0:s:0 output.srt

# 添加 SRT 字幕(软字幕)
ffmpeg -i input.mp4 -i subtitle.srt -c copy -c:s srt output.mkv

# 转换 SRT 为 ASS
ffmpeg -i subtitle.srt subtitle.ass

ASS/SSA 字幕格式

ASS 格式说明

[Script Info]
Title: Example
ScriptType: v4.00+

[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
Dialogue: 0,0:00:01.00,0:00:04.00,Default,,0,0,0,,这是第一行字幕
Dialogue: 0,0:00:05.00,0:00:08.00,Default,,0,0,0,,这是第二行字幕

ASS 操作

# 提取 ASS 字幕
ffmpeg -i input.mkv -map 0:s:0 output.ass

# 添加 ASS 字幕(软字幕)
ffmpeg -i input.mp4 -i subtitle.ass -c copy -c:s ass output.mkv

# 转换 ASS 为 SRT
ffmpeg -i subtitle.ass subtitle.srt

ASS 样式定制

# 创建自定义 ASS 字幕
cat > custom.ass << 'EOF'
[Script Info]
Title: Custom Subtitle
ScriptType: v4.00+

[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,Microsoft YaHei,24,&H00FFFFFF,&H000000FF,&H00000000,&H80000000,-1,0,0,0,100,100,0,0,1,3,1,2,10,10,30,1
Style: Title,Microsoft YaHei,36,&H0000FFFF,&H000000FF,&H00000000,&H80000000,-1,0,0,0,100,100,0,0,1,4,2,8,10,10,30,1

[Events]
Format: Layer,Start,End,Style,Name,MarginL,MarginR,MarginV,Effect,Text
Dialogue: 0,0:00:01.00,0:00:04.00,Default,,0,0,0,,这是默认样式的字幕
Dialogue: 0,0:00:05.00,0:00:08.00,Title,,0,0,0,,这是标题样式的字幕
EOF

WebVTT 字幕格式

WebVTT 格式说明

WEBVTT

1
00:00:01.000 --> 00:00:04.000
这是第一行字幕

2
00:00:05.000 --> 00:00:08.000
这是第二行字幕

WebVTT 操作

# 提取 WebVTT 字幕
ffmpeg -i input.mp4 -map 0:s:0 output.vtt

# 添加 WebVTT 字幕
ffmpeg -i input.mp4 -i subtitle.vtt -c copy -c:s webvtt output.mp4

# 转换 SRT 为 WebVTT
ffmpeg -i subtitle.srt subtitle.vtt

软字幕与硬字幕

软字幕(Soft Subtitle)

软字幕作为独立的字幕流存储在容器中,可以被播放器选择显示或隐藏。

# 添加软字幕(MKV 容器)
ffmpeg -i input.mp4 -i subtitle.srt -c copy -c:s srt output.mkv

# 添加软字幕(MP4 容器)
ffmpeg -i input.mp4 -i subtitle.srt -c copy -c:s mov_text output.mp4

# 添加多个软字幕
ffmpeg -i input.mp4 -i sub_cn.srt -i sub_en.srt \
    -map 0 -map 1 -map 2 \
    -c copy -c:s srt \
    -metadata:s:s:0 language=chi \
    -metadata:s:s:1 language=eng \
    output.mkv

# 设置默认字幕
ffmpeg -i input.mp4 -i subtitle.srt \
    -map 0 -map 1 \
    -c copy -c:s srt \
    -disposition:s:0 default \
    output.mkv

硬字幕(Hard Subtitle)

硬字幕被直接烧录到视频画面中,无法关闭。

# SRT 硬字幕
ffmpeg -i input.mp4 -vf "subtitles=subtitle.srt" output.mp4

# ASS 硬字幕
ffmpeg -i input.mp4 -vf "ass=subtitle.ass" output.mp4

# 指定字幕编码
ffmpeg -i input.mp4 -vf "subtitles=subtitle.srt:force_style='FontName=Microsoft YaHei,FontSize=24'" output.mp4

# 使用 MKV 内置字幕
ffmpeg -i input.mkv -vf "subtitles=input.mkv:si=0" output.mp4

软字幕 vs 硬字幕

方面 软字幕 硬字幕
可关闭
可切换
文件大小 不影响
画质影响 有(轻微)
兼容性 依赖播放器 极好
编辑 容易 需要重新编码
适用场景 多语言、收藏 兼容性需求

字幕提取

提取文本字幕

# 提取 SRT 字幕
ffmpeg -i input.mkv -map 0:s:0 output.srt

# 提取 ASS 字幕
ffmpeg -i input.mkv -map 0:s:0 output.ass

# 提取所有字幕
ffmpeg -i input.mkv -map 0:s output_%d.srt

# 提取特定语言字幕
ffmpeg -i input.mkv -map 0:s:m:language:chi output_cn.srt

提取位图字幕

# 提取 VobSub 字幕
ffmpeg -i input.mkv -map 0:s:0 output.sub

# 提取 PGS 字幕
ffmpeg -i input.mkv -map 0:s:0 output.sup

# 转换位图字幕为文本(需要 OCR)
# 使用 SubtitleEdit 或其他 OCR 工具

查看字幕信息

# 查看字幕流信息
ffprobe -v quiet -show_streams -select_streams s input.mkv

# 查看字幕格式
ffprobe -v quiet -show_entries stream=codec_name,codec_type -select_streams s input.mkv

# 列出所有字幕流
ffprobe -v quiet -show_entries stream=index,codec_name,codec_type -select_streams s input.mkv

字幕烧录

基本烧录

# 烧录 SRT 字幕
ffmpeg -i input.mp4 -vf "subtitles=subtitle.srt" -c:v libx264 -crf 23 -c:a copy output.mp4

# 烧录 ASS 字幕
ffmpeg -i input.mp4 -vf "ass=subtitle.ass" -c:v libx264 -crf 23 -c:a copy output.mp4

# 烧录容器内字幕
ffmpeg -i input.mkv -vf "subtitles=input.mkv:si=0" -c:v libx264 -crf 23 -c:a copy output.mp4

字幕样式定制

# 自定义字体
ffmpeg -i input.mp4 -vf "subtitles=subtitle.srt:force_style='FontName=Microsoft YaHei'" output.mp4

# 自定义大小
ffmpeg -i input.mp4 -vf "subtitles=subtitle.srt:force_style='FontSize=24'" output.mp4

# 自定义颜色
ffmpeg -i input.mp4 -vf "subtitles=subtitle.srt:force_style='PrimaryColour=&H00FFFFFF'" output.mp4

# 自定义边框
ffmpeg -i input.mp4 -vf "subtitles=subtitle.srt:force_style='Outline=3,Shadow=1'" output.mp4

# 自定义位置
ffmpeg -i input.mp4 -vf "subtitles=subtitle.srt:force_style='Alignment=2,MarginV=30'" output.mp4

ASS 样式参数

参数 说明 示例值
FontName 字体名称 Microsoft YaHei
FontSize 字体大小 24
PrimaryColour 主颜色 &H00FFFFFF
SecondaryColour 次颜色 &H000000FF
OutlineColour 边框颜色 &H00000000
BackColour 背景颜色 &H80000000
Bold 粗体 -1/0
Italic 斜体 -1/0
Underline 下划线 -1/0
StrikeOut 删除线 -1/0
ScaleX 水平缩放 100
ScaleY 垂直缩放 100
Spacing 字间距 0
Angle 旋转角度 0
BorderStyle 边框样式 1/3
Outline 边框宽度 2
Shadow 阴影 1
Alignment 对齐方式 1-9
MarginL 左边距 10
MarginR 右边距 10
MarginV 垂直边距 30

对齐方式

位置
1 左下
2 中下
3 右下
4 左中
5 居中
6 右中
7 左上
8 中上
9 右上

颜色格式

ASS 颜色格式为 &HAABBGGRR(十六进制):

  • AA:透明度(00=不透明,FF=完全透明)
  • BB:蓝色
  • GG:绿色
  • RR:红色
# 白色(不透明)
PrimaryColour=&H00FFFFFF

# 红色(不透明)
PrimaryColour=&H000000FF

# 半透明白色
PrimaryColour=&H80FFFFFF

字幕滤镜

subtitles 滤镜

# 基本使用
ffmpeg -i input.mp4 -vf "subtitles=subtitle.srt" output.mp4

# 指定字符编码
ffmpeg -i input.mp4 -vf "subtitles=subtitle.srt:charenc=UTF-8" output.mp4

# 使用原始时间戳
ffmpeg -i input.mp4 -vf "subtitles=subtitle.srt:original_size=1920x1080" output.mp4

# 指定流索引
ffmpeg -i input.mkv -vf "subtitles=input.mkv:si=1" output.mp4

ass 滤镜

# 基本使用
ffmpeg -i input.mp4 -vf "ass=subtitle.ass" output.mp4

# 指定字体目录
ffmpeg -i input.mp4 -vf "ass=subtitle.ass:fontsdir=/usr/share/fonts" output.mp4

drawtext 滤镜

# 基本文字
ffmpeg -i input.mp4 -vf "drawtext=text='Hello':x=10:y=10:fontsize=24:fontcolor=white" output.mp4

# 使用字幕文件
ffmpeg -i input.mp4 -vf "drawtext=file=subtitle.txt:fontsize=24:fontcolor=white:x=(w-tw)/2:y=h-50" output.mp4

# 带背景的文字
ffmpeg -i input.mp4 -vf "drawtext=text='Subtitle':fontsize=24:fontcolor=white:box=1:[email protected]:boxborderw=5:x=(w-tw)/2:y=h-50" output.mp4

字幕转换

格式转换

# SRT 转 ASS
ffmpeg -i subtitle.srt subtitle.ass

# ASS 转 SRT
ffmpeg -i subtitle.ass subtitle.srt

# SRT 转 WebVTT
ffmpeg -i subtitle.srt subtitle.vtt

# WebVTT 转 SRT
ffmpeg -i subtitle.vtt subtitle.srt

字幕编码转换

# GBK 转 UTF-8
ffmpeg -i subtitle_gbk.srt -sub_charenc GBK subtitle_utf8.srt

# 指定输入编码
ffmpeg -charenc GBK -i subtitle.srt subtitle_utf8.srt

多字幕处理

添加多语言字幕

# 添加中文和英文字幕
ffmpeg -i input.mp4 -i sub_cn.srt -i sub_en.srt \
    -map 0:v -map 0:a -map 1 -map 2 \
    -c:v copy -c:a copy -c:s srt \
    -metadata:s:s:0 language=chi \
    -metadata:s:s:1 language=eng \
    -disposition:s:0 default \
    output.mkv

字幕合并

# 合并多个字幕文件
cat sub1.srt sub2.srt > combined.srt

# 使用 FFmpeg 合并(需要重新编号)
ffmpeg -i sub1.srt -i sub2.srt -filter_complex \
    "[0:s][1:s]concat=n=2:v=0:a=0:ts=first" \
    output.srt

字幕分离

# 提取所有字幕
ffmpeg -i input.mkv -map 0:s:0 sub1.srt -map 0:s:1 sub2.srt

# 提取特定字幕
ffmpeg -i input.mkv -map 0:s:0 output.srt

字幕时间调整

时间偏移

# 使用 ffprobe 查看字幕时间
ffprobe -v quiet -show_entries stream=start_time -select_streams s:0 input.mkv

# 调整字幕时间(使用外部工具)
# 使用 SubtitleEdit 或其他工具调整

字幕同步

# 提取字幕
ffmpeg -i input.mkv -map 0:s:0 subtitle.srt

# 编辑字幕时间(使用 sed 或其他工具)

# 重新添加字幕
ffmpeg -i input.mkv -i subtitle_fixed.srt -c copy -c:s srt output.mkv

字幕嵌入

嵌入到不同容器

# 嵌入到 MKV(支持所有格式)
ffmpeg -i input.mp4 -i subtitle.srt -c copy -c:s srt output.mkv

# 嵌入到 MP4(需要 mov_text)
ffmpeg -i input.mp4 -i subtitle.srt -c copy -c:s mov_text output.mp4

# 嵌入到 WebM(需要 WebVTT)
ffmpeg -i input.mp4 -i subtitle.vtt -c copy -c:s webvtt output.webm

容器格式与字幕兼容性

容器 SRT ASS WebVTT VobSub PGS
MKV
MP4
WebM
AVI

字幕特效

ASS 特效标签

# 创建带特效的 ASS 字幕
cat > effects.ass << 'EOF'
[Script Info]
Title: Effects Example
ScriptType: v4.00+

[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,24,&H00FFFFFF,&H000000FF,&H00000000,&H80000000,0,0,0,0,100,100,0,0,1,2,1,2,10,10,30,1

[Events]
Format: Layer,Start,End,Style,Name,MarginL,MarginR,MarginV,Effect,Text
Dialogue: 0,0:00:01.00,0:00:04.00,Default,,0,0,0,,{\fad(500,500)}这是淡入淡出的字幕
Dialogue: 0,0:00:05.00,0:00:08.00,Default,,0,0,0,,{\move(100,100,300,300)}这是移动的字幕
Dialogue: 0,0:00:09.00,0:00:12.00,Default,,0,0,0,,{\fs32\c&H0000FF&}这是改变大小和颜色的字幕
EOF

常用 ASS 特效

标签 说明 示例
\fad(in,out) 淡入淡出 \fad(500,500)
\move(x1,y1,x2,y2) 移动 \move(100,100,300,300)
\pos(x,y) 位置 \pos(200,200)
\fs(size) 字体大小 \fs32
\c&HBBGGRR& 颜色 \c&H0000FF&
\alpha&HAA& 透明度 \alpha&H80&
\b(weight) 粗体 \b1
\i(1/0) 斜体 \i1
\u(1/0) 下划线 \u1
\s(1/0) 删除线 \s1
\bord(width) 边框宽度 \bord3
\shad(depth) 阴影深度 \shad2
\an(alignment) 对齐 \an8
\k(duration) 卡拉 OK \k50

批量字幕处理

批量提取字幕

#!/bin/bash
# batch_extract_subtitles.sh

INPUT_DIR=${1:-.}
OUTPUT_DIR=${2:-subtitles}

mkdir -p "$OUTPUT_DIR"

for file in "$INPUT_DIR"/*.mkv; do
    filename=$(basename "$file" .mkv)
    
    # 提取所有字幕流
    stream_index=0
    while true; do
        subtitle=$(ffmpeg -i "$file" -map 0:s:$stream_index -c:s srt -f srt - 2>/dev/null)
        if [ -z "$subtitle" ]; then
            break
        fi
        
        echo "$subtitle" > "$OUTPUT_DIR/${filename}_sub${stream_index}.srt"
        echo "提取: ${filename}_sub${stream_index}.srt"
        
        stream_index=$((stream_index + 1))
    done
done

echo "字幕提取完成"

批量烧录字幕

#!/bin/bash
# batch_burn_subtitles.sh

INPUT_DIR=${1:-.}
SUBTITLE_DIR=${2:-subtitles}
OUTPUT_DIR=${3:-output}

mkdir -p "$OUTPUT_DIR"

for file in "$INPUT_DIR"/*.mp4; do
    filename=$(basename "$file" .mp4)
    subtitle="$SUBTITLE_DIR/${filename}.srt"
    
    if [ -f "$subtitle" ]; then
        echo "烧录: $filename"
        ffmpeg -y -i "$file" -vf "subtitles=$subtitle" \
            -c:v libx264 -crf 23 -c:a copy \
            "$OUTPUT_DIR/$filename.mp4"
    else
        echo "未找到字幕: $filename"
    fi
done

echo "批量烧录完成"

字幕工具推荐

命令行工具

工具 说明 平台
SubtitleEdit 字幕编辑器 跨平台
Aegisub ASS 字幕编辑器 跨平台
srt SRT 处理工具 跨平台
ffmpeg 字幕处理 跨平台

Python 库

说明
pysrt SRT 处理库
ass ASS 处理库
srt SRT 处理库
webvtt-py WebVTT 处理库

注意事项

  1. 编码问题:字幕文件可能使用不同编码,注意转换为 UTF-8
  2. 格式兼容:不同容器对字幕格式的支持不同
  3. 字体依赖:ASS 字幕可能依赖特定字体,确保字体可用
  4. 时间同步:字幕时间需要与视频同步
  5. 画质影响:硬字幕会重新编码视频,可能影响画质

业务场景

场景 1:多语言视频制作

# 添加中英文字幕
ffmpeg -i input.mp4 -i sub_cn.srt -i sub_en.srt \
    -map 0:v -map 0:a -map 1 -map 2 \
    -c:v copy -c:a copy -c:s srt \
    -metadata:s:s:0 language=chi \
    -metadata:s:s:1 language=eng \
    -disposition:s:0 default \
    output.mkv

场景 2:视频翻译

# 提取原字幕
ffmpeg -i input.mkv -map 0:s:0 original.srt

# 翻译字幕(使用翻译工具)

# 添加翻译字幕
ffmpeg -i input.mkv -i translated.srt \
    -map 0 -map 1 \
    -c copy -c:s srt \
    -metadata:s:s:1 language=chi \
    output.mkv

场景 3:字幕烧录分享

# 烧录字幕并压缩
ffmpeg -i input.mkv -vf "subtitles=input.mkv:si=0:force_style='FontSize=20,PrimaryColour=&H00FFFFFF'" \
    -c:v libx264 -crf 23 -preset medium \
    -c:a aac -b:a 128k \
    output.mp4

扩展阅读

  1. ASS 字幕规范
  2. SRT 格式规范
  3. WebVTT 规范
  4. FFmpeg 字幕滤镜
  5. FFmpeg 字幕选项

总结

本章介绍了 FFmpeg 的字幕处理功能,包括:

  • 字幕格式概览
  • 软字幕与硬字幕
  • 字幕提取与烧录
  • 字幕样式定制
  • 多字幕处理

掌握字幕处理技术可以帮助您制作多语言视频、翻译字幕和分享视频内容。