Comment convertir un répertoire entier avec ffmpeg?

191

Comment convertir un répertoire / dossier entier avec ffmpeg via la ligne de commande ou avec un script batch?

Eugène
la source

Réponses:

175

La réponse précédente ne créera qu'un seul fichier de sortie appelé out.mov. Pour créer un fichier de sortie distinct pour chaque ancien film, essayez ceci.

for i in *.avi;
  do name=`echo "$i" | cut -d'.' -f1`
  echo "$name"
  ffmpeg -i "$i" "${name}.mov"
done
Isaac
la source
24
Si vous êtes comme moi et que vous avez beaucoup d'espaces (et quelques autres caractères problématiques) dans vos noms de fichiers, je vous suggère d'ajouter des guillemets doubles: ffmpeg -i "$ i" "$ name.mov";
Pif du
7
Je reçois l'erreuri was unexpected at this time.
Keavon
5
do name=`echo "${i%.*}"`;fonctionnera sur les noms de fichiers contenant des points (et des espaces).
Nepoxx
8
Wow, cette réponse est incroyablement compliquée. Voir l'une des réponses en une ligne.
foobaritchen
2
est ce support pour .batWindows?
Jazuly
294

Pour Linux et macOS, cela peut être fait en une seule ligne, en utilisant l' expansion des paramètres pour changer l'extension du nom de fichier du fichier de sortie:

for i in *.avi; do ffmpeg -i "$i" "${i%.*}.mp4"; done
llogan
la source
2
C'est parfait, merci! Voici la commande complète qui a fonctionné très bien pour moi: for i in * .avi; faire ffmpeg -i "$ i" -c: a aac -b: a 128k -c: v libx264 -crf 20 "$ {i% .avi} .mp4"; done
Phil Kulak
1
@Junaid 1) Assurez-vous d'utiliser un nom différent pour le fichier de sortie que l'entrée ou la sortie vers un autre répertoire, car ffmpegvous ne pouvez pas entrer et sortir dans le même fichier. 2) Je ne sais pas si les commandes Bash fonctionnent sur Windows 10 de manière native. Peut-être devrais-je ajouter à la réponse qu'il est destiné aux systèmes qui peuvent utiliser nativement Bash tels que Linux et macOS. lxs a fourni une réponse Windows à cette question.
llogan
4
Réponse géniale. Fonctionne aussi avec les noms de fichiers avec des espaces!
wisbucky
1
Cela devrait être la meilleure réponse. Certes, l'explication de la raison pour laquelle {$ i%. *} N'est pas simple, mais si vous pouvez mettre cela de côté et simplement "l'utiliser", vous pouvez rapidement le modifier en conséquence. Par exemple, j'ai converti des centaines de fichiers .mp4 (avec des noms de fichiers comportant des espaces et des caractères spéciaux) en un format plus petit en utilisant: for i in .mp4; faire ffmpeg -i "$ i" -s 512x288 -c: une copie "$ {i%. } .m4v"; done
Tony M
1
Pour aller plus loin, vous pouvez utiliser la substitution de paramètre Bash si vous souhaitez remplacer la chaîne "x265" par "x264" si vous transcodez de H.265 à H.264, ce qui est un cas d'utilisation courant. 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

Et sous Windows:

FOR /F "tokens=*" %G IN ('dir /b *.flac') DO ffmpeg -i "%G" -acodec mp3 "%~nG.mp3"
lxs
la source
19
si vous exécutez cette commande dans un fichier batch (.bat), vous devez doubler les signes% => %%
hB0
Une idée comment exécuter cette commande mais copier dans un nouveau fichier qui inclut les métadonnées du fichier d'origine?
Barryman9000 le
@ Barryman9000, c'était il y a longtemps mais je pense qu'il y a une option de fichier de sortie que vous pourriez passer
lxs
@lxs merci pour le suivi. J'ai fini par le faire avec Powershell en changeant le nom du nouveau fichier pour qu'il devienne la date de création du fichier d'origine stackoverflow.com/a/35671099/197472
Barryman9000
Utilisé pour supprimer les métadonnées. Mais cela me donne une erreur d'accès refusé. J'ai donc changé le nom du fichier de sortie avec un espace supplémentaire pour en faire un nouveau fichier. 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

Un script bash d'une ligne serait facile à faire - remplacez-le *.avipar votre type de fichier:

for i in *.avi; do ffmpeg -i "$i" -qscale 0 "$(basename "$i" .avi)".mov  ; done
Jaune d'œuf
la source
L'encodeur par défaut pour .mov est libx264 (si disponible), mais cet encodeur ignore -qscale. Supprimez-le et utilisez les paramètres par défaut, ou utilisez-le à la -crfplace (la valeur par défaut est -crf 23).
llogan
1
S'il y a des espaces dans le nom de fichier, la commande échouera car le basenamesous-shell backticked n'est pas cité. C'est exactement pourquoi bash a une extension shell à la place: for i in * .avi; do ffmpeg -i "$ i" -qscale 0 "$ (nom de base" $ i ".avi)". mov; done
Calimo
merci @Calimo totalement d'accord - j'ai mis à jour ma réponse
jaune
22

Pour convertir avec des sous-répertoires, utilisez par exemple

find . -exec ffmpeg -i {} {}.mp3 \;
user2707001
la source
J'ai utilisé ceci, combiné avec cette réponse pour convertir VTT en SRT, avec beaucoup d'effet. find -name "*.vtt" -exec ffmpeg -i {} {}.srt \;
grooveplex
Je cette commande, avec une légère modification pour convertir tous les mp4 en mp3:find *.mp4 -exec ffmpeg -i {} {}.mp3 \;
swdev
1
Ou, si vous souhaitez convertir plusieurs types de fichiers:find . -name *.ogg -or -name *.wma -exec ffmpeg -i {} {}.mp3 \;
bonh
Convertissez tous les fichiers wma en mp3 et supprimez-les:find . -name *.wma -exec ffmpeg -i {} {}.mp3 \; -exec rm {} \;
Panagiotis
21

Pour les fenêtres:

Ici, je convertis tous les fichiers (.mp4) en fichiers (.mp3).
Ouvrez simplement cmd, accédez au dossier souhaité et tapez la commande.

Raccourci: (facultatif)
1. Accédez au dossier dans lequel vos fichiers (.mp4) sont présents
2. Appuyez sur Maj et faites un clic gauche et choisissez «Ouvrir la fenêtre PowerShell ici»
ou «Ouvrir la fenêtre d'invite de commande ici»
3. Tapez «cmd» [REMARQUE : Ignorez cette étape si elle ouvre directement cmd au lieu de PowerShell]
4. Exécutez la commande

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

Si vous souhaitez mettre cela dans un fichier de commandes sous Windows 10, vous devez utiliser %% i.

shubhamr238
la source
18

Pour tous ceux qui souhaitent convertir par lots quoi que ce soit avec ffmpeg mais souhaitent disposer d'une interface Windows pratique, j'ai développé ce front-end:

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

Il ajoute à ffmpeg une interface de mode de fenêtre, des barres de progression et des informations sur le temps restant, des fonctionnalités que j'ai toujours manquées lors de l'utilisation de ffmpeg.

Eibel
la source
Ok c'est un beau projet! J'ai poursuivi ma queue pendant une heure en essayant de faire accepter à ffmpeg un chemin d'accès relatif dans Windows et cela me donne l'impression de tricher. EDIT: j'ai utilisé ceci pour convertir .xwm en .flac
semtex41
6

Si vous avez GNU parallèle, vous pouvez convertir tous les fichiers .avi ci-dessous vid_diren mp4 en parallèle, en utilisant tous sauf un de vos cœurs de processeur avec

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

Pour convertir de / vers différents formats, modifiez '*.avi'ou .mp4au besoin. GNU parallel est répertorié dans la plupart des référentiels de distributions Linux dans un paquet qui est généralement appelé parallel.

sebbit
la source
ne pourriez-vous pas faire la même chose en ajoutant !à la fin de l'un des one-liners bash?
stib
3

Je sais que cela peut être redondant, mais j'utilise ce script pour convertir des fichiers par lots.

old_extension=$1
new_extension=$2

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

Il faut 2 arguments pour le rendre plus flexible:

  1. l'extension à partir de laquelle vous souhaitez effectuer la conversion
  2. la nouvelle extension vers laquelle vous souhaitez convertir

Je crée un alias pour cela mais vous pouvez également l'utiliser manuellement comme ceci:

sh batch_convert.sh mkv mp4

Cela convertirait tous les mkvfichiers en mp4fichiers.

Comme vous pouvez le voir, il est légèrement plus polyvalent. Tant que vous ffmpegpouvez le convertir, vous pouvez spécifier deux extensions.

Alexandre Luna
la source
C'est le meilleur 👍
Andreas Prang
3

Obtenir un peu comme code golf ici, mais comme presque toutes les réponses jusqu'à présent sont bash (à l'exception d'une seule cmd), voici une commande Windows multiplateforme qui utilise PowerShell (parce que génial):

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

Vous pouvez changer * .avi en ce qui correspond à votre métrage source.

stib
la source
3

Bien sûr, maintenant PowerShell est venu, spécialement conçu pour rendre quelque chose exactement comme ça extrêmement facile.

Et, oui, PowerShell est également disponible sur d'autres systèmes d'exploitation autres que Windows, mais il est pré-installé sur Windows, donc cela devrait être utile à tout le monde.

Tout d'abord, vous voudrez lister tous les fichiers dans le répertoire actuel, nous allons donc commencer par:

ls

Vous pouvez également l'utiliser ls -Recursesi vous souhaitez convertir de manière récursive tous les fichiers des sous-répertoires.

Ensuite, nous filtrerons ceux-ci au seul type de fichier que nous voulons convertir - par exemple "avi".

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

Après cela, nous transmettrons ces informations à FFmpeg via un fichier ForEach.

Pour l'entrée de FFmpeg, nous utiliserons le FullName- c'est le chemin d'accès complet au fichier. Et pour la sortie de FFmpeg, nous utiliserons le Name- mais en remplaçant le .avià la fin par .mp3. Donc, cela ressemblera à quelque chose comme ceci:

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

Alors, mettons tout cela ensemble et voici le résultat:

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

Cela convertira tous les fichiers ".avi" en fichiers ".mp3" via FFmpeg, remplacez simplement les trois éléments entre guillemets pour décider du type de conversion que vous souhaitez, et n'hésitez pas à ajouter d'autres arguments à FFmpeg dans le ForEach.

Vous pouvez aller plus loin et ajouter Remove-Itemà la fin pour supprimer automatiquement les anciens fichiers.

Si ce ffmpegn'est pas dans votre chemin, et qu'il se trouve en fait dans le répertoire dans lequel vous vous trouvez actuellement, écrivez- ./ffmpegy au lieu de simplement ffmpeg.

J'espère que cela aide n'importe qui.

ABPerson
la source
1
PowerShell est génial, merci! Au cas où quelqu'un d'autre aurait des problèmes pour exécuter ceci: mettez cette commande dans un .ps1fichier, pas dans un .batfichier. Vous devrez vous exécuter en Set-ExecutionPolicy RemoteSignedtant qu'administrateur si vous n'avez jamais exécuté de script PS auparavant.
starpause
Eh bien, en général, je pensais juste à l'exécuter directement dans PowerShell, donc je n'y ai pas vraiment pensé! Bon conseil cependant!
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

Traitement par lots des flacfichiers dans mp3(sans danger pour les noms de fichiers avec des espaces) en utilisant [1] [2]

César D. Velandia
la source
2

les fenêtres:

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

%~nd.2.mp3"
)

il s'agit d'un débit binaire variable de qualité 2, vous pouvez le régler sur 0 si vous le souhaitez mais à moins d'avoir un très bon système d'enceintes, cela ne vaut rien imo

user151496
la source
1

Si vous voulez une interface graphique pour traiter par lots avec ffmpegX, essayez Quick Batcher . C'est gratuit et prendra vos derniers paramètres ffmpegX pour convertir les fichiers que vous y déposez.

Notez que vous ne pouvez pas faire glisser les dossiers sur Quick Batcher. Sélectionnez donc les fichiers, puis placez-les dans Quick Batcher.

Nirav Mehta
la source
2
Le logiciel "Quick Batcher" est UNIQUEMENT pour MAC OS
Mohammad ElNesr
1

Seul celui-ci a fonctionné pour moi, veuillez noter que vous devez créer manuellement le dossier "newfiles" où se trouve le fichier ffmpeg.exe.

Convertissez . fichiers au code audio .wav:

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

c'est-à-dire que si vous voulez convertir tous les fichiers .mp3 en .wav, changez ("*.*")en ("*.mp3").

L'auteur de ce script est:

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

espérons que cela a aidé 🙏.

Mehrdad995
la source
0

Cela créera une vidéo mp4 à partir de tous les fichiers jpg du répertoire actuel.

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

Et pour Windows, cela ne fonctionne pas

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

même si je les double %.

Je suggérerais même:

-acodec ***libmp3lame***

aussi:

FOR /F "tokens=*" %G IN ('dir /b *.flac') DO ffmpeg -i "%G" -acodec libmp3lame "%~nG.mp3"
Halligallator
la source
Est-ce une réponse ou une tentative de publier une nouvelle question comme réponse? Dans ce dernier cas, veuillez créer une question complètement nouvelle à la place, mais éventuellement en renvoyant ici pour le fond.
tripleee
0

C'est ce que j'utilise pour convertir par lots avi en 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"

Fonctionne bien comme un fichier cmd, exécutez-le, la boucle trouve tous les fichiers avi dans ce dossier.

appelle MY (changez pour le vôtre) ffmpeg, transmet le nom d'entrée, les paramètres sont pour le redimensionnement avec accentuation. Je n'ai pas besoin de CRF et de " -b:v 1024k" ...

Le fichier de sortie est le fichier d'entrée moins l'extension, avec mp4 comme nouvel ext.

Morphy
la source
0

J'utilise ce one-liner sous Linux pour convertir des fichiers (généralement H265) en quelque chose que je peux jouer sur Kodi sans problèmes:

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

Cela convertit en un fichier temporaire, puis remplace l'original afin que les noms restent les mêmes après la conversion.

user1634000
la source
0

Aussi si vous voulez la même conversion dans les sous-dossiers. voici le code récursif.

for /R "folder_path" %%f in (*.mov,*.mxf,*.mkv,*.webm) do (
    ffmpeg.exe -i "%%~f" "%%~f.mp4"
    )
Hasan Yilmaz
la source
-1

petit script php pour le faire:

#!/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
la source
2
Une réponse à portée très limitée car un utilisateur doit avoir PHP installé sur sa machine. La ligne de commande et les réponses au fichier de commandes sont beaucoup plus faciles et beaucoup moins complexes.
ProfK
2
@ProfK PHP est l'un des langages les plus populaires sur SO - deuxièmement, la réponse d'Isaac pour sh est quelque peu peu fiable, en ce sens qu'il pourrait renommer vos fichiers en autre chose que l'original, par exemple, il ne conserve pas les nouvelles lignes dans le nom de fichier. Le script bat de lyx est encore pire, il IGNORE COMPLÈTEMENT tout fichier avec des retours à la ligne dans le nom. je ne sais pas pourquoi, pas même une erreur de syntaxe ou quoi que ce soit, mais c'est le cas (testé sur win10). mon script php n'a aucun problème, grâce à escapeshellarg(), et fonctionne à la fois sur Windows et Linux. Je suis d'accord que c'est un cas de pointe.
hanshenrik
-1

Une autre solution simple qui n'a pas encore été suggérée serait d'utiliser xargs:

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

Un piège mineur est le nom maladroit des fichiers de sortie (par exemple input.avi.mp4). Une solution de contournement possible pour cela pourrait être:

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

telenachos
la source
shellcheck.net a quelques suggestions concernant vos exemples.
llogan
mywiki.wooledge.org/ParsingLs bien que vous puissiez simplement le remplacer lspar printf '%s\n'ici.
tripleee