前一篇的简单命令假设输入只有一条视频和一条音频。真实文件可能有多条音轨、字幕或封面图,这时要把“选哪条流”和“选后怎么处理”分开看:

flowchart LR
I0[输入 0<br/>视频 / 多条音频 / 字幕] --> P[ffprobe<br/>index · type · language]
I1[输入 1<br/>旁白或 Logo] --> P
P --> S[-map<br/>选择流]
S --> T[当前输出流集合]
T --> C[-c:v / -c:a<br/>copy 或编码]
C --> M[Muxer<br/>目标容器]
M --> O[一个输出文件]

图中顺序就是写命令时的配置顺序:先探测事实,再用 -map 选择,最后用 -c、滤镜和目标容器决定如何处理。-map 不会自动把视频转成 H.264,-c 也不会替你选择另一条音轨。

-map 选择输入流
-c 决定选中的流复制还是编码

先查看再选择

Terminal window
ffprobe -v error -show_entries "stream=index,codec_type,codec_name:stream_tags=language,title" -of json input.mkv

可能看到:

Stream #0:0 video h264
Stream #0:1 audio aac language=chi
Stream #0:2 audio aac language=eng
Stream #0:3 subtitle ass language=chi

编号来自当前输入,不能根据文件后缀或经验猜测。

不写 -map:自动选择

Terminal window
ffmpeg -i input.mkv output.mp4

没有 -map 时,FFmpeg 会按照输出格式允许的类型自动选择输入流。对常见文件,通常得到一条视频和一条音频,而不是输入中的全部轨道;具体选择规则和版本相关,见官方 Stream selection 文档。

自动选择适合“输出结构不重要”的临时任务。要保留指定语言、全部音轨、字幕或封面,就应该显式写出 -map

最基本的 -map

选择第 0 个输入的第一条视频和第一条音频:

Terminal window
ffmpeg -i input.mkv -map 0:v:0 -map 0:a:0 -c copy output.mkv

常用写法:

写法含义
0第 0 个输入的全部流
0:v第 0 个输入的全部视频流
0:a第 0 个输入的全部音频流
0:v:0第 0 个输入匹配到的第一条视频流
0:a:1第 0 个输入匹配到的第二条音频流
0:s:0第 0 个输入匹配到的第一条字幕流
0:2第 0 个输入中全局索引为 2 的流

0:a:1 的最后一个数字是“音频类型内序号”,和 0:2 的全局索引不是一个概念。

不存在时是否失败

普通映射要求流必须存在:

Terminal window
ffmpeg -i silent.mp4 -map 0:v:0 -map 0:a:0 -c copy output.mp4

如果输入没有音频,这条命令会失败。末尾加 ? 可以把它设为可选:

Terminal window
ffmpeg -i silent.mp4 -map 0:v:0 -map 0:a:0? -c copy output.mp4

可选映射适合输入结构不一致的批处理,但也可能把“本来应该有音频”的数据问题变成静默成功。是否忽略缺失流应由任务规格决定。

选择全部或排除部分流

保留输入中的全部流:

Terminal window
ffmpeg -i input.mkv -map 0 -c copy output.mkv

全部选择后排除字幕:

Terminal window
ffmpeg -i input.mkv -map 0 -map -0:s -c copy output.mkv

排除第二条音频:

Terminal window
ffmpeg -i input.mkv -map 0 -map -0:a:1 -c copy output.mkv

目标容器不一定支持输入中的附件、数据或字幕;-map 0 失败时,应按目标容器的能力重新选择,而不是盲目重试。

只输出音频或视频

-vn-an-sn 分别禁止视频、音频和字幕输出:

Terminal window
ffmpeg -i input.mkv -map 0:a:0 -vn -c:a aac -b:a 192k audio.m4a
ffmpeg -i input.mkv -map 0:v:0 -an -c:v libx264 video.mp4

显式 -map 已经能排除未选择的类型;-vn/-an 更多是把输出意图写清楚。

按语言标签选择

语言是元数据,不是所有文件都有,也不保证使用同一代码。官方支持按元数据匹配:

Terminal window
ffmpeg -i input.mkv -map 0:m:language:eng -c copy english.mkv

这条写法会选择语言标签为 eng 的匹配流;按语言匹配本身不替代媒体类型筛选。如果同一语言同时有音频和字幕,先用 ffprobe 查看结果,再用 0:a:10:s:0 这样的索引写出明确规格:

Terminal window
ffmpeg -i input.mkv -map 0:v:0 -map 0:a:1 -map 0:s:0? -c copy selected.mkv

? 适合直接跟在普通流选择后表示“没有该流也继续”;不要把它拼到未经验证的复杂元数据选择表达式中。语言标签缺失或使用 chizhozh 等不同值时,应以探测结果为准。

两个输入合成一个输出

视频来自输入 0,旁白来自输入 1:

Terminal window
ffmpeg -i video.mp4 -i narration.wav -map 0:v:0 -map 1:a:0 -c:v copy -c:a aac -b:a 192k -shortest output.mp4

输入编号按 -i 出现顺序从 0 开始。-shortest 在最短的输出流结束时停止,不会自动修复两个输入的起点延迟或音画同步。

一个输出对应一组映射

同一条命令生成视频文件和音频文件时,每个输出都要重新声明自己的映射和编码:

Terminal window
ffmpeg -i input.mkv -map 0:v:0 -c:v libx264 -an video.mp4 -map 0:a:0 -c:a aac -vn audio.m4a

第一个输出的 -map-c-vn 不会自动延续到第二个输出;输出文件是参数作用域的边界,第 05 篇会解释这一点。

选择和处理不要混淆

Terminal window
ffmpeg -i input.mkv -map 0:v:0 -map 0:a:1 -c:v libx264 -c:a copy output.mkv

这条命令先选择第一条视频和第二条音频,再分别决定视频重编码、音频复制。-c:v libx264 不会改变已经选择的流,也不会自动选择另一条视频。

本篇之后

如果需要把选中的画面送进 scaleoverlay 或多个滤镜分支,先保持 -map 关系清楚,再看第 05 篇的滤镜和参数作用域。若输出仍缺轨道,回到 ffprobe 检查实际 index、类型和语言标签。

依据:FFmpeg Stream selection 官方文档FFmpeg -map 选项