Batch wyodrębnij audio z avconv bez transkodowania

14

Mam około 70 plików mp4 i chcę wyodrębnić pliki audio bezpośrednio bez dalszego transkodowania. Wszystkie pliki MP4 mają pliki audio AAC.

Rozumiem, że mogę użyć następującego polecenia, aby wyodrębnić plik audio z jednego z plików mp4:

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

Jak wyodrębnić wszystkie pliki audio ze wszystkich plików 70 mp4, aby otrzymać 70 plików AAC?

oshirowanen
źródło

Odpowiedzi:

21

Możesz użyć prostej pętli for:

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

lub w jednej linii:

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

To, co robi, jest uruchamiane avconvraz dla każdego pliku o nazwie, np. *.mp4Gdzie nazwa pliku jest przechowywana w ${i}zmiennej.

${i%.mp4}oznacza ${i}(tj. nazwę pliku) z .mp4usuniętym z końca.

Andrew Gunnerson
źródło
2
IIRC, surowe pliki AAC nie mogą zawierać metadanych; jeśli chcesz zachować metadane z oryginalnych plików, użyj m4a (która jest po prostu inną nazwą mp4, ale jest dość powszechnie rozpoznawana przez odtwarzacze audio) zamiast aac jako rozszerzenia pliku.
evilsoup
Do czego służy opcja -map? Dlaczego wybierasz strumień 0: 1 zamiast innych strumieni, takich jak 0: 0, 0: 2?
qed
Porzuciłem opcję -map i działa dobrze
qed
aby użyć tego polecenia w niestandardowych akcjach Thunara i podobnych, działa, jeśli zostanie dodany do skryptu i akcji Thunar: bash /path/to/the/script %F- jak tutaj
2
@qed: upuszczenie -mapmoże nadal powodować, że wideo będzie rozpatrywane po przełączeniu na inny format wyjściowy (jeśli ten format może zawierać zarówno dźwięk, jak i wideo). Bezpieczniej jest zachować go takim, jakim jest.
dr. Sybren
5

Odpowiedź Xiao jest na ogół najbardziej przydatna, jeśli masz wszystkie pliki w jednym katalogu; ale jeśli pliki MP4 są rozproszone w różnych katalogach, możesz użyć tego findpolecenia, aby je przekonwertować.

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

Używa nieco innej formy podstawiania ciągu bash na końcu: „$ {0 /% mp4 / m4a}” mówi bashowi, aby zastąpił mp4 m4a, ale tylko jeśli mp4 znajduje się na końcu ciągu.

zła
źródło
Nigdy nie wiedziałem, że bash ma tego rodzaju substytucję. Niesamowite :)
Andrew Gunnerson
1
@xiao Jeśli pominiesz, spowoduje %podstawienie pierwszej instancji znalezionego ciągu; możesz także użyć, #aby zastąpić ciąg tylko wtedy, gdy jest on na początku zmiennej; więc $ {0 / mp4 / m4a} zamieniłoby pierwszą instancję mp4 na m4a (co może być problemem, jeśli masz naprawdę dziwne nazwy plików); a $ {0 / # mp4 / m4a} zastąpi mp4 zamiast m4a, ale tylko wtedy, gdy wartość ciągu zmiennej zaczyna się od mp4 (oczywiście nie ma tu zastosowania, ale może się przydać gdzie indziej).
evilsoup
3

Aby uniknąć przetwarzania wielu plików jednocześnie (które mogą zużywać zbyt wiele zasobów), użyj parallel. Domyślnie wykonuje tylko jedno zadanie na raz. Jeśli chcesz używać wielu rdzeni procesora równolegle, spróbuj wykonać parallel -j 4 ...4 zadania równolegle. Sprawdź także man parallel.

sudo apt-get install parallel

Ta linia wyodrębni aacpliki audio z wybranych filmów i umieści je w m4apojemnikach.

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

Podczas pracy bezpośrednio w interfejsie CLI zastąp %Flistę plików wejściowych. Np *.mp4.

Zainspirowany odpowiedzią, poprzednią odpowiedzią na to pytanie oraz komentarzem evilsoup do drugiego (mówiąc: „surowe pliki AAC nie mogą zawierać metadanych; jeśli chcesz zachować metadane z oryginalnych plików, użyj m4a (które to po prostu inna nazwa mp4, ale jest dość powszechnie rozpoznawana przez odtwarzacze audio) zamiast aac jako rozszerzenie pliku ” ).

Używam takich poleceń w niestandardowych akcjach Thunar,

wprowadź opis zdjęcia tutaj

ograniczenie aplikacji do filmów zawierających aacdźwięk.

wprowadź opis zdjęcia tutaj

Aby okno terminalu było otwarte podczas przetwarzania, które zamyka się na końcu, polecenie można zmienić w następujący sposób:

 gnome-terminal -e "parallel avconv -i '{}' -map 0:1 -c:a copy '{.}.m4a' ::: %F"
Społeczność
źródło
2

Rozszerzyłem odpowiedź @ Xiao-Long Chena, przekształcając ją w skrypt, który pomija pliki, gdy plik wyjściowy jest nowszy:

#!/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
źródło