FFmpeg 不复制所有音频流

Posted

技术标签:

【中文标题】FFmpeg 不复制所有音频流【英文标题】:FFmpeg not copying all audio streams 【发布时间】:2016-10-15 15:53:51 【问题描述】:

我无法让 ffmpeg 从 .mp4 文件中复制所有音频流。经过数小时的在线搜索,这似乎应该复制所有流(as shown in example 4 here):

ffmpeg -i in.mp4 -map 0 -c copy out.mp4

in.mp4 包含 3 个流:

视频 音轨 1 音轨 2

out.mp4(应与in.mp4 相同)仅包含 2 个流:

视频 音轨 1

FFmpeg 似乎可以正确识别所有 3 个流,但不会将它们全部复制过来。 FFmpeg 的输出:

Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #0:1 -> #0:1 (copy)
  Stream #0:2 -> #0:2 (copy)

编辑:来自ffmpeg -v 9 -loglevel 99 -i in.mp4的输出:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from in.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf57.36.100
  Duration: 00:00:06.03, start: 0.000000, bitrate: 5582 kb/s
    Stream #0:0(und), 1, 1/15360: Video: h264 (Main), 1 reference frame (avc1 /
0x31637661), yuv420p(tv, bt470bg/unknown/unknown, left), 1920x1080 (0x0) [SAR 1:
1 DAR 16:9], 0/1, 5317 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(und), 1, 1/48000: Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz,
 stereo, fltp, 128 kb/s (default)
    Metadata:
      handler_name    : SoundHandler
    Stream #0:2(und), 1, 1/48000: Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz,
 stereo, fltp, 128 kb/s
    Metadata:
      handler_name    : SoundHandler
Successfully opened the file.
At least one output file must be specified
[AVIOContext @ 0000000001c2b9e0] Statistics: 153350 bytes read, 2 seeks

编辑 2(已解决):我设法从 this ticket 中找到了正确的语法。对于任何其他感兴趣的人,正确的语法是:

ffmpeg -i in.mp4 -vcodec copy -c:a copy -map 0 out.mp4

这将复制所有流。

【问题讨论】:

你使用的是哪个版本的ffmpeg,在什么平台上?根据ffmpeg.org/bugreports.html 上的“错误报告”页面,ffmpeg -v 9 -loglevel 99 -i in.mp4 的输出会有所帮助。 我添加了来自ffmpeg -v 9 -loglevel 99 -i 的输出。平台是 Windows。 FFmpeg 版本为git-0a9e781 (2016-06-10) 相关文档:trac.ffmpeg.org/wiki/Map#Example4 【参考方案1】:

好的,我深入阅读了 ffmpeg 手册页,发现这应该很有用:

请注意,目前每个输出流只能包含来自 单个输入流;例如,您不能使用“-map_channel” 选择不同流中包含的多个输入音频通道 (来自相同或不同的文件)并将它们合并到单个输出中 溪流。因此,例如,目前不可能转向 两个单独的单声道流变成一个立体声流。然而 将立体声流分成两个单声道单声道流是 可能。

如果您需要此功能,可能的解决方法是使用 amerge 筛选。例如,如果您需要合并一个媒体(此处为 input.mkv) 将 2 个单声道音频流合并为一个立体声声道音频流 (并保留视频流),您可以使用以下命令:

ffmpeg -i input.mkv -filter_complex "[0:1] [0:2] amerge" -c:a pcm_s16le -c:v copy output.mkv

您可能需要通读并尝试使用 man ffmpeg-filters 上的手册页说明,以了解您在命名通道和预期输出方面的复杂程度。

[编辑:正如 Mulvya 所指出的,这回答了一个问题,但它并不是原始发帖人的问题。]

【讨论】:

太好了,我会做一些实验。谢谢。 我设法从this ticket 中找到了正确的语法。对于任何其他感兴趣的人,正确的语法是:ffmpeg -i in.mp4 -vcodec copy -c:a copy -map 0:0 -map 0:1 -map 0:2 out.mp4,这将复制所有 3 个流。 这个答案与OP的查询无关。他们想要复制曲目,而不是合并或拆分它们。正如stream mapping 代码所示,OP 的原始命令应该可以工作。为什么它没有但单独的流编解码器语法却是一个谜。 OP 可以共享原始复制命令的控制台输出吗?【参考方案2】:

显然这是一个受欢迎的问题,所以我将我的解决方案作为答案发布(以前是评论回复),以便其他人可以看到。

我设法从这个ticket 中找到了正确的语法。正确的语法是:

ffmpeg -i in.mp4 -vcodec copy -c:a copy -map 0:0 -map 0:1 -map 0:2 out.mp4

这将复制所有 3 个流。

【讨论】:

我给 +1 答案,但修改它会很有帮助:从输入文件中选择所有视频和第三个音频流:ffmpeg -i INPUT -map 0:v - map 0:a:2 OUTPUT 所有音频流都一样,可以记为 0:a【参考方案3】:

FFmpeg 有将所有流映射到输出的选项,您必须使用选项-map 0 将所有流从输入映射到输出。

在完整的行中,它可能看起来像:

ffmpeg -i in.mp4 -c copy -map 0 out.mp4

有关详细信息,请参阅有关 stream selection 和 -map 选项的文档。

【讨论】:

这非常有帮助。您有兴趣添加完整的命令以使其更容易吗? ffmpeg -i IN.mp4 -c copy -map 0:? OUT.mp4 对于像-i in0.mp4 -i in1.aac这样的多个来源,需要添加-map 0 -map 1来复用所有输入流。 您可以将-map 0:? 替换为-map 0 有没有办法做到这一点但忽略潜艇?我正在尝试 -ss 剪辑视频,如果潜艇不是某种格式,它们会抛出错误。理想情况下,我只想将 subs 转换为可用的格式并保留它们。【参考方案4】:

首先我在这里尝试了这个更广泛的答案:https://***.com/a/54616353/1422630

但是我遇到了不支持的字幕轨道问题,所以我不得不使用这个命令:

avconv -i INFILE -c copy -map 0:a -map 0:v OUTFILE

我知道,在我要求复制之后,它基本上只复制了我映射的内容(当然它还映射了所有音频),因为我根本不关心嵌入的字幕.如果您想映射字幕,只需添加此-map 0:s

【讨论】:

【参考方案5】:

似乎特定的 ffmpeg 版本忽略了-c copy 选项并跳过音频流复制,从而导致最终文件没有音频,例如不会复制音轨并产生没有声音的视频。

受影响的 ffmpeg 例如用于 Synology Disk Station 设备:

ffmpeg version 2.7.7 Copyright (c) 2000-2015 the FFmpeg developers
  built with gcc 4.9.3 (crosstool-NG 1.20.0) 20150311 (prerelease)

为了解决这个问题,无需分析文件结构并使用 -map 0:1 -map 0:2 等手动映射所有音频流,我找到了非常简单的命令来自动处理它:

ffmpeg -i INFILE -map 0 -c copy -c:a copy OUTFILE

这与-c:v -c:a 不同,因为它保留了章节和字幕以及视频和所有不同语言的音轨,如英语、西班牙语、法语、俄语或中文。

另外,如果您有更多几乎没有损坏的文件,而简单的副本无法修复,请尝试使用此命令,这可能会修复更多错误,这可能会导致视频播放器崩溃,或卡住视频或音频:

ffmpeg -err_detect ignore_err -i INFILE -map 0 -c copy -c:a copy OUTFILE

【讨论】:

以上是关于FFmpeg 不复制所有音频流的主要内容,如果未能解决你的问题,请参考以下文章

ffmpeg命令: 删除视频中不需要的音频流

带有水印和音频的 FFmpeg 连接“过滤器图描述中的流说明符不匹配任何流”。

FFmpeg总结用ffmpeg进行转格式,Android下播放网络音频流

使用多个音频流ffmpeg时不能使用-shortest参数

FFMpeg SDK使用4调用FFmpeg SDK解析封装格式的视频为音频流和视频流

FFMpeg;混合两个音频流时出错