使用avconv批量提取音频而无需转码


14

我大约有70个mp4文件,我想直接提取音频文件而无需进一步进行转码。所有的mp4文件都有aac音频文件。

我了解我可以使用以下命令从mp4文件之一提取音频文件:

avconv -i "INPUT FILE" -map 0:1 -c:a copy "OUTPUT FILE"

如何从所有70个mp4文件中提取所有音频文件,所以最终得到70个aac文件?

Answers:


21

您可以使用简单的for循环:

for i in *.mp4; do
    avconv -i "${i}" -map 0:1 -c:a copy "${i%.mp4}.aac"
done

或一行:

for i in *.mp4; do avconv -i "${i}" -map 0:1 -c:a copy "${i%.mp4}.aac"; done

avconv对每个命名*.mp4文件(文件名存储在${i}变量中的位置)运行一次。

${i%.mp4}意味着${i}(即文件名).mp4从结尾处剥离。


2
IIRC,原始aac文件不能包含元数据;如果要保留原始文件中的元数据,请使用m4a(这是mp4的另一个名称,但在音频播放器中已被广泛认可)而不是aac作为文件扩展名。
evilsoup

-map选项有什么用?为什么选择0:1流而不是其他流,例如0:0、0:2?
QED

我删除了-map选项,效果很好
2013年

以便在Thunar自定义操作和类似操作中使用此命令,如果将其添加到脚本和Thunar操作中,则可以使用:bash /path/to/the/script %F-像这里

2
@qed:-map如果切换到其他输出格式(如果该格式可以同时包含音频和视频),则丢弃仍可能会导致视频被视为视频。保持原样更安全。
博士 Sybren

5

如果您将所有文件都放在一个目录中,则肖的答案通常是最有用的。但是,如果MP4文件分散在不同目录中,则可以使用此find命令将它们全部转换。

find . -type f -name '*.mp4' -exec bash -c 'avconv -i "$0" -c:a copy "${0/%mp4/m4a}"' {} \;

这在末尾使用了稍稍不同的bash字符串替换形式:“ $ {0 /%mp4 / m4a}”告诉bash用m4a替换mp4,但前提是mp4在字符串的末尾。


我从来不知道bash有这种替代类型。太棒了:)
安德鲁·甘纳森

1
@xiao如果省略%,它将替换它找到的字符串的第一个实例;您还可以使用#使其仅在变量开头的字符串来代替;因此$ {0 / mp4 / m4a}将用m4a替换mp4的第一个实例(如果您的文件名确实很奇怪,可能会出现问题);$ {0 /#mp4 / m4a}和$ {0 /#mp4 / m4a}会将mp4替换为m4a,但前提是变量的字符串值以mp4开头(显然在这里没有用,但在其他地方可能会派上用场)。
evilsoup

3

为避免同时处理多个文件(可能会使用太多资源),请使用parallel。默认情况下,它一次只执行一项工作。如果要并行使用多个CPU内核,请尝试并行parallel -j 4 ...执行4个作业。还检查一下man parallel

sudo apt-get install parallel

此行aac将从选定的视频中提取音频文件,并将其放入m4a容器中。

parallel avconv -i '{}' -map 0:1 -c:a copy '{.}.m4a' ::: %F

直接在CLI中工作时%F,请用输入文件列表代替。例如*.mp4

灵感来自这个答案,前面的回答这个问题,并通过evilsoup “后者(话说的评论:”原始的AAC文件不能包含元数据;如果你想保留元数据从原来的文件,然后使用M4A(其只是mp4的另一个名称,但在音频播放器中已得到相当广泛的认可),而不是aac作为文件扩展名')。

我在Thunar自定义操作中使用了此类命令,

在此处输入图片说明

将应用程序限制为包含aac音频的视频。

在此处输入图片说明

要在处理过程中打开一个终端窗口,并在最后关闭,可以像下面这样更改命令:

 gnome-terminal -e "parallel avconv -i '{}' -map 0:1 -c:a copy '{.}.m4a' ::: %F"

2

我扩展了@ Xiao-Long Chen的答案,将其转换为一个脚本,该脚本在输出文件较新时会跳过文件:

#!/bin/bash

for file in *.mp4; do
    OUT="${file/.mp4/.m4a}"

    if [ "$file" == "$OUT" ]; then
        echo "Unable to handle $file" >&2
        exit 1
    fi

    if [ "$OUT" -nt "$file" ]; then
        echo "Skipping $file; output file is newer."
        continue
    fi

    echo "Converting \"$file\" -> \"$OUT\""
    avconv -loglevel warning -i "$file" -map 0:1 -c:a copy "$OUT"
done
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.