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?

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

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

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"

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

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ż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.


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.


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.


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.


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.


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.


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]


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


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.


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 🙏.


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");

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"

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.


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.


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"
    )

-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' ) );
}

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"


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.