音视频处理的瑞士军刀有三把刃:转码、体检、播放。这一章从第一性原理出发,先搞清楚一个视频文件里到底装着什么,再亲手生成、体检、播放第一个视频——把 FFmpeg 的"全家桶"一次认全
核心方法论:第一性原理
「搞懂本质,一切工具都是表象。这一章我们不背参数,而是从最底层出发:一个 .mp4 文件里究竟装着什么?容器和编码是什么关系?ffmpeg、ffprobe、ffplay 各自在管哪一段?把这三件事亲手做过一遍,你以后再遇到转码失败、文件打不开、码率对不上,就都有了可以推理的起点。」
音视频处理为什么难?因为"一个视频文件"从来不是一个简单的东西。说人话:一个 .mp4 文件就像一只快递箱,箱子里至少装着两条"货"——一条视频流、一条音频流;每条流又用一种"压缩技术"(编码,codec,负责把画面和声音压缩成尽量小的字节)打过包。全世界的视频格式、音频格式、容器格式加起来有几百种,组合起来更是天文数字,手工处理根本不现实。于是有了 FFmpeg——目前全球使用最广的音视频处理工具集:Chrome、Firefox 的网页播放、VLC 播放器、OBS 录屏直播、YouTube 的视频处理流水线,背后都在用 FFmpeg 的库。
FFmpeg 有一段传奇历史。2000 年 12 月,法国程序员 Fabrice Bellard(费布里斯·贝拉尔)发起了这个项目,名字里的 "FF" 是 fast forward(快进)的缩写——合起来就是"快进 MPEG"。2004 年,Michael Niedermayer 加入并长期担任核心维护者。整个项目用 C 语言编写,以"库 + 命令行工具"的形式发布:libavcodec、libavformat 等库供其他软件嵌入使用,命令行工具供我们直接操作。本机安装的是 8.1.1 版本,先让它做个自我介绍:
# ffmpeg -version(本机真实输出,节选)
ffmpeg version 8.1.1 Copyright (c) 2000-2026 the FFmpeg developers
built with Apple clang version 21.0.0 (clang-2100.0.123.102)
configuration: --prefix=/opt/homebrew/Cellar/ffmpeg-full/8.1.1 --enable-shared ...
libavutil 60. 26.101 / 60. 26.101
libavcodec 62. 28.101 / 62. 28.101
libavformat 62. 12.101 / 62. 12.101
libavdevice 62. 3.101 / 62. 3.101
libavfilter 11. 14.101 / 11. 14.101
libswscale 9. 5.101 / 9. 5.101
libswresample 6. 3.101 / 6. 3.101
版本号下面那串 lib 版本列表值得多看一眼——FFmpeg 不是一个程序,而是一组库加三个命令行工具的集合。全家桶里我们日常打交道的工具就三个:ffmpeg 是转码引擎(把一种格式变成另一种,本章 1.3、1.4 节)、ffprobe 是媒体探针(只读不改,输出文件的"体检报告",1.5 节)、ffplay 是调试播放器(快速预览、逐帧检查,1.6 节)。三个工具同装同删,版本号永远一致:
# ffprobe / ffplay 的版本自报(本机真实输出,节选)
ffprobe version 8.1.1 Copyright (c) 2007-2026 the FFmpeg developers
built with Apple clang version 21.0.0 (clang-2100.0.123.102)
ffplay version 8.1.1 Copyright (c) 2003-2026 the FFmpeg developers
built with Apple clang version 21.0.0 (clang-2100.0.123.102)
| 工具 | 一句话定位 | 典型用途 | 本章出场 |
|---|---|---|---|
ffmpeg | 转码引擎 | 格式转换、裁剪、滤镜、截帧、推流 | 1.3 / 1.4 |
ffprobe | 媒体探针 | 读取容器、流、编码、时长、码率 | 1.5 |
ffplay | 调试播放器 | 快速预览输出文件、逐帧检查 | 1.6 |
装好 FFmpeg 后,第一件事就是跑 ffmpeg -version 确认可用(macOS 用 brew install ffmpeg,Linux 用 apt install ffmpeg)。如果提示 command not found,先解决安装再往下走——本章所有命令都依赖这三个工具。
用第一性原理问一个问题:一个 .mp4 文件里,到底装着什么?答案分两层。第一层是容器(container,也叫封装格式):它决定"文件怎么把多条数据流装在一起、时间戳怎么对齐、元数据存在哪",相当于快递箱。第二层是编码(codec,编解码器):它决定"画面和声音怎么压缩成尽量小的字节",相当于货物本身。视频流和音频流各自用一套编码,互不相干——箱子可以装任何货物。
这正是新手第一大误区:扩展名不等于编码。.mp4 只是箱子,里面的视频既可以是 H.264,也可以是 H.265 甚至 AV1;.mkv 也不代表"比 mp4 更清晰",它只是更能装。判断"箱子里是什么货",正是 ffprobe 的本职工作(1.5 节)。而 FFmpeg 的价值,就是把"任意箱子 + 任意货物"统一处理。一条音视频数据要过几道关?答案是五道:
# 一条音视频数据的标准处理管线(FFmpeg 的看家本领,先混个脸熟)
输入文件 --解封装(demux)--> 压缩流 --解码(decode)--> 原始帧/采样
原始帧/采样 --滤镜(filter)--> 处理后的帧/采样 --编码(encode)--> 压缩流
压缩流 --封装(mux)--> 输出文件
@解封装=拆箱取货,解码=还原画面,滤镜=加工,编码=重新压缩,封装=装箱
解封装(demux)是把"箱子拆开取出压缩流",解码(decode)把压缩流还原成能看的原始帧,滤镜(filter)做加工(缩放、加水印、调色),编码(encode)把原始帧重新压缩,封装(mux)把压缩流"装箱成新文件"。ffmpeg 转码就是走完这条管线;ffprobe 只做最前面的"拆箱检查";ffplay 做"拆箱 + 解码 + 显示"。FFmpeg 支持的容器到底有多少?看看 ffmpeg -formats 的输出——D 表示支持解封装(demuxing),E 表示支持封装(muxing):
# ffmpeg -formats(本机真实输出,grep 过滤节选)
Formats:
D.. = Demuxing supported
.E. = Muxing supported
..d = Is a device
---
E matroska Matroska
D matroska,webm Matroska / WebM
DE mp3 MP3 (MPEG audio layer 3)
E mp4 MP4 (MPEG-4 Part 14)
DE wav WAV / WAVE (Waveform Audio)
注意 mp4 这一行只有 E(只能封装)——因为"读取 mp4"这个能力由一条组合条目承担:D mov,mp4,m4a,3gp,3g2,mj2 QuickTime / MOV。也就是说 QuickTime/MOV 家族共用一个解封装器,这种"一个条目管一族格式"的设计在 FFmpeg 里很常见。常见容器与编码的搭配关系,列成一张表:
| 容器 | 常见视频编码 | 常见音频编码 | 典型场景 |
|---|---|---|---|
| mp4 | h264 / h265 / av1 | aac / mp3 | 网页、手机、短视频 |
| mkv | 几乎任意(h264 / h265 / av1…) | 几乎任意(aac / opus / flac…) | 高清收藏、外挂字幕 |
| mov | h264 / prores | aac / pcm | 苹果生态、剪辑中间格式 |
| flv | h264 | aac / mp3 | 直播、老式网页播放器 |
| mpegts | h264 / h265 | aac / mp3 | 广播电视、直播切片 |
| mp3 / wav | —(纯音频) | mp3 / pcm | 音乐、音频编辑 |
注意:容器不等于编码。看到 .mp4 别默认里面是 H.264,看到 .mkv 别以为"一定更清晰"。扩展名只告诉你"箱子类型",不告诉你"货物"。真正的答案要用 ffprobe 读出来——从下一节开始,我们就用本机实测把这条管线走一遍。
ffmpeg 的命令行骨架一句话就能概括:ffmpeg [全局选项] -i 输入 ... 输出文件。所有处理都围绕"输入 → 输出"两个端点展开,中间的选项决定"怎么变"。第 2 章会正式上手转码,这一节先认识它最重要的"能力清单"——三个自检命令:-formats 看容器、-encoders 看编码器、-decoders 看解码器。
关键认知:每个 ffmpeg 二进制"会什么",由编译时打开的功能决定。1.1 节 -version 里那一长串 configuration 就是编译选项的现场记录:--enable-libx264 表示内置 H.264 软件编码器,--enable-ffplay 表示带了 ffplay,--enable-videotoolbox 表示支持苹果硬件加速。先看容器清单的开头(真实输出):
# ffmpeg -formats | head(本机真实输出,节选)
ffmpeg version 8.1.1 Copyright (c) 2000-2026 the FFmpeg developers
built with Apple clang version 21.0.0 (clang-2100.0.123.102)
...
Formats:
D.. = Demuxing supported
.E. = Muxing supported
..d = Is a device
---
D 3dostr 3DO STR
E 3g2 3GP2 (3GPP2 file format)
E 3gp 3GP (3GPP file format)
D 4xm 4X Technologies
E a64 a64 - video for Commodore 64
连 3DO 游戏机、Commodore 64 这种远古平台的格式都在列表里——FFmpeg 的野心是"什么都能读"。接着看编码器:用 grep 过滤出我们最关心的 H.264 与 AAC 相关条目(真实输出):
# ffmpeg -encoders | grep -E 'aac|h264'(本机真实输出)
V....D libx264 libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (codec h264)
V....D libx264rgb libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 RGB (codec h264)
V....D h264_videotoolbox VideoToolbox H.264 Encoder (codec h264)
V....D h264_vulkan H.264/AVC (Vulkan) (codec h264)
A....D aac AAC (Advanced Audio Coding)
A..... aac_at aac (AudioToolbox) (codec aac)
每列的含义:第一列首字符 V/A/S 表示"视频 / 音频 / 字幕"类;名字列是编码器名字,也是之后 -c:v 选项要填的值;括号里 (codec h264) 是它对应的编码标准名。这一小段列表信息量很大:libx264 是纯软件编码器(CPU 干活),h264_videotoolbox 是苹果硬件编码器(GPU 干活),h264_vulkan 走 Vulkan 图形 API——同一编码标准,软硬两条路,这正是第 7 章 GPU 加速的伏笔。音频侧同理:aac 是内置软件编码器,aac_at 走 AudioToolbox。
# ffmpeg -decoders | head(本机真实输出,节选)
Decoders:
V..... = Video
A..... = Audio
S..... = Subtitle
.F.... = Frame-level multithreading
..S... = Slice-level multithreading
...X.. = Codec is experimental
....B. = Supports draw_horiz_band
.....D = Supports direct rendering method 1
------
V....D 012v Uncompressed 4:2:2 10-bit
V....D 4xm 4X Movie
V....D 8bps QuickTime 8BPS video
V....D aasc Autodesk RLE
V....D agm Amuse Graphics Movie
VF...D aic Apple Intermediate Codec
注意:你机器上的列表不等于别人的列表。FFmpeg 的能力由编译配置决定:官方精简二进制可能没有 libx264,某些发行版可能没带 ffplay。"为什么我的 ffmpeg 没有 xxx"——九成答案是"编译时没开"。查证的标准动作就是 -encoders / -decoders 各 grep 一遍。
判断"这台机器能不能编/解某格式",最快的方法不是查文档,而是 ffmpeg -encoders | grep 名字(编码)和 ffmpeg -decoders | grep 名字(解码)。它回答的是"我这台机器的真实能力",比任何网上教程都准。
学习转码首先得有素材。下载现成视频麻烦、体积大、版权不明,还不一定覆盖我们想要的参数组合。FFmpeg 早就想到了:它内置 lavfi 虚拟输入设备——一个"假摄像头 + 假麦克风",可以按需生成测试画面和测试音调。说人话:让 ffmpeg 自己画一张测试图、合成一段声音,直接喂进编码器。零下载、可复现、参数随便改。
下面这条命令生成一个 3 秒、320×240、15 帧/秒的测试视频:画面是 testsrc 测试图案(彩条 + 跳动的计时数字),声音是 440Hz 正弦波(标准音 A4),视频用 H.264 软件编码器 libx264,音频用 aac。本机真实执行成功:
# 生成测试视频(本机真实执行,产物 /tmp/hello_ffmpeg.mp4;-y 表示覆盖同名文件)
ffmpeg -y -f lavfi -i testsrc=duration=3:size=320x240:rate=15 -f lavfi -i sine=frequency=440:duration=3 -c:v libx264 -pix_fmt yuv420p -c:a aac /tmp/hello_ffmpeg.mp4
# 编码完成时的统计输出(本机真实输出,节选;方括号里的内存地址每次运行不同)
[libx264 @ 0x87d031180] kb/s:34.56
[aac @ 0x87d031180] Qavg: 609.750
# 产物信息(本机真实输出)
-rw-r--r-- 1 helios wheel 42953 Aug 8 15:12 /tmp/hello_ffmpeg.mp4
编码期间 libx264 会打印一大堆以 [libx264 @ 内存地址] 开头的统计行(帧类型分布、码率等),属于正常噪音,不用恐慌,最后一行 kb/s:34.56 就是视频流的平均码率。逐段拆解这条命令:-f lavfi 告诉 ffmpeg"下一个输入来自 lavfi 虚拟设备";-i testsrc=duration=3:size=320x240:rate=15 是第一个输入(画面),冒号分隔的三个参数分别是时长 3 秒、尺寸 320×240、帧率 15;-i sine=frequency=440:duration=3 是第二个输入(声音),正弦波频率 440Hz、时长 3 秒。-c:v libx264 指定视频编码器(c 是 codec,v 是 video),-pix_fmt yuv420p 指定像素格式,-c:a aac 指定音频编码器,最后是输出文件名。
为什么一定要写 -pix_fmt yuv420p?说人话:视频画面用 YUV 色彩模型表示——一个亮度分量 Y 加两个色度分量 U、V。yuv420p 表示色度按 2×2 降采样,是播放兼容性最好的像素格式。不指定时 libx264 可能输出 yuv444p(不降采样,画质更好但更占空间),部分老播放器、网页播放器就打不开了。"编码器默认值"和"播放兼容性"打架,是音视频日常第一坑,本章先埋个印象。
| 参数 | 含义 | 本命令取值 |
|---|---|---|
-f lavfi | 输入来自虚拟设备 | 视频、音频各用一次 |
-i testsrc=… | 测试图案输入(彩条 + 计时器) | duration=3:size=320x240:rate=15 |
-i sine=… | 正弦波音调输入 | frequency=440:duration=3 |
-c:v libx264 | 视频编码器 | libx264(H.264 软件编码) |
-pix_fmt yuv420p | 像素格式 | yuv420p(色度 4:2:0) |
-c:a aac | 音频编码器 | aac |
testsrc 只是 lavfi 测试图案家族的一员:testsrc2、smptebars、mandelbrot、color、gradients 都是现成的"假摄像头"。把 testsrc 换成 mandelbrot,就能生成一段分形动画当素材。想看某个滤镜支持哪些参数,运行 ffmpeg -h filter=testsrc(本机实测可用)。
注意:-y 表示"遇到覆盖询问直接选是",脚本里常用,但同名文件会被静默覆盖,别拿重要文件当输出名。另外"生成视频 / ffprobe 体检"完全不需要屏幕,无头服务器也能跑;但 ffplay 播放需要图形环境,1.6 节有绕法。
视频生成出来了,怎么确认它"真的对"?靠肉眼播放一遍太慢,靠猜更不行。ffprobe 就是为此而生的:一个只读探针,不修改文件,把容器、流、编码、时长、码率全部读出来,输出一份体检报告。说人话:给视频文件做一次 CT 扫描。以后遇到"ffmpeg 报错看不懂""文件打不开""码率对不上",第一步永远是 ffprobe。
直接对刚才生成的视频做体检(本机真实输出,全文):
# ffprobe /tmp/hello_ffmpeg.mp4(本机真实输出,全文)
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/tmp/hello_ffmpeg.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf62.12.101
Duration: 00:00:03.00, start: 0.000000, bitrate: 114 kb/s
Stream #0:0[0x1](und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(progressive), 320x240 [SAR 1:1 DAR 4:3], 36 kb/s, 15 fps, 15 tbr, 15360 tbn (default)
Metadata:
handler_name : VideoHandler
encoder : Lavc62.28.101 libx264
Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 69 kb/s (default)
Metadata:
handler_name : SoundHandler
逐行读报告。第一行 Input #0:容器格式是 mov,mp4,m4a,3gp,3g2,mj2 家族(就是 1.2 节那条组合条目,文件实际是 mp4);Duration 00:00:03.00 时长 3 秒,总码率 114 kb/s。Stream #0:0 是第一条视频流:编码 h264、档次 High(profile,编码特性的等级),像素格式 yuv420p,分辨率 320x240,帧率 15 fps,视频码率 36 kb/s——注意它标出了编码器 Lavc62.28.101 libx264,正是 1.4 节我们选的软件编码器。Stream #0:1 是音频流:编码 aac LC(Low Complexity,低复杂度档),采样率 44100 Hz(44.1kHz,CD 音质标准),单声道 mono,码率 69 kb/s。36 + 69 = 105 kb/s,加上容器开销后总码率 114 kb/s,对得上。
默认输出是给人看的;机器要消费,用 -show_streams / -show_format 配合 -of 指定输出格式。先看逐流详情(真实输出):
# ffprobe -v error -show_entries stream=codec_name,codec_type,width,height,r_frame_rate,sample_rate,channels /tmp/hello_ffmpeg.mp4
codec_name=h264
codec_type=video
width=320
height=240
r_frame_rate=15/1
codec_name=aac
codec_type=audio
sample_rate=44100
channels=1
r_frame_rate=0/0
-v error 把版本横幅等噪音全部关掉,只留结果;-show_entries 精确挑选字段。注意音频流没有"帧率"概念,r_frame_rate 显示 0/0 是正常占位,不是错误。再看容器级信息(真实输出):
# ffprobe -v error -show_format /tmp/hello_ffmpeg.mp4(本机真实输出)
[FORMAT]
filename=/tmp/hello_ffmpeg.mp4
nb_streams=2
format_name=mov,mp4,m4a,3gp,3g2,mj2
format_long_name=QuickTime / MOV
duration=3.000000
size=42953
bit_rate=114541
probe_score=100
nb_streams=2 表示两条流(视频 + 音频);duration=3.000000 时长 3 秒整;size=42953 与 ls -l 看到的一致;bit_rate=114541 就是 114 kb/s 的精确值;probe_score=100 是探测置信度,满分说明文件头信息完整——这份体检报告可以打"合格"。
# -of json:机器可读输出,脚本处理的首选(本机真实输出)
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name,width,height,r_frame_rate -of json /tmp/hello_ffmpeg.mp4
{
"programs": [
],
"stream_groups": [
],
"streams": [
{
"codec_name": "h264",
"width": 320,
"height": 240,
"r_frame_rate": "15/1"
}
]
}
| 选项 | 作用 |
|---|---|
-v error | 只输出结果/错误,关掉版本横幅等噪音 |
-show_streams | 逐条流输出编码、分辨率、帧率等详情 |
-show_format | 输出容器级信息(时长、码率、大小) |
-select_streams v:0 | 只处理第 0 条视频流(音频用 a:0) |
-show_entries … | 精确挑选要输出的字段 |
-of json / csv / xml | 改变输出格式,json 最适合脚本 |
ffprobe 是纯只读的,永远不修改文件。把它当成"音视频界的 file 命令":不确定一个媒体文件是什么,先 probe 一下再说话。第 3 章我们会专门把 ffprobe 的每一个字段讲透。
注意:-show_packets / -show_frames 会逐包、逐帧输出,数据量极大,别对完整片源直接跑。真要用,务必配合 -select_streams 限定流、-show_entries 限定字段,再用 head 截断观察。
转码的最终目的是"能看"。ffplay 是 FFmpeg 自带的极简播放器:基于 SDL 库 + FFmpeg 解码器,不追求产品级体验,但启动快、可脚本化、自带全套调试快捷键。说人话:它是"给开发者看的放映机"。日常追剧请用 VLC / IINA,但验证刚转出来的文件有没有问题,ffplay 一开就知道。
用法极简:ffplay 文件路径 即可弹出播放窗口。窗口里有一套常用快捷键:空格暂停、q 退出、左右方向键快退/快进 10 秒、上下键 1 分钟、f 全屏、m 静音、9/0 调音量、s 逐帧步进。无头服务器(没有显示器)也有绕法:-nodisp 不弹窗口、-autoexit 播完自动退出,两者配合就成了"解码冒烟测试"——退出码 0 表示文件能正常解码播放(本机真实执行):
# 无头环境验证:不弹窗口,解码完自动退出(本机真实执行,退出码 0)
ffplay -autoexit -nodisp -loglevel error /tmp/hello_ffmpeg.mp4
# (无任何输出 = 一切正常)
| 按键 | 作用 |
|---|---|
| q / ESC | 退出 |
| 空格 / p | 暂停 / 继续 |
| ← / → | 快退 / 快进 10 秒 |
| ↑ / ↓ | 快退 / 快进 1 分钟 |
| f | 全屏切换 |
| s | 逐帧步进模式 |
| m | 静音 |
| 9 / 0 | 音量减 / 加 |
说到硬件加速:4K、8K 视频用软件解码会吃掉大量 CPU,现代机器都有专门处理视频的硬件。FFmpeg 把"硬件加速能力"也列成了一张清单——ffmpeg -hwaccels(本机真实输出):
# ffmpeg -hwaccels(本机真实输出,节选)
Hardware acceleration methods:
videotoolbox
vulkan
macOS 上,videotoolbox 是苹果官方硬件编解码框架,vulkan 是跨平台 GPU 图形 API。对照 1.3 节的编码器列表,你会发现一个规律:同一编码标准,软件、硬件各有一个编码器——libx264 是 CPU 软编,h264_videotoolbox 是 GPU 硬编。在 NVIDIA 显卡的世界里,对应的是 h264_cuvid(硬解)和 h264_nvenc(硬编)。本站早年的 GPU 转码笔记里留了一条真实命令(CUDA 环境),先混个脸熟,第 7-8 章会完整拆解:
# NVIDIA GPU 转码示例(CUDA 环境,硬解 + 硬编 + GPU 缩放,来自本站旧笔记)
ffmpeg -hwaccel cuvid -c:v h264_cuvid -i video/video-H264-AAC.mkv -c:v h264_nvenc -b:v 2048k -vf scale_npp=1280:-1 -y /root/transcode.mp4
硬件解码不会自动生效:ffmpeg 只会自动选择 CPU 解码器。要用 GPU 解码,必须先用 ffprobe 识别输入视频的编码格式,再在命令行显式指定对应的 GPU 解码器(如 -hwaccel cuvid -c:v h264_cuvid)。这也是 ffprobe 与 ffmpeg 配合作战的第一个经典场景。
注意:ffplay 是调试工具,不是播放器产品。把它当 VLC 用会失望——没有播放列表、没有字幕设置、界面简陋。它的价值在"快"和"真":渲染的就是 FFmpeg 自己的解码结果,转码产物有没有问题一眼便知。
到这儿,全家桶三件套已经认全:ffmpeg 会转、ffprobe 会检、ffplay 会播,测试视频也能自己造了。下一章(第 2 章)我们就正式上手 ffmpeg 转码:-i / -c / -b / -vf 四大选项,把"输入 → 输出"这条管线真正驱动起来。
把三个工具与职责配对:① ffmpeg;② ffprobe;③ ffplay。候选描述:A. 只读探针,输出媒体的体检报告;B. 播放预览,快速验证转码产物;C. 转码引擎,完成格式与编码转换。
回顾 1.1 节的工具对照表:谁负责"变"、谁负责"读"、谁负责"播"?
① → C(ffmpeg 转码引擎);② → A(ffprobe 只读探针);③ → B(ffplay 播放预览)。记住口诀:ffmpeg 负责变,ffprobe 负责读,ffplay 负责看。
请说出下面这条命令每一段的含义:ffmpeg -y -f lavfi -i testsrc=duration=3:size=320x240:rate=15 -f lavfi -i sine=frequency=440:duration=3 -c:v libx264 -pix_fmt yuv420p -c:a aac /tmp/hello_ffmpeg.mp4
按顺序拆:两个 -f lavfi -i … 是输入,-c:v、-pix_fmt、-c:a 是输出侧编码设置,最后一个是输出文件。testsrc 和 sine 的参数用冒号分隔。
-y 覆盖同名文件;-f lavfi 声明输入来自虚拟设备;-i testsrc=duration=3:size=320x240:rate=15 是画面输入:测试图案,时长 3 秒、尺寸 320×240、帧率 15;-i sine=frequency=440:duration=3 是声音输入:440Hz 正弦波、时长 3 秒;-c:v libx264 视频用 H.264 软件编码器;-pix_fmt yuv420p 像素格式设为 4:2:0(兼容性最好);-c:a aac 音频用 AAC;最后 /tmp/hello_ffmpeg.mp4 是输出文件。
基于 1.5 节的真实 ffprobe 输出回答五个问题:① 容器格式是什么?② 时长和总码率是多少?③ 视频流的编码、分辨率、帧率、码率?④ 音频流的编码、采样率、声道数?⑤ 视频 36 kb/s + 音频 69 kb/s = 105 kb/s,为什么报告里的总码率是 114 kb/s?
总码率比两路码率之和略大,差出来的部分花在哪了?想想容器除了装流还要装什么。
① mov,mp4,m4a,3gp,3g2,mj2 家族(实际是 mp4,QuickTime/MOV 共用一个解封装器);② 3.00 秒,114 kb/s;③ h264(High 档次)、320×240、15 fps、36 kb/s;④ aac(LC 档)、44100 Hz、单声道;⑤ 105 kb/s 是两条流码率之和,差出来的约 9 kb/s 是容器开销——封装元数据(品牌信息、时间戳、流索引等)也要占码率,这正是 1.2 节"容器是箱子,箱子本身也有重量"的体现。
把 1.4 节的命令改造成:5 秒、640×360、30 帧/秒的测试视频(画面用 testsrc,声音用 440Hz 正弦波,编码仍为 libx264 + aac)。然后:① 用 ffprobe -v error -show_format 验证时长是 5.0 秒;② 用 ffplay -autoexit -nodisp -loglevel error 验证可播放(退出码 0);③ 运行 ffmpeg -formats | grep mp4,解释为什么 mp4 那一行只有 E 标志,而"读取 mp4"的能力由哪一行承担。
只需改 testsrc 的三个参数(duration、size、rate)和输出文件名;时长参数在视频、音频两个输入里都要改成 5。mp4 的 demux 能力在 1.2 节出现过。
命令:ffmpeg -y -f lavfi -i testsrc=duration=5:size=640x360:rate=30 -f lavfi -i sine=frequency=440:duration=5 -c:v libx264 -pix_fmt yuv420p -c:a aac /tmp/hello5.mp4。① -show_format 应输出 duration=5.000000;② 冒烟测试退出码应为 0;③ grep 输出是 E mp4 MP4 (MPEG-4 Part 14)——只有 E(muxing)没有 D,因为读取 mp4 由组合条目 D mov,mp4,m4a,3gp,3g2,mj2 QuickTime / MOV 承担(QuickTime/MOV 家族共用一个解封装器)。三关全过,你就完整走通了本章"生成 → 体检 → 播放"的闭环。