Пакетное извлечение аудио с помощью avconv без транскодирования


14

У меня есть около 70 файлов mp4, и я хочу извлечь аудиофайлы напрямую без дальнейшего перекодирования. Все файлы mp4 имеют аудио файлы aac.

Я понимаю, что могу использовать следующую команду для извлечения аудиофайла из одного из файлов mp4:

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

Как извлечь все аудиофайлы из всех файлов 70 mp4, чтобы я получил 70 файлов aac?

Ответы:


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, и она отлично работает
qed

чтобы использовать эту команду в пользовательских действиях 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 заменить mp4 на m4a, но только если mp4 находится в конце строки.


Я никогда не знал, что у bash есть такая замена. Круто :)
Эндрю Ганнерсон

1
@xiao Если вы пропустите %, он выполнит замену для первого экземпляра найденной строки; вы также можете использовать #его для замены строки, только если она находится в начале переменной; поэтому $ {0 / mp4 / m4a} заменит первый экземпляр mp4 на m4a (что может быть проблемой, если у вас действительно странные имена файлов); и $ {0 / # mp4 / m4a} заменит mp4 вместо m4a, но только если строковое значение переменной начинается с mp4 (здесь, очевидно, бесполезно, но оно может пригодиться в другом месте).
evilsoup

3

Чтобы избежать одновременной обработки нескольких файлов (которые могут использовать слишком много ресурсов), используйте parallel. По умолчанию он выполняет только одну работу за раз. Если вы хотите использовать несколько процессорных ядер параллельно, попробуйте выполнить 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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.