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

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

容器格式与字幕兼容性

容器SRTASSWebVTTVobSubPGS
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字幕编辑器跨平台
AegisubASS 字幕编辑器跨平台
srtSRT 处理工具跨平台
ffmpeg字幕处理跨平台

Python 库

说明
pysrtSRT 处理库
assASS 处理库
srtSRT 处理库
webvtt-pyWebVTT 处理库

注意事项

  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 的字幕处理功能,包括:

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

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