mcpField
F
ffmpeg-media-finishing

ffmpeg-media-finishing

github.com/calesthio创意与媒体219172 次安装15 周前更新
代码仓库

关于 ffmpeg-media-finishing

FFmpeg media finishing 是面向媒体交付阶段的技能,供制作人员将生成或剪辑后的音视频整理为可复现、符合规格且带审计记录的文件。它要求先探测输入、依据交付要求选择处理方式,再检查输出。

主要功能

  1. 01使用 ffprobe 审计媒体输入与输出
  2. 02通过规格检查验证常见媒体参数
  3. 03按需选择封装复制、转码或滤镜
  4. 04记录命令、版本、校验和及已知风险

适用场景

  1. 01检查来源媒体是否满足交付规格
  2. 02为不同分辨率或画幅制作交付版本
  3. 03核验转码输出的编码、帧率与音频参数
  4. 04整理带审计记录的媒体交接

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/calesthio/generative-media-skills --skill ffmpeg-media-finishing

安装后在 Claude Code 中输入/ffmpeg-media-finishing确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

EVAL.md
scripts/
media_probe.py
tests/
test_media_probe.py

详细介绍

FFmpeg 媒体成片处理

在成片处理阶段使用此技能:创意生成或编辑完成并产出源媒体后、将交付内容交给用户前。你的任务是将脆弱且不一致的媒体输出,转换为可复现、符合规格并带有审计记录的文件。

此技能独立于服务提供方。它假设本地已提供 ffmpeg 和 ffprobe,但不假设已安装的构建版本编译了所有编解码器、滤镜、硬件编码器或字幕渲染器。FFmpeg 构建能力、编码器名称、平台上传规则和社交平台规格都可能变化;请在制作时使用下方命令并参照当前交付规格重新核实。

操作规则

不要猜测媒体的状态。先探测,再决定,执行确定性命令,然后探测输出。

每次成片交付都应包含:

  • 来自 ffprobe 的输入审计摘要;
  • 选定的交付规格及任何尚未解决的假设;
  • 运行过的确切命令,包括 FFmpeg 版本和构建信息;
  • 输出审计摘要;
  • 校验和,以及适用时的帧哈希;
  • 已知风险,例如字幕重新编码、色彩元数据含糊不清、削波、有损转码或平台特有的不确定性。

附带的确定性辅助工具

此技能包含一个确定性的 Python 3.11+ 标准库辅助脚本 scripts/media_probe.py。在需要可重复的技术审计,或需要在成片处理前后快速检查交付规格时使用。它仅提供辅助,不能替代感知评估、色彩管理审批、音频试听、字幕/无障碍审查、版权审查或平台/客户端签核。

已记录事实,核实于 2026-07-11:ffprobe 的设计用途是收集多媒体流信息,并可使用 -show_format、-show_streams 和 -print_format json 输出 JSON;如果无法打开或识别输入文件,它会返回正数退出代码。该辅助脚本使用 subprocess argv 列表调用 ffprobe,不通过 shell 执行,也不会运行 ffmpeg 或修改媒体。

调用方式:

python skills/production/runtime-assembly/ffmpeg-media-finishing/scripts/media_probe.py input.mp4 --pretty
python skills/production/runtime-assembly/ffmpeg-media-finishing/scripts/media_probe.py input.mp4 --expect expected.json --pretty

选项:

  • media:必填,要检查的媒体路径;文件仅由 ffprobe 打开。
  • --expect expected.json:可选的预期规格。退出代码 0 表示审计已运行且所有预期均通过;退出代码 1 表示审计已运行,但有一项或多项预期未通过。
  • --ffprobe PATH_OR_NAME:覆盖 ffprobe 可执行文件。默认使用 PATH 中的 ffprobe。
  • --timeout SECONDS:ffprobe 超时时间。默认值为 30。
  • --pretty:输出采用两空格缩进的 JSON,而非紧凑格式。

退出代码:

0  audit completed and expectations passed, or no expectations were provided
1  audit completed but at least one expectation failed
2  usage or input-file error
3  ffprobe executable unavailable
4  ffprobe returned a non-zero exit code
5  ffprobe timed out
6  ffprobe output was not valid or usable JSON
7  expectation JSON could not be read, parsed, or validated

标准化审计架构,版本 1.0:

{
  "schema_version": "1.0",
  "status": "pass",
  "tool": "media_probe.py",
  "ffprobe": {
    "executable": "ffprobe",
    "argv": ["ffprobe", "-v", "error", "-show_format", "-show_streams", "-print_format", "json", "input.mp4"]
  },
  "media": {
    "path": "input.mp4",
    "format_name": "mov,mp4,m4a,3gp,3g2,mj2",
    "format_long_name": "QuickTime / MOV",
    "duration_seconds": 1.0,
    "size_bytes": 12345,
    "bit_rate": 98765
  },
  "streams": {
    "counts": {"video": 1, "audio": 1, "subtitle": 0, "other": 0},
    "video": {
      "index": 0,
      "codec_name": "h264",
      "profile": "High",
      "width": 1920,
      "height": 1080,
      "pix_fmt": "yuv420p",
      "r_frame_rate": {"raw": "30/1", "value": 30.0},
      "avg_frame_rate": {"raw": "30/1", "value": 30.0},
      "duration_seconds": 1.0
    },
    "audio": {
      "index": 1,
      "codec_name": "aac",
      "sample_rate": 48000,
      "channels": 2,
      "channel_layout": "stereo",
      "sample_fmt": "fltp",
      "duration_seconds": 1.0
    }
  },
  "expectations": null
}

如果不存在视频流或音频流,其标准化值为 null,相应计数为 0。未知数值会输出为 null,不会凭空编造。

预期架构:

{
  "checks": [
    {"field": "media.duration_seconds", "op": "tolerance", "value": {"value": 10.0, "tolerance": 0.05}},
    {"field": "streams.video.codec_name", "op": "equals", "value": "h264"},
    {"field": "streams.video.width", "op": "equals", "value": 1920},
    {"field": "streams.video.height", "op": "equals", "value": 1080},
    {"field": "streams.video.avg_frame_rate.value", "op": "tolerance", "value": {"value": 30.0, "tolerance": 0.01}},
    {"field": "streams.video.pix_fmt", "op": "equals", "value": "yuv420p"},
    {"field": "streams.audio.codec_name", "op": "equals", "value": "aac"},
    {"field": "streams.audio.sample_rate", "op": "equals", "value": 48000},
    {"field": "streams.audio.channels", "op": "equals", "value": 2}
  ]
}

支持的 op 值:

  • equals:精确匹配 JSON。
  • in:实际值必须是预期数组中的某个值。
  • range:数值型实际值必须在 {"min": number, "max": number} 范围内;可省略任一边界。
  • tolerance:数值型实际值必须在 value +/- tolerance 范围内。

预期文件中的格式错误数值、非有限数值和负容差值均属于使用错误。辅助脚本会将其报告为退出代码 7,并输出结构化错误 JSON,而不会将其视为媒体检查未通过。

字段是指向标准化报告的点分路径。支持的预期检查目标有意覆盖常见的成片处理检查项:时长容差、视频编解码器、宽度、高度、帧率、像素格式、音频编解码器、采样率和声道数。该架构也可以定位上文列出的任何稳定字段,但不要将此辅助脚本视为感知质量、色彩正确性、响度合规性或版权状态的证明。

1. 预检工具链和输入

记录 FFmpeg 的构建版本以及编码器/滤镜的可用性,因为实际行为取决于已安装的二进制文件、编译标志和外部库。

ffmpeg -hide_banner -version
ffmpeg -hide_banner -encoders
ffmpeg -hide_banner -muxers
ffmpeg -hide_banner -filters
ffmpeg -hide_banner -h encoder=libx264
ffmpeg -hide_banner -h filter=loudnorm

对每个源文件运行 ffprobe;如果任务有多个输入、客户端规格,或存在参数不匹配的风险,请保存机器可读的 JSON:

ffprobe -v error \
  -show_format -show_streams -show_chapters \
  -print_format json input.mp4 > input.ffprobe.json

如需简明的人工审核记录:

ffprobe -v error \
  -select_streams v:0 \
  -show_entries stream=codec_name,profile,width,height,pix_fmt,r_frame_rate,avg_frame_rate,time_base,field_order,color_range,color_space,color_transfer,color_primaries,sample_aspect_ratio,display_aspect_ratio,duration,nb_frames \
  -of default=noprint_wrappers=1 input.mp4

ffprobe -v error \
  -select_streams a:0 \
  -show_entries stream=codec_name,sample_rate,channels,channel_layout,sample_fmt,bits_per_sample,duration,bit_rate \
  -of default=noprint_wrappers=1 input.mp4

至少审核以下内容:

  • 容器、时长、文件大小、时码/章节需求;
  • 视频编解码器、分辨率、显示宽高比、样本宽高比、像素格式、位深、Alpha、隔行扫描、标称和平均帧率、时间基、开始时间;
  • 色彩元数据:范围、基色、传递特性、矩阵/色彩空间;
  • 音频编解码器、采样率、声道数/布局、时长、位深/采样格式,以及所需的响度目标;
  • 字幕流和外部字幕;
  • MKV/ASS 工作流中的字体等附件;
  • 拼接或流复制前,输入是否具有相同参数。

如果 ffprobe 报告元数据缺失或不一致,请将其视为警告,而不是自行编造数值的许可。请询问用户,或仅在必要时根据创作流程谨慎推断,并记录推断结果。

2. 选择流复制、转码或滤镜

如果已编码的流符合要求,且只需进行容器级操作,则使用流复制:

ffmpeg -y -i input.mov -map 0 -c copy -movflags +faststart output.mp4

流复制适用于重新封装、在关键帧边界裁剪、添加兼容的元数据或提取轨道。如果需要更改分辨率、编解码器、像素格式、通过重采样改变帧率、响度、烧录字幕、叠加、色彩转换,或生成任何滤镜图输出,则不适用。FFmpeg 文档说明,-codec copy 可复制流而无需重新编码;滤镜则需要解码帧,因此必须重新编码。

如果交付内容需要不同的编解码器/容器、分辨率、帧率、像素格式、音频布局、响度、烧录字幕、叠加或兼容性配置文件,则进行转码。

注重质量时,除非平台或客户端规格要求限制比特率,否则优先选择恒定质量设置,而不是随意指定比特率。使用 libx264 编码 H.264 时,一种常见的中间母版转交付格式做法是:

ffmpeg -y -i input.mov \
  -map 0:v:0 -map 0:a? \
  -c:v libx264 -preset slow -crf 18 -pix_fmt yuv420p \
  -c:a aac -b:a 192k -ar 48000 \
  -movflags +faststart output.mp4

生产经验法则:CRF 越低,质量越高、文件越大;CRF 越高,文件越小。请进行视觉检查;CRF 数值不代表交付保证。如果客户端给出了目标比特率、最大比特率、GOP 长度、配置文件、色度或级别要求,请遵循规格,而不是采用此经验法则。

3. 容器、编解码器和兼容性

区分容器和编解码器:

  • MP4/MOV/MKV/WebM 是容器。
  • H.264/H.265/AV1/ProRes/DNxHR/AAC/Opus/PCM 是编解码器。
  • 某个流可能兼容一种容器,但不兼容另一种。

常见的交付选择:

  • 广泛兼容的网页/社交平台格式:MP4,采用 H.264 视频和 AAC 音频,通常使用 yuv420p。
  • 保留透明度或 Alpha 通道的中间格式:MOV 中的 ProRes 4444、PNG 序列;仅当目标支持且已安装的构建版本能够编码时,才使用带 Alpha 通道的 WebM VP9/AV1。
  • 归档或审核用中间母版:ProRes/DNxHR/PCM 或客户端指定的其他中间母版;未经批准,不要替换为 H.264。
  • WebM:通常采用 VP9/AV1/Opus,或根据目标兼容性采用 VP8/Vorbis。
  • 纯音频:用于交换时采用 WAV/PCM;用于紧凑交付时,根据平台规格采用 AAC/MP3/Opus。

使用编解码器前,请检查本地构建版本:

ffmpeg -hide_banner -encoders | findstr /i "264 265 av1 prores aac opus"

在非 Windows shell 中,使用 grep -Ei 替代 findstr。

h264_nvenc、hevc_videotoolbox、h264_qsv 或 h264_amf 等硬件编码器取决于机器和驱动程序。它们速度可能很快,但码率控制行为和质量可能有所不同。不要假设它们可用;请先测试一段短样本。

4. 缩放、裁剪、填充和宽高比

请有意选择几何处理方式:

  • 画布内缩放并填充边缘,适用于必须保留完整画面的情况。
  • 裁剪后填满画布,适用于可以舍弃边缘内容的情况。
  • 仅当可以接受画面变形,或源画面的宽高比与目标一致时,才精确缩放。
  • 对大多数 Web/社交媒体成品,将样例宽高比标准化为方形像素。

缩放以适配 1920x1080,并用黑色填充:

ffmpeg -y -i input.mp4 \
  -vf "scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,setsar=1" \
  -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p \
  -c:a copy output_1080p_letterbox.mp4

裁剪以填满 1080x1920 的竖屏画面:

ffmpeg -y -i input.mp4 \
  -vf "scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920,setsar=1" \
  -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p \
  -c:a aac -b:a 192k output_9x16.mp4

生成静帧时,对于要求色度二次采样的编解码器,请使用偶数尺寸:

ffmpeg -y -loop 1 -framerate 30 -t 5 -i still.png \
  -vf "scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,setsar=1,format=yuv420p" \
  -c:v libx264 -crf 18 -preset slow -an still_card.mp4

5. 帧率、时间戳、时基和同步

帧率变更是造成卡顿、漂移、重复帧和字幕错乱的常见原因。请检查 r_frame_rate 和 avg_frame_rate;可变帧率源的标称帧率往往容易引起混淆。

规则:

  • 除非交付规格要求转换,否则请保留源帧率。
  • 不要随意转换 23.976/24/25/30/50/60 fps;转换可能引入节奏瑕疵。
  • 对社交媒体版本,仅当平台/客户端规格、编辑时间线或 concat 要求时,才选择单一恒定帧率。
  • 使用流复制剪辑时,除非重新编码,否则应预期剪辑会对齐到关键帧。
  • 使用 fps、trim、setpts、atrim 或 asetpts 等滤镜时,请重新编码经过滤镜处理的流。

为平台专用版本强制使用恒定 30 fps:

ffmpeg -y -i input.mp4 \
  -vf "fps=30,scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920,setsar=1" \
  -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p \
  -c:a aac -b:a 192k -ar 48000 output_30fps_vertical.mp4

通过重新编码进行精确剪辑:

ffmpeg -y -ss 12.345 -to 27.890 -i input.mp4 \
  -map 0:v:0 -map 0:a? \
  -c:v libx264 -crf 18 -preset slow \
  -c:a aac -b:a 192k clip_exact.mp4

通过流复制快速进行关键帧对齐剪辑:

ffmpeg -y -ss 12 -to 28 -i input.mp4 -map 0 -c copy clip_fast.mp4

如果处理完成后音频和视频时长不一致,请检查起始时间、PTS/DTS 警告,以及滤镜图是否丢弃或重复了帧。除非规格要求,否则不要用随意填充音频的方式掩盖同步问题。

6. 色彩范围和色彩空间注意事项

FFmpeg 可以设置或转换色彩元数据,但元数据不等于正确的色彩转换。生成的素材通常缺少可靠的色彩标签。全范围/有限范围、Rec.709/Rec.2020 原色、传递函数或 HDR/SDR 假设不匹配,都可能导致导出画面褪色或暗部细节丢失。

最低限度的做法:

  1. 探查源文件的色彩标签。
  2. 如果源素材是在已知工作空间中生成或合成的,请在后期处理说明中记录相关信息。
  3. 对普通 SDR Web 交付,通常以 Rec.709 元数据和 yuv420p 为目标,除非客户端规格另有要求。
  4. 如果要转换 HDR、广色域、Log 素材,或处理对客户至关重要的品牌色,请升级至色彩管理工作流,或由人工审核色彩。
  5. 设置标签后,重新探查输出文件,并在已知可靠的播放器上进行视觉检查。

为 SDR H.264 交付添加标签,但不声称进行了色彩转换的示例:

ffmpeg -y -i input.mp4 \
  -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p \
  -color_primaries bt709 -color_trc bt709 -colorspace bt709 -color_range tv \
  -c:a aac -b:a 192k output_sdr_tagged.mp4

如果必须在矩阵/范围之间进行转换,请先检查已安装滤镜的选项并使用测试帧验证,然后再使用 zscale 或 colorspace 等色彩滤镜。不要仅使用元数据标志来完成转换。

7. 音频响度、采样率和声道布局

按照交付规格完成音频。如果没有规格:

  • 对于网络/社交视频,48 kHz AAC 立体声具有广泛兼容性。
  • 对于广播、客户或广告交付,请遵循准确的响度标准和容差。
  • 对于归档/交换用途,请保留 PCM/WAV,或按要求交付独立分轨。

准确使用标准术语:

  • ITU-R BS.1770 定义了响度和真峰值测量算法。
  • EBU R 128 是一项广播建议,基于响度标准化和真峰值限制。
  • 平台响度目标各不相同且经常变化;请重新查阅平台文档,不要依赖记忆。

先测量:

ffmpeg -hide_banner -i input.mp4 \
  -af loudnorm=I=-16:TP=-1.5:LRA=11:print_format=json \
  -f null -

如需可重复的响度标准化,请使用两遍 loudnorm:先测量,再将测量值输入第二遍。示例目标是常见的在线视频经验值,并非标准:

ffmpeg -hide_banner -i input.mp4 \
  -af loudnorm=I=-16:TP=-1.5:LRA=11:print_format=json \
  -f null -

ffmpeg -y -i input.mp4 \
  -af "loudnorm=I=-16:TP=-1.5:LRA=11:measured_I=-18.7:measured_TP=-3.2:measured_LRA=8.4:measured_thresh=-29.1:offset=0.2:linear=true:print_format=summary,aformat=sample_rates=48000:channel_layouts=stereo" \
  -c:v copy -c:a aac -b:a 192k output_loudnorm.mp4

如果要保留影院混音、音乐动态、分轨、空间音频或客户批准的母版,请勿盲目标准化。将 5.1/7.1/Atmos/空间音频下混为立体声前,请先询问。

下混示例。先检查探测到的声道布局,并相应调整声道名称;有些 5.1 源会将侧声道标记为 SL/SR,而非后置声道 BL/BR。

ffmpeg -y -i input.mov \
  -map 0:v:0 -map 0:a:0 \
  -c:v copy \
  -af "pan=stereo|FL=0.707*FC+FL+0.707*BL+0.5*LFE|FR=0.707*FC+FR+0.707*BR+0.5*LFE,aformat=sample_rates=48000:channel_layouts=stereo" \
  -c:a aac -b:a 192k output_stereo.mp4

通过试听检查下混结果。公式化的下混系数只是起点,不能替代实际试听。

8. 字幕:内嵌与外挂

应将字幕处理作为交付决策,而不是事后才考虑。

当无障碍访问、可搜索性、用户控制、本地化或平台原生字幕很重要时,请使用外挂字幕。常见外挂字幕格式包括 SRT 和 WebVTT;具体支持哪些格式由目标平台决定。

当平台不支持字幕轨道、用户要求开放式字幕,或短视频的可读性是首要考虑时,请内嵌字幕。内嵌字幕会成为像素:无法关闭、搜索或通过辅助技术重新设置样式,也无法在不重新渲染的情况下更正。

WCAG 指南将字幕视为与语音及必要非语音音频同步的文本。当无障碍访问或客户合规性很重要时,未经审核的自动生成字幕不能视为最终版本。

当容器/播放器支持时,将兼容的 SRT 外挂字幕添加为字幕流:

ffmpeg -y -i input.mp4 -i captions.srt \
  -map 0:v -map 0:a? -map 1:0 \
  -c:v copy -c:a copy -c:s mov_text \
  -metadata:s:s:0 language=eng output_with_captions.mp4

使用基于 libass 的渲染方式内嵌 SRT 字幕:

ffmpeg -y -i input.mp4 \
  -vf "subtitles=captions.srt:force_style='Fontname=Arial,Fontsize=42,Outline=2,Shadow=1,MarginV=80'" \
  -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p \
  -c:a copy output_burned_captions.mp4

使用 subtitles 前,请确认 FFmpeg 构建包含该滤镜和 libass 支持:

ffmpeg -hide_banner -filters | findstr /i subtitles

字幕 QA:

  • 在所有剪辑和变速处理完成后,根据最终音频确认时间轴;
  • 在需要时添加有意义的说话者标识和非语音音频说明;
  • 确保字幕行在目标宽高比下易于阅读;
  • 测试平台 UI 覆盖层的安全区域;
  • 编码/内嵌后检查特殊字符和非拉丁文字;
  • 当用户同时需要无障碍访问和社交媒体可读性时,交付外挂字幕和内嵌字幕版本。

9. 图像序列、静帧和生成帧

生成的图像序列在 AI 工作流中很常见。编码前应统一编号、帧率、像素格式和 Alpha 处理方式。

编码带编号的 PNG 序列:

ffmpeg -y -framerate 24 -start_number 1 -i "frames/frame_%05d.png" \
  -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p output_from_sequence.mp4

保留 Alpha 以便合成检查:

ffmpeg -y -framerate 24 -i "frames/frame_%05d.png" \
  -c:v prores_ks -profile:v 4444 -pix_fmt yuva444p10le output_alpha.mov

提取帧以供 QA:

ffmpeg -y -i output.mp4 -vf "fps=1,scale=320:-1" "qa/thumb_%04d.jpg"

如果序列存在缺帧、编号重复、尺寸不一、色彩配置文件混用或 Alpha 不一致,请停止编码并先修复序列。

10. GIF 和社交媒体预览导出

GIF 通常适用于预览,但处理照片内容或长内容时效率不高。除非明确要求 GIF,否则实际交付优先使用 MP4/WebM。

使用调色板以提升 GIF 质量:

ffmpeg -y -ss 0 -t 4 -i input.mp4 \
  -vf "fps=12,scale=640:-1:flags=lanczos,palettegen" palette.png

ffmpeg -y -ss 0 -t 4 -i input.mp4 -i palette.png \
  -lavfi "fps=12,scale=640:-1:flags=lanczos[x];[x][1:v]paletteuse=dither=bayer:bayer_scale=5" \
  preview.gif

从母版快速制作社交媒体版本,但最终交付前请重新核对当前平台规则:

# 16:9 landscape
ffmpeg -y -i master.mov \
  -vf "scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,setsar=1" \
  -c:v libx264 -crf 20 -preset medium -pix_fmt yuv420p \
  -c:a aac -b:a 192k -movflags +faststart deliverable_16x9.mp4

# 9:16 vertical
ffmpeg -y -i master.mov \
  -vf "scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920,setsar=1" \
  -c:v libx264 -crf 20 -preset medium -pix_fmt yuv420p \
  -c:a aac -b:a 192k -movflags +faststart deliverable_9x16.mp4

# 1:1 square
ffmpeg -y -i master.mov \
  -vf "scale=1080:1080:force_original_aspect_ratio=increase,crop=1080:1080,setsar=1" \
  -c:v libx264 -crf 20 -preset medium -pix_fmt yuv420p \
  -c:a aac -b:a 192k -movflags +faststart deliverable_1x1.mp4

社交媒体和广告规格会发生变化。应将当前平台文档、客户媒体计划和广告管理器要求视为必须遵守的要求;此处示例仅供参考。

11. 拼接、修剪、片头片尾、叠加和水印

仅当输入在编解码器、时间基准、分辨率、像素格式、帧率、采样率和声道布局方面兼容时,才使用流复制进行拼接。否则,应先对每个片段进行标准化,或使用 concat 滤镜并重新编码。

使用 concat 解复用器拼接兼容片段:

file 'clip01.mp4'
file 'clip02.mp4'
file 'clip03.mp4'
ffmpeg -y -f concat -safe 0 -i concat_list.txt -c copy joined.mp4

先标准化,再拼接:

ffmpeg -y -i clip01.mov -vf "scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,fps=30,setsar=1,format=yuv420p" -af "aformat=sample_rates=48000:channel_layouts=stereo" -c:v libx264 -crf 18 -preset slow -c:a aac -b:a 192k norm01.mp4

叠加水印:

ffmpeg -y -i input.mp4 -i logo.png \
  -filter_complex "[1:v]scale=180:-1[logo];[0:v][logo]overlay=W-w-40:H-h-40:format=auto" \
  -c:v libx264 -crf 18 -preset slow -pix_fmt yuv420p \
  -c:a copy output_watermarked.mp4

从图像添加片头片尾,同时通过在节目音频前拼接明确的静音片段来保持音画同步:

ffmpeg -y -loop 1 -t 3 -i slate.png -i program.mp4 -f lavfi -t 3 -i anullsrc=r=48000:cl=stereo \
  -filter_complex "[0:v]scale=1920:1080,setsar=1,fps=30,format=yuv420p[v0];[1:v]scale=1920:1080,setsar=1,fps=30,format=yuv420p[v1];[2:a]aformat=sample_rates=48000:channel_layouts=stereo[a0];[1:a]aformat=sample_rates=48000:channel_layouts=stereo[a1];[v0][a0][v1][a1]concat=n=2:v=1:a=1[v][a]" \
  -map "[v]" -map "[a]" \
  -c:v libx264 -crf 18 -preset slow -c:a aac -b:a 192k output_with_slate.mp4

如果节目没有音频,请使用仅包含视频的拼接(concat=n=2:v=1:a=0),并省略音频映射。除非有意设置偏移,否则不要在前置片头片尾的情况下直接映射节目音频。

12. 批量变体与可复现性

批量处理时采用由清单驱动的模式。记录输入路径、输出路径、所需规格、确切命令、FFmpeg 版本、源文件哈希、输出文件哈希和 QA 状态。避免为数十个变体手写一次性命令。

清单字段示例:

{
  "job_id": "campaign-final-2026-07-11",
  "ffmpeg_version": "record from ffmpeg -version",
  "source": "master.mov",
  "source_sha256": "computed before processing",
  "deliverables": [
    {
      "name": "youtube_16x9",
      "output": "deliverable_16x9.mp4",
      "spec": "MP4 H.264 AAC 1920x1080 SDR",
      "command": "exact command string",
      "output_sha256": "computed after processing",
      "qa": "pass with noted warnings"
    }
  ]
}

使用 SHA-256 生成文件完整性清单:

certutil -hashfile output.mp4 SHA256

在 macOS/Linux 上:

shasum -a 256 output.mp4

验证解码后的帧是否等效或检测意外媒体更改时,使用 FFmpeg 帧哈希:

ffmpeg -v error -i output.mp4 -f framehash output.framehash
ffmpeg -v error -i output.mp4 -f framemd5 output.framemd5

元数据发生变化时,文件校验和也会变化。某些容器元数据发生变化时,帧哈希可能保持稳定;但经过有损重新编码、缩放、音频标准化或像素/采样格式转换后,帧哈希会变化。

13. 最终 QA 检查清单

运行自动化检查:

ffmpeg -v error -i output.mp4 -f null -
ffprobe -v error -show_format -show_streams -print_format json output.mp4 > output.ffprobe.json

检查:

  • 至少能在一个目标播放器中打开并播放输出文件;
  • 时长与预期相符,误差在容差范围内;
  • 在开头、中间和结尾处,音画同步正常;
  • 没有意外的丢帧/重复帧警告;
  • 分辨率、宽高比、帧率、像素格式、编解码器、配置文件、级别、比特率/文件大小符合规格;
  • 音频采样率、声道布局、响度和真峰值符合规格;
  • 字幕同步、易读、准确,并按要求编码或烧录;
  • 叠加元素和水印位置正确,且不会被平台 UI 遮挡;
  • 色彩标签符合预期交付要求,且视觉检查结果可接受;
  • 元数据未泄露不需要的私有路径、模型提示词或客户端信息;
  • 已生成校验和/清单;
  • 文件名确定且适用于目标平台。

对于重要交付物,应抽查帧,而不要仅凭命令执行成功就认定无误:

ffmpeg -y -i output.mp4 -vf "select='eq(n,0)+eq(n,300)+eq(n,600)',scale=480:-1" -vsync vfr "qa_sample_%03d.jpg"

需要升级处理的情况

遇到以下情况时,请暂停并请求批准或专家审核:

  • 客户规格与源媒体或平台限制冲突;
  • 出现法律、版权、水印、徽标、音乐许可、字幕合规性、无障碍合规性或广告政策相关问题;
  • 交付要求涉及 HDR、广色域、广播、影院、环绕声/空间音频或色彩关键场景;
  • 平台规格不可用、受限,或自项目简报以来已有变更;
  • 生成内容包含私人数据、尚未发布的产品信息或来源不明的第三方标记;
  • FFmpeg 缺少所需的编码器/滤镜,而替代方案会影响质量、成本或兼容性;
  • 对经客户批准的母版而言,有损转码不可避免;
  • 对合规敏感的发布内容,字幕准确性尚未经过人工审核。

避免提供法律建议。应说明制作风险,并根据情况建议由客户、法律顾问、平台方或无障碍专家进行审核。

完整示例

示例:为生成的 9:16 社交视频添加字幕并完成制作

意图:使用 AI 视频母版和审核通过的字幕,制作竖屏短视频。

输入:

  • master.mov:生成的 16:9 或混合宽高比视频,带音频;
  • captions.srt:审核通过的字幕文件;
  • 目标:1080x1920 MP4、H.264/AAC,并为社交信息流烧录字幕。

工作流:

ffmpeg -hide_banner -version > ffmpeg_version.txt
ffprobe -v error -show_format -show_streams -print_format json master.mov > master.ffprobe.json

ffmpeg -y -i master.mov \
  -vf "scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920,setsar=1,subtitles=captions.srt:force_style='Fontname=Arial,Fontsize=44,Outline=2,Shadow=1,MarginV=110',format=yuv420p" \
  -af "loudnorm=I=-16:TP=-1.5:LRA=11,aformat=sample_rates=48000:channel_layouts=stereo" \
  -c:v libx264 -crf 20 -preset slow \
  -c:a aac -b:a 192k -movflags +faststart \
  final_9x16_burned.mp4

ffmpeg -v error -i final_9x16_burned.mp4 -f null -
ffprobe -v error -show_format -show_streams -print_format json final_9x16_burned.mp4 > final_9x16_burned.ffprobe.json
certutil -hashfile final_9x16_burned.mp4 SHA256

这样安排的原因:

  • 明确指定缩放和裁剪,以适配竖屏交付;
  • 将字幕烧录到视频中,因为许多社交平台的观看场景默认用户会快速静音观看;
  • 音频按适用于在线视频的启发式标准进行响度标准化,而非广播标准;
  • 对输出重新探测并计算哈希值。

可能的故障模式:

  • 裁剪掉重要的视觉内容;
  • 缺少 libass,导致 subtitles 滤镜不可用;
  • 响度目标不符合客户端/平台规范;
  • 源文件中的色彩元数据仍不明确。
示例:封装已批准的母版,不更改已编码的流

意图:将已批准的 MOV 母版转换为 MP4 封装格式,以便上传审阅,而无需重新编码。

工作流:

ffprobe -v error -show_format -show_streams -print_format json approved_master.mov > approved_master.ffprobe.json

ffmpeg -y -i approved_master.mov \
  -map 0 -c copy -movflags +faststart review_upload.mp4

ffprobe -v error -show_format -show_streams -print_format json review_upload.mp4 > review_upload.ffprobe.json
certutil -hashfile approved_master.mov SHA256
certutil -hashfile review_upload.mp4 SHA256

决策说明:

  • 这会保留已编码的流;它不是会改变画质的渲染。
  • 只有当输入流符合 MP4 规范且目标平台接受这些流时,此操作才可行。
  • 由于容器发生变化,文件校验和也会不同;如有需要,可使用解码后的帧哈希来验证媒体内容。
示例:批量交付横屏、方形和竖屏版本

意图:从一个母版制作三个可复现的版本,同时保留清单记录。

工作流:

ffprobe -v error -show_format -show_streams -print_format json master.mov > master.ffprobe.json

ffmpeg -y -i master.mov \
  -vf "scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,setsar=1,format=yuv420p" \
  -c:v libx264 -crf 20 -preset medium -c:a aac -b:a 192k -movflags +faststart deliverable_16x9.mp4

ffmpeg -y -i master.mov \
  -vf "scale=1080:1080:force_original_aspect_ratio=increase,crop=1080:1080,setsar=1,format=yuv420p" \
  -c:v libx264 -crf 20 -preset medium -c:a aac -b:a 192k -movflags +faststart deliverable_1x1.mp4

ffmpeg -y -i master.mov \
  -vf "scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920,setsar=1,format=yuv420p" \
  -c:v libx264 -crf 20 -preset medium -c:a aac -b:a 192k -movflags +faststart deliverable_9x16.mp4

变体:

  • 对大型母版而言,使用单个多输出滤镜图可能更快,但分成三个独立命令更便于审计和调试。优先选择清晰可靠的输出,而非耍巧的一行命令。

来源与验证说明

本技能中的重要事实基于以下来源,核查日期为 2026-07-11:

评论

支持 Markdown