Extração em lote de áudio com avconv sem transcodificação

14

Tenho cerca de 70 arquivos mp4 e quero extrair os arquivos de áudio diretamente sem transcodificar ainda mais. Todos os arquivos mp4 possuem arquivos de áudio aac.

Entendo que posso usar o seguinte comando para extrair o arquivo de áudio de um dos arquivos mp4:

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

Como faço para extrair todos os arquivos de áudio de todos os 70 arquivos mp4, para acabar com 70 arquivos aac?

oshirowanen
fonte

Respostas:

21

Você pode usar um loop for simples:

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

ou em uma linha:

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

O que se faz é executado avconvuma vez para cada arquivo nomeado como *.mp4onde o nome do arquivo está armazenado na ${i}variável.

${i%.mp4}significa ${i}(ou seja, o nome do arquivo) .mp4retirado do final.

Andrew Gunnerson
fonte
2
IIRC, arquivos aac brutos não podem conter metadados; se você deseja manter os metadados dos arquivos originais, use m4a (que é apenas outro nome para mp4, mas é amplamente reconhecido pelos reprodutores de áudio) em vez de aac como uma extensão de arquivo.
evilsoup
Para que serve a opção -map? Por que você escolhe o fluxo 0: 1 em vez de outros fluxos, como 0: 0, 0: 2?
usar o seguinte
Larguei a opção -map e ele funciona muito bem
qed
para usar esse comando nas ações personalizadas do Thunar e similares, ele funciona se adicionado a um script e nas ações do Thunar: bash /path/to/the/script %F- como aqui
2
@ qed: a queda -mapainda pode levar o vídeo a ser considerado quando você alterna para outro formato de saída (se esse formato puder conter áudio e vídeo). É mais seguro mantê-lo como está.
dr. Sybren
5

A resposta de Xiao é geralmente a mais útil se você tiver todos os arquivos em um diretório; mas se houver arquivos MP4 espalhados em diretórios diferentes, você poderá usar este findcomando para converter todos eles.

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

Isso usa uma forma ligeiramente diferente de substituição de string do bash no final: "$ {0 /% mp4 / m4a}" diz ao bash para substituir mp4 por m4a, mas somente se o mp4 estiver no final da string.

evilsoup
fonte
Eu nunca soube que o bash tinha esse tipo de substituição. Impressionante :)
Andrew Gunnerson
1
@xiao Se você deixar de fora o %, ele substituirá a primeira instância da string que encontrar; você também pode usar #para substituir apenas a string se ela estiver no início de uma variável; então $ {0 / mp4 / m4a} substituiria a primeira instância do mp4 por m4a (o que poderia ser um problema se você tiver nomes de arquivos realmente estranhos); e $ {0 / # mp4 / m4a} substituirão mp4 por m4a, mas somente se o valor da string da variável começar com mp4 (não é necessário usar aqui, obviamente, mas pode ser útil em outros lugares).
evilsoup
3

Para evitar que vários arquivos sejam processados ​​ao mesmo tempo (que podem usar muitos recursos), use parallel. Por padrão, ele realiza apenas um trabalho por vez. Se você deseja usar vários núcleos de CPU em paralelo, tente parallel -j 4 ...4 trabalhos em paralelo. Também confira man parallel.

sudo apt-get install parallel

Essa linha extrai aacarquivos de áudio dos vídeos selecionados e os coloca em m4acontêineres.

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

Ao trabalhar diretamente na CLI, substitua %Fpela lista de seus arquivos de entrada. Por exemplo *.mp4.

Inspirado por esta resposta, por uma resposta anterior a esta pergunta e pelo comentário de evilsoup a esta (dizendo: 'os arquivos raw aac não podem conter metadados; se você deseja manter os metadados dos arquivos originais, use m4a (que é apenas outro nome para mp4, mas é amplamente reconhecido por players de áudio) em vez de aac como uma extensão de arquivo ' ).

Eu uso esses comandos nas ações personalizadas Thunar,

insira a descrição da imagem aqui

limitando o aplicativo a vídeos que contêm aacáudio.

insira a descrição da imagem aqui

Para ter uma janela de terminal aberta durante o processamento, que fecha no final, o comando pode ser alterado como:

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

Estendi a resposta de Xiao-Long Chen, transformando-a em um script que ignora arquivos quando o arquivo de saída é mais recente:

#!/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
dr. Sybren
fonte