【问题标题】:How can I extract audio from video with ffmpeg?如何使用 ffmpeg 从视频中提取音频?
【发布时间】:2012-04-12 08:54:31
【问题描述】:

我尝试了以下命令从视频中提取音频:

ffmpeg -i Sample.avi -vn -ar 44100 -ac 2 -ab 192k -f mp3 Sample.mp3

但我得到以下输出

libavutil     50.15. 1 / 50.15. 1
libavcodec    52.72. 2 / 52.72. 2
libavformat   52.64. 2 / 52.64. 2
libavdevice   52. 2. 0 / 52. 2. 0
libavfilter    1.19. 0 /  1.19. 0
libswscale     0.11. 0 /  0.11. 0
libpostproc   51. 2. 0 / 51. 2. 0
SamplE.avi: Invalid data found when processing input

有人可以帮忙吗?

【问题讨论】:

    标签: ffmpeg video-processing audio-processing


    【解决方案1】:

    提取音频流而不重新编码:

    ffmpeg -i input-video.avi -vn -acodec copy output-audio.aac
    
    • -vn 没有视频。
    • -acodec copy 说使用已经存在的相同音频流。

    读取输出以查看它是什么编解码器,以设置正确的文件扩展名。

    【讨论】:

    • 而不是第一次运行 ffmpeg 来检查它是哪个音频流,而是使用 ffprobe input-video.avi
    • 如果只从视频流中提取音频,音频的长度可能会比视频的长度短。为确保不会发生这种情况,请使用对 ffmpeg 的相同调用提取音频和视频,例如"ffmpeg -i vid.avi -map 0:a audio.wav -map 0:v onlyvideo.avi
    • 用一个将原始 AAC 封装到 M4A 容器中的命令来扩展这个答案会很棒。
    • 在这种精确的情况下,只需将目标路径中的“.aac”替换为“.m4a”即可。 ffmpeg 足够聪明,可以猜测您的意图,并将结果封装到 M4A 容器中:)
    • FWIW,我制作了一个PHP脚本,所以我只指定输入视频文件,它会自动确定输出音频文件的扩展名:superuser.com/questions/1301901/…
    【解决方案2】:

    要从电影文件(例如 AVI、MP4、MOV 等)或音频文件(例如 WAV)中编码高质量的 MP3 或 MP4 音频,我发现最好使用 -q:a 0 来实现可变比特率,这很好练习指定-map a 排除视频/字幕,只抓取音频:

    ffmpeg -i sample.avi -q:a 0 -map a sample.mp3
    

    如果您想从视频中提取一部分音频,请使用-ss 选项指定起始时间戳,并使用-t 选项指定编码持续时间,例如从 3 分钟开始5 秒 45 秒:

    ffmpeg -i sample.avi -ss 00:03:05 -t 00:00:45.0 -q:a 0 -map a sample.mp3
    
    • 时间戳需要采用 HH:MM:SS.xxx 格式或以秒为单位。

    • 如果你不指定 -t 选项,它会走到最后。

    • 如果您想指定范围,例如 45 秒,您可以使用 -to 选项而不是 -t 选项:00:03:05 + 45 = 00:03:50

    工作示例:

    1. 下载ffmpeg
    2. 打开命令提示符(开始 > 运行 > CMD)或在 Mac/Linux 上打开终端
    3. cd(更改目录命令)到带有 ffmeg.exe 的目录,如图所示。
    4. 发出命令并等待输出文件(或解决任何错误)

    Windows

    Mac/Linux

    【讨论】:

    • 这里是-q:a 值的指南:trac.ffmpeg.org/wiki/Encode/MP3 零是最高质量的 VBR 设置,这通常会导致平均比特率处于正常 CBR 范围的上部(其中 320 kbit/ s 是最大值,可能有点超出无损压缩变得更合适的点)。
    • -map a 是做什么的?
    • 警告:这是使用有损压缩重新编码音频,这会稍微降低质量。如果原件已经被压缩,您将降低质量两次,这可能会或可能不会被注意到。
    • 这个命令对我有用,而上面带有-vn 的命令不起作用。
    • 重新编码不是提取,所以这不能回答问题。
    【解决方案3】:

    提取所有音轨/流

    这会将所有音频放入一个文件中:

    ffmpeg -i input.mov -map 0:a -c copy output.mov
    
    • -map 0:a 仅选择所有音频流。视频和字幕将被排除在外。
    • -c copy 启用 stream copy 模式。这会复制音频并且不会对其进行重新编码。如果您想重新编码音频,请移除 -c copy
    • 选择支持您的音频格式的输出格式。见comparison of container formats

    提取特定的音轨/流

    提取音频流#4的示例:

    ffmpeg -i input.mkv -map 0:a:3 -c copy output.m4a
    
    • -map 0:a:3 仅选择音频流 #4(ffmpeg 从 0 开始计数)。
    • -c copy 启用 stream copy 模式。这会复制音频并且不会对其进行重新编码。如果您想重新编码音频,请移除 -c copy
    • 选择支持您的音频格式的输出格式。见comparison of container formats

    提取并重新编码音频/更改格式

    与上面的示例类似,但没有-c copy。各种例子:

    ffmpeg -i input.mp4 -map 0:a output.mp3
    ffmpeg -i input.mkv -map 0:a output.m4a
    ffmpeg -i input.avi -map 0:a -c:a aac output.mka
    ffmpeg -i input.mp4 output.wav
    

    单独提取所有音频流

    本例中的这个输入有 4 个音频流。每个音频流都将作为单个文件输出。

    ffmpeg -i input.mov -map 0:a:0 output0.wav -map 0:a:1 output1.wav -map 0:a:2 output2.wav -map 0:a:3 output3.wav
    

    可选择在每个输出文件名前添加-c copy 以启用stream copy 模式。


    提取某个频道

    使用channelsplit filter。从立体声输入获取右前 (FR) 通道的示例:

    ffmpeg -i stereo.wav -filter_complex "[0:a]channelsplit=channel_layout=stereo:channels=FR[right]" -map "[right]" front_right.wav
    
    • channel_layout 是输入的通道布局。它不会自动检测到,因此您必须提供布局名称。
    • channels 列出了您要提取的频道。
    • 有关音频通道布局名称(对于 channel_layout)和通道名称(对于 channels),请参见 ffmpeg -layouts
    • 过滤时不能使用stream copy模式(-c copy),所以必须对音频进行重新编码。
    • 有关更多示例,请参阅 FFmpeg Wiki: Audio Channels

    -map-vn 有什么区别?

    ffmpeg 具有默认的 stream selection 行为,它将为每种流类型选择 1 个流(1 个视频、1 个音频、1 个字幕、1 个数据)。

    -vn 是一个旧的遗留选项。它从默认流选择行为中排除视频。因此音频、字幕和数据仍会自动选择,除非使用 -an-sn-dn 告知不要这样做。

    -map 更复杂但更灵活和有用。 -map 禁用默认流选择行为,ffmpeg 将仅包含您使用 -map 选项告诉它的内容。 -map 也可用于排除某些流或流类型。例如,-map 0 -map -0:v 将包括所有流除了所有视频。

    更多示例请参见FFmpeg Wiki: Map


    错误

    无效的音频流。只需要一个 MP3 音频流。

    MP3 仅支持 1 个音频流。该错误意味着您试图将超过 1 个音频流放入 MP3。这也可能意味着您正在尝试将非 MP3 音频放入 MP3。

    WAVE 文件只有一个流

    与上面类似。

    在流 #0 中找不到编解码器的标记,容器当前不支持编解码器

    您正在尝试将音频格式放入不支持它的输出中,例如将 PCM (WAV) 放入 MP4。

    移除-c copy,选择不同的输出格式(更改文件扩展名),或者手动选择编码器(如-c:a aac)。

    comparison of container formats

    Could not write header for output file #0 (incorrect codec parameters ?): Invalid argument

    这是一个无用的通用错误。实际的、信息丰富的错误应紧接在此通用错误消息之前。

    【讨论】:

      【解决方案4】:

      似乎您正在从视频文件中提取音频并缩混为立体声通道。
      仅提取音频(无需重新编码):

      ffmpeg.exe -i in.mp4 -vn -c:a copy out.m4a
      

      提取音频和downmix to stereo(无需重新编码):

      ffmpeg.exe -i in.mp4 -vn -c:a copy -ac 2 out.m4a
      

      要生成 mp3 文件,您需要重新编码音频:

      ffmpeg.exe -i in.mp4 -vn -ac 2 out.mp3
      

      【讨论】:

      • 如果不重新编码,您将无法缩混(或进行任何其他更改)。
      • 这只会提取第一个音轨。我怎样才能提取第二个? (或全部,以分隔文件?)
      【解决方案5】:

      命令行正确且适用于有效的视频文件。我会确保您已安装正确的库以使用 mp3,安装 lame o probe 与另一个音频编解码器。

      通常

      ffmpeg -formats
      

      ffmpeg -codecs
      

      会提供足够的信息,以便您了解更多。

      【讨论】:

        【解决方案6】:

        ffmpeg -i sample.avi 将为您提供文件的音频/视频格式信息。确保您配置了正确的库来解析输入流。另外,请确保文件没有损坏。

        【讨论】:

        • 现在,当我用 .mkv vedio 尝试相同的评论时,我得到了正确的结果。为什么它不适用于 .avi,是否有任何 ffmpeg 命令可以转换 .avi
        • AVI 或 MKV 是指可以容纳许多不同音频/视频格式的容器格式。您不是要转换 AVI 音频,而是要转换 AVI 文件中的音轨,但您尚未指定。使用我上面列出的命令来查看 AVI 文件中的音轨类型。如果是 MP3,你需要用 MP3 库编译 FFMPEG,比如 LAME lame.sourceforge.net
        【解决方案7】:

        要编码 mp3 音频ffmpeg.org 显示以下示例:

        ffmpeg -i input.wav -codec:a libmp3lame -qscale:a 2 output.mp3
        

        我只是通过将input.wav 替换为视频文件名来从视频中提取音频。 2 表示 190 kb/秒。您可以在我上面的链接中查看其他质量级别。

        【讨论】:

        • 该示例用于将音频文件转换为不同的格式,而不是从视频中提取它。
        • @IulianOnofrei,正如我在回答中所描述的,您可以将音频文件替换为视频文件。它对我有用。
        【解决方案8】:

        对于寻找从视频文件中提取音频同时保留原始视频文件参数的更简单方法的人,您可以使用:

        ffmpeg -i <video_file_name.extension> <audio_file_name.extension>
        

        例如,运行:

        ffmpeg -i screencap.mov screencap.mp3
        

        mov 视频文件中提取mp3 音频文件。

        【讨论】:

        • 简单有效。为什么所有其他解决方案都如此复杂? +1
        • 问题是,为什么会有删除投票?!
        • 没错,这对我每次都有效。为什么还不是最佳答案?
        • @SMBiggs:因为这会重新编码音频,失去质量。
        • @DanDascalescu 不知道——感谢您指出这一点!
        【解决方案9】:

        这是我刚刚使用的:

        ffmpeg -i my.mkv -map 0:3 -vn -b:a 320k my.mp3
        

        选项说明:

        • my.mkv 是一个源视频文件,您也可以使用其他格式
        • -map 0:3 表示我想要视频文件中的第三个流。把你的 N 放在那里——视频文件通常有多个音频流;您可以省略它或使用-map 0:a 来获取默认音频流。运行ffprobe my.mkv,查看视频文件有哪些流。
        • my.mp3 是一个目标音频文件名,ffmpeg 发现我想要一个 MP3 从它的扩展名。在我的情况下,源音频流是 ac3 DTS,只是复制不是我想要的
        • 320k 是所需的目标比特率
        • -vn 表示我不希望目标文件中有视频

        【讨论】:

          【解决方案10】:

          从多个视频剪辑创建有声读物

          1. 首先,从一堆 h264 文件中提取音频(作为 `.m4a):
          for f in *.mp4; do ffmpeg -i "$f" -vn -c:a copy "$(basename "$f" .mp4).m4a"; done
          

          -vn 输出选项禁用视频输出(自动选择或映射任何视频流)。对于full manual control,请参阅-map 选项。

          可选

          1. 如果有一段介绍,比如 40 秒,您可以使用 -ss 参数跳过它:
          for f in *.m4a; do ffmpeg -i "$f" -ss 00:00:40  -c copy crop/"$f"; done
          
          1. 将所有文件合并为一个:
          ffmpeg -f concat -safe 0 -i <(for f in ./*.m4a; do echo "file '$PWD/$f'"; done) -c copy output.m4a
          

          【讨论】:

            【解决方案11】:

            如果打包成 avi 的音频一开始不是 mp3 格式,您可能需要指定 -acodec mp3 作为附加参数。或者无论你的 mp3 编解码器是什么(在 Linux 系统上它可能是 -acodec libmp3lame)。您也可以通过指定-f mp3 将格式“强制”为mp3 来获得与平台无关的相同效果,尽管并非所有版本的ffmpeg 仍支持该开关。您的里程可能会有所不同。

            【讨论】:

              【解决方案12】:

              要在不进行转换的情况下提取,我使用上下文菜单条目 - 作为 Linux 中的文件管理器自定义操作 - 运行以下命令(在检查视频包含的音频类型之后;包含 ogg 音频的视频示例):

              bash -c 'ffmpeg -i "$0" -map 0:a -c:a copy "${0%%.*}".ogg' %f 
              

              它基于 ffmpeg 命令ffmpeg -i INPUT -map 0:a -c:a copy OUTPUT

              我使用-map 0:1 没有问题,但是,正如@LordNeckbeard 在评论中所说,“流0:1 不能保证总是音频。使用-map 0:a 而不是-map 0:1将避免歧义。”

              【讨论】:

              • @LordNeckbeard ~ 我会考虑到这一点,谢谢。
              • 我使用mediainfo 来确定音轨,并像这样选择它:-map 0:a:1 其中a:1 是第二个音轨索引,谢谢! -c:a copy 让它更快!
              【解决方案13】:

              使用-b:a 而不是-ab 因为-ab 现在已经过时了,还要确保你的输入文件路径是正确的。

              为了从视频中提取音频,我使用了下面的命令并且工作正常。

              String[] complexCommand = {"-y", "-i", inputFileAbsolutePath, "-vn", "-ar", "44100", "-ac", "2", "-b:a", "256k", "-f", "mp3", outputFileAbsolutePath};
              

              这里,

              • -y - 无需询问即可覆盖输出文件。
              • -i - FFmpeg 从-i 选项指定的任意数量的输入“文件”中读取
              • -vn - 禁用视频录制
              • -ar - 设置音频流的采样率(如果已编码)
              • -ac - 设置音频通道数。
              • -b:a - 设置音频比特率
              • -f - 格式

              查看this,了解我在 GitHub 上的完整示例 FFmpeg android 项目。

              【讨论】:

                猜你喜欢
                • 2015-08-25
                • 1970-01-01
                • 2023-02-07
                • 2018-05-09
                • 2021-02-26
                • 1970-01-01
                • 2015-12-31
                • 2021-12-17
                相关资源
                最近更新 更多