Jak przekonwertować cały katalog za pomocą ffmpeg?

190

Jak przekonwertować cały katalog / folder za pomocą ffmpeg za pomocą wiersza polecenia lub skryptu wsadowego?

Eugene
źródło

Odpowiedzi:

174

Poprzednia odpowiedź utworzy tylko 1 plik wyjściowy o nazwie out.mov. Aby utworzyć osobny plik wyjściowy dla każdego starego filmu, spróbuj tego.

for i in *.avi;
  do name=`echo "$i" | cut -d'.' -f1`
  echo "$name"
  ffmpeg -i "$i" "${name}.mov"
done
Izaak
źródło
24
Jeśli jesteś podobny do mnie i masz dużo spacji (i kilka innych problematycznych znaków) w nazwach plików, sugeruję dodanie podwójnych cudzysłowów: ffmpeg -i "$ i" "$ name.mov";
Pif,
7
i was unexpected at this time.
Pojawia się
5
do name=`echo "${i%.*}"`;będzie działać na nazwach plików z kropkami (i spacjami) w nich.
Nepoxx
8
Wow, ta odpowiedź jest niezwykle skomplikowana. Zobacz jedną z odpowiedzi w jednym wierszu.
foobarbecue
2
czy to jest wsparcie dla systemu .batWindows?
Jazuly
294

W systemach Linux i macOS można to zrobić w jednym wierszu, używając rozszerzenia parametrów do zmiany rozszerzenia nazwy pliku wyjściowego:

for i in *.avi; do ffmpeg -i "$i" "${i%.*}.mp4"; done
Llogan
źródło
2
To jest idealne, dziękuję! Oto pełne polecenie, które skończyło się dla mnie świetne: for i in * .avi; do ffmpeg -i "$ i" -c: aac -b: a 128k -c: v libx264 -crf 20 "$ {i% .avi} .mp4"; zrobione
Phil Kulak
1
@Junaid 1) Upewnij się, że używasz innej nazwy pliku wyjściowego niż danych wejściowych lub danych wyjściowych do innego katalogu, ponieważ ffmpegnie można wejść i wyjść do tego samego pliku. 2) Nie jestem pewien, czy polecenia Bash działają w systemie Windows 10 natywnie. Może powinienem dodać do odpowiedzi, że jest on skierowany do systemów, które mogą natywnie używać Basha, takich jak Linux i macOS. lxs dostarczył odpowiedź Windows na to pytanie.
llogan
4
Świetna odpowiedź. Działa również z nazwami plików ze spacjami!
wisbucky,
1
To powinna być najlepsza odpowiedź. Co prawda wyjaśnienie, dlaczego {$ i%. *} Nie jest proste, ale jeśli możesz to odłożyć na bok i po prostu „użyć”, możesz szybko zmodyfikować, aby dopasować. Na przykład przekonwertowałem setki plików .mp4 (o nazwach plików zawierających spacje i znaki specjalne) na mniejszy format, używając: for i in .mp4; do ffmpeg -i „$ i” -s 512x288 -c: kopia „$ {i%. } .m4v”; gotowe
Tony M
1
Aby pójść o krok dalej, możesz użyć podstawienia parametru Bash, jeśli chcesz zamienić ciąg „x265” na „x264”, jeśli transkodujesz z H.265 na H.264, co jest częstym przypadkiem użycia. for f in *.mkv; do ffmpeg -i "$f" -map 0 -movflags faststart -c:v libx264 -c:a copy -c:s copy "${f/x265/x264}"; done
Travis Runyard,
70

A w systemie Windows:

FOR /F "tokens=*" %G IN ('dir /b *.flac') DO ffmpeg -i "%G" -acodec mp3 "%~nG.mp3"
lxs
źródło
19
jeśli uruchomisz to polecenie w pliku wsadowym (.bat), musisz podwoić znaki% => %%
hB0
Masz pomysł, jak uruchomić to polecenie, ale skopiuj do nowego pliku zawierającego metadane pliku oryginalnego?
Barryman9000,
@ Barryman9000 to było dawno temu, ale myślę, że istnieje opcja pliku wyjściowego, którą możesz przekazać
lxs
@lxs dzięki za kontynuację. Skończyłem z Powershellem, zmieniając nazwę nowego pliku na datę utworzenia oryginalnego pliku stackoverflow.com/a/35671099/197472
Barryman9000
Służył do usuwania metadanych. Ale daje mi błąd odmowy dostępu. Więc zmieniłem nazwę pliku wyjściowego z dodatkową spacją, aby uczynić go nowym plikiem. FOR /F "tokens=*" %G IN ('dir /b *.mp3') DO ffmpeg -i "%G" -map_metadata -1 -c:v copy -c:a copy "%~nG .mp3"
Junaid
28

Jednoliniowy skrypt bash byłby łatwy do zrobienia - zamień na *.aviswój typ pliku:

for i in *.avi; do ffmpeg -i "$i" -qscale 0 "$(basename "$i" .avi)".mov  ; done
żółtko
źródło
Domyślnym koderem dla .mov jest libx264 (jeśli jest dostępny), ale ten koder ignoruje -qscale. Usuń go i użyj ustawień domyślnych lub użyj -crfzamiast tego (domyślnie jest -crf 23).
llogan
1
Jeśli w nazwie pliku znajdują się spacje, wykonanie polecenia nie powiedzie się, ponieważ basenamepodpowłoka wsteczna nie jest cytowana. Właśnie dlatego bash ma zamiast tego rozszerzenie powłoki: dla i w * .avi; do ffmpeg -i "$ i" -qscale 0 "$ (basename" $ ​​i ".avi)" mov; gotowe
Calimo
dzięki @Calimo całkowicie się zgadzam - zaktualizowałem swoją odpowiedź
żółtko
22

Aby przekonwertować za pomocą podkatalogów użyj np

find . -exec ffmpeg -i {} {}.mp3 \;
użytkownik2707001
źródło
Użyłem tego, w połączeniu z tą odpowiedzią, aby przekonwertować VTT na SRT, aby uzyskać doskonały efekt. find -name "*.vtt" -exec ffmpeg -i {} {}.srt \;
grooveplex
I to polecenie, z niewielkim modyfikatorem do konwersji wszystkich MP4 na mp3:find *.mp4 -exec ffmpeg -i {} {}.mp3 \;
swdev
1
Lub, jeśli chcesz przekonwertować wiele typów plików:find . -name *.ogg -or -name *.wma -exec ffmpeg -i {} {}.mp3 \;
bonh
Konwertuj wszystkie pliki wma na mp3 i po ich usunięciu:find . -name *.wma -exec ffmpeg -i {} {}.mp3 \; -exec rm {} \;
Panagiotis,
20

Dla Windowsa:

Tutaj przekształcam wszystkie pliki (.mp4) w pliki (.mp3).
Po prostu otwórz cmd, przejdź do żądanego folderu i wpisz polecenie.

Skrót: (opcjonalnie)
1. Przejdź do folderu, w którym znajdują się pliki (.mp4)
2. Naciśnij Shift i kliknij lewym przyciskiem myszy i wybierz „Otwórz okno PowerShell tutaj”
lub „Otwórz okno wiersza polecenia tutaj”
3. Wpisz „cmd” [UWAGA : Pomiń ten krok, jeśli bezpośrednio otworzy cmd zamiast PowerShell]
4. Uruchom polecenie

for %i in (*.mp4) do ffmpeg -i "%i" "%~ni.mp3"

Jeśli chcesz umieścić to w pliku wsadowym w systemie Windows 10, musisz użyć %% i.

shubhamr238
źródło
18

Dla każdego, kto chce wsadowo przekonwertować cokolwiek za pomocą ffmpeg, ale chciałby mieć wygodny interfejs Windows, opracowałem ten interfejs:

https://sourceforge.net/projects/ffmpeg-batch

Dodaje do ffmpeg interfejs mody okna, paski postępu i informacje o pozostałym czasie, funkcje, których zawsze brakowało podczas korzystania z ffmpeg.

Eibel
źródło
Ok, to niezły projekt! Gonię za ogonem od godziny, próbując przekonać ffmpeg do zaakceptowania względnej ścieżki wyjściowej w systemie Windows, co sprawia, że ​​czuję się jak oszustwo. EDYCJA: użyłem tego do konwersji .xwm na .flac
semtex41
6

Jeśli masz GNU równolegle, możesz konwertować wszystkie pliki .avi poniżej vid_dirna mp4 równolegle, używając wszystkich oprócz jednego rdzenia procesora z

find vid_dir -type f -name '*.avi' -not -empty -print0 |
    parallel -0 -j -1 ffmpeg -loglevel fatal -i {} {.}.mp4

Aby przekonwertować z / do różnych formatów, zmień '*.avi'lub .mp4w razie potrzeby. GNU równoległe jest wymienione w repozytoriach większości dystrybucji Linuksa w pakiecie, który jest zwykle nazywany parallel.

Sebbit
źródło
czy nie możesz zrobić tego samego, dodając !na końcu jednego z linijek bash?
stib
3

Wiem, że to może być zbędne, ale używam tego skryptu do grupowej konwersji plików.

old_extension=$1
new_extension=$2

for i in *."$old_extension";
  do ffmpeg -i "$i" "${i%.*}.$new_extension";
done

Aby uczynić go bardziej elastycznym, potrzeba 2 argumentów:

  1. rozszerzenie, z którego chcesz przekonwertować
  2. nowe rozszerzenie, na które chcesz przekonwertować

Tworzę dla niego alias, ale możesz go również użyć ręcznie w następujący sposób:

sh batch_convert.sh mkv mp4

Spowodowałoby to konwersję wszystkich mkvplików na mp4pliki.

Jak widać, jest to nieco bardziej wszechstronne. Tak długo, jak ffmpegmożna go przekonwertować, można określić dowolne dwa rozszerzenia.

Alexander Luna
źródło
To jest najlepsze 👍
Andreas Prang
3

Trochę przypomina kod golfa, ale ponieważ prawie wszystkie dotychczasowe odpowiedzi są bash (z wyjątkiem jednego samotnego cmd), oto polecenie systemu Windows dla wielu platform, które używa PowerShell (ponieważ niesamowite):

ls *.avi|%{ ffmpeg -i $_ <ffmpeg options here> $_.name.replace($_.extension, ".mp4")}

Możesz zmienić * .avi na cokolwiek, co pasuje do twojego materiału źródłowego.

dźgnięcie
źródło
3

Oczywiście pojawił się teraz PowerShell, specjalnie zaprojektowany, aby uczynić coś dokładnie tak niezwykle łatwym.

I tak, PowerShell jest również dostępny w innych systemach operacyjnych niż tylko Windows, ale jest fabrycznie zainstalowany w systemie Windows, więc powinien być przydatny dla wszystkich.

Najpierw będziesz chciał wymienić wszystkie pliki w bieżącym katalogu, więc zaczniemy od:

ls

Możesz także użyć, ls -Recursejeśli chcesz rekurencyjnie przekonwertować wszystkie pliki w podkatalogach.

Następnie przefiltrujemy je do typu pliku, który chcemy przekonwertować - np. „Avi”.

ls | Where { $_.Extension -eq ".avi" }

Następnie przekażemy te informacje do FFmpeg za pośrednictwem ForEach.

Do danych wejściowych FFmpeg użyjemy FullName- to jest cała ścieżka do pliku. I na wyjściu FFmpeg będziemy używać Name- ale zastępując.avi na koniec z .mp3. Będzie to wyglądać mniej więcej tak:

$_.Name.Replace(".avi", ".mp3")

Połączmy to wszystko razem i oto wynik:

ls | Where { $_.Extension -eq ".avi" } | ForEach { ffmpeg -i $_.FullName $_.Name.Replace(".avi", ".mp3") }

Spowoduje to konwersję wszystkich plików „.avi” do plików „.mp3” za pomocą FFmpeg, wystarczy zastąpić trzy cytaty, aby zdecydować, jakiego rodzaju konwersję chcesz, i możesz dodać dowolne inne argumenty do FFmpeg w pliku ForEach.

Możesz pójść o krok dalej i dodać Remove-Itemdo końca, aby automatycznie usunąć stare pliki.

Jeśli ffmpegnie znajduje się na twojej ścieżce i rzeczywiście znajduje się w katalogu, w którym aktualnie się znajdujesz, napisz ./ffmpegtam zamiast po prostu ffmpeg.

Mam nadzieję, że to pomoże każdemu.

ABPerson
źródło
1
PowerShell jest świetny, dzięki! W przypadku problemów z uruchomieniem tego: umieść to polecenie w .ps1pliku, a nie w .batpliku. Musisz uruchomić Set-ExecutionPolicy RemoteSignedjako administrator, jeśli nigdy wcześniej nie uruchamiałeś skryptu PS.
starpause
Cóż, ogólnie pomyślałem o uruchomieniu go prosto w PowerShell, więc tak naprawdę nie pomyślałem o tym! Dobra wskazówka!
ABPerson
2
for i in *.flac;
  do name=`echo "${i%.*}"`;
  echo $name;
  ffmpeg -i "${i}" -ab 320k -map_metadata 0 -id3v2_version 3 "${name}".mp3;
done

Przetwarzaj flacpliki wsadowo w mp3(bezpieczny dla nazw plików ze spacjami) przy użyciu [1] [2]

César D. Velandia
źródło
2

Windows:

@echo off
for /r %%d in (*.wav) do (
    ffmpeg -i "%%~nd%%~xd" -codec:a libmp3lame -c:v copy -qscale:a 2 "%

%~nd.2.mp3"
)

jest to zmienna przepływność o jakości 2, możesz ustawić ją na 0, jeśli chcesz, ale jeśli nie masz naprawdę dobrego systemu głośników, nie warto

użytkownik151496
źródło
1

Jeśli chcesz, aby interfejs graficzny przetwarzał wsadowo za pomocą ffmpegX, wypróbuj Quick Batcher . To nic nie kosztuje i zajmie ostatnie ustawienia ffmpegX w celu konwersji plików, które do niego upuścisz.

Pamiętaj, że nie możesz przeciągać folderów do Szybkiego Batchera. Wybierz pliki, a następnie przeprowadź je przez Quick Batcher.

Nirav Mehta
źródło
2
Oprogramowanie „Quick Batcher” jest TYLKO dla MAC OS
Mohammad ElNesr
1

Tylko ten działał dla mnie, proszę zauważyć, że trzeba ręcznie utworzyć folder „newfiles”, w którym znajduje się plik ffmpeg.exe.

Konwersja . pliki do .wav audio Kod:

for %%a in ("*.*") do ffmpeg.exe -i "%%a" "newfiles\%%~na.wav"
pause

tzn. jeśli chcesz przekonwertować wszystkie pliki .mp3 na .wav zmień ("*.*")na ("*.mp3").

Autorem tego skryptu jest:

https://forum.videohelp.com/threads/356314-How-to-batch-convert-multiplex-any-files-with-ffmpeg

mam nadzieję, że to pomogło 🙏.

Mehrdad995
źródło
0

Spowoduje to utworzenie wideo MP4 ze wszystkich plików JPG z bieżącego katalogu.

echo exec("ffmpeg -framerate 1/5 -i photo%d.jpg -r 25 -pix_fmt yuv420p output.mp4");
thesachinparmar
źródło
0

W przypadku systemu Windows to nie działa

FOR /F "tokens=*" %G IN ('dir /b *.flac') DO ffmpeg -i "%G" -acodec mp3 "%~nG.mp3"

nawet jeśli podwoję te %.

Sugerowałbym nawet:

-acodec ***libmp3lame***

również:

FOR /F "tokens=*" %G IN ('dir /b *.flac') DO ffmpeg -i "%G" -acodec libmp3lame "%~nG.mp3"
Halligallator
źródło
Czy to odpowiedź, czy próba opublikowania nowego pytania jako odpowiedzi? W tym drugim przypadku utwórz całkowicie nowe pytanie, choć możliwe, że wrócisz tutaj, aby uzyskać dodatkowe informacje.
tripleee
0

Tego właśnie używam do wsadowej konwersji avi na 1280x mp4

FOR /F "tokens=*" %%G IN ('dir /b *.avi') DO "D:\Downloads\ffmpeg.exe" -hide_banner -i "%%G" -threads 8 -acodec mp3 -b:a 128k -ac 2 -strict -2 -c:v libx264 -crf 23 -filter:v "scale=1280:-2,unsharp=5:5:1.0:5:5:0.0" -sws_flags lanczos -b:v 1024k -profile:v main -preset medium -tune film -async 1 -vsync 1 "%%~nG.mp4"

Działa dobrze jako plik cmd, uruchom go, pętla znajdzie wszystkie pliki avi w tym folderze.

wywołuje MY (zmień dla twojego) ffmpeg, przekazuje nazwę wejściową, ustawienia dotyczą skalowania z wyostrzaniem. I probs nie potrzebują CRF i „ -b:v 1024k” ...

Plik wyjściowy to plik wejściowy minus rozszerzenie, z mp4 jako nowym rozszerzeniem.

Morphy
źródło
0

Używam tego jednowierszowego linuksa do konwersji plików (zwykle H265) na coś, co mogę odtwarzać na Kodi bez problemów:

for f in *.mkv; do ffmpeg -i "$f" -c:v libx264 -crf 28 -c:a aac -b:a 128k output.mkv; mv -f output.mkv "$f"; done

Konwertuje to na plik tymczasowy, a następnie zastępuje oryginał, dzięki czemu nazwy pozostają takie same po konwersji.

użytkownik1634000
źródło
0

Także jeśli chcesz taką samą konwersję w podfolderach. oto kod rekurencyjny.

for /R "folder_path" %%f in (*.mov,*.mxf,*.mkv,*.webm) do (
    ffmpeg.exe -i "%%~f" "%%~f.mp4"
    )
Hasan Yilmaz
źródło
-1

mały skrypt php, aby to zrobić:

#!/usr/bin/env php
<?php
declare(strict_types = 1);
if ($argc !== 2) {
    fprintf ( STDERR, "usage: %s dir\n", $argv [0] );
    die ( 1 );
}
$dir = rtrim ( $argv [1], DIRECTORY_SEPARATOR );
if (! is_readable ( $dir )) {
    fprintf ( STDERR, "supplied path is not readable! (try running as an administrator?)" );
    die(1);
}
if (! is_dir ( $dir )) {
    fprintf ( STDERR, "supplied path is not a directory!" );
    die(1);
}
$files = glob ( $dir . DIRECTORY_SEPARATOR . '*.avi' );
foreach ( $files as $file ) {
    system ( "ffmpeg -i " . escapeshellarg ( $file ) . ' ' . escapeshellarg ( $file . '.mp4' ) );
}
hanshenrik
źródło
2
Odpowiedź w bardzo ograniczonym zakresie, ponieważ użytkownik musi mieć PHP zainstalowane na swoim komputerze. Odpowiedzi na wiersze poleceń i pliki wsadowe są znacznie łatwiejsze i znacznie mniej złożone.
ProfK
2
@ProfK PHP jest jednym z najpopularniejszych języków na SO - po drugie, odpowiedź Izaaka na sh jest nieco niewiarygodna, ponieważ może zmienić nazwę twoich plików na coś innego niż oryginał, na przykład nie zachowuje nowych linii w nazwie pliku. Skrypt nietoperza lyx jest jeszcze gorszy, CAŁKOWICIE IGNORUJE każdy plik z nową linią w nazwie. nie jestem pewien, dlaczego, nawet błąd składniowy lub cokolwiek, ale tak się dzieje (testowane na Win10). mój skrypt php nie ma problemów dzięki escapeshellarg()i działa zarówno na systemie Windows, jak i Linux. zgadzam się jednak, że jest to przypadek skrajny.
hanshenrik
-1

Innym prostym rozwiązaniem, które nie zostało jeszcze zasugerowane, byłoby użycie xargs:

ls *.avi | xargs -i -n1 ffmpeg -i {} "{}.mp4"

Drobną pułapką jest niewygodne nazewnictwo plików wyjściowych (np input.avi.mp4.). Możliwym obejściem tego problemu może być:

ls *.avi | xargs -i -n1 bash -c "i={}; ffmpeg -i {} "\${i%.*}.mp4"

telenachos
źródło
shellcheck.net ma kilka sugestii dotyczących twoich przykładów.
llogan
mywiki.wooledge.org/ParsingLs choć może po prostu wymienić lssię printf '%s\n'tutaj.
tripleee