¿Cómo se convierte un directorio completo con ffmpeg?

191

¿Cómo se convierte un directorio / carpeta completo con ffmpeg a través de la línea de comandos o con un script por lotes?

Eugene
fuente

Respuestas:

175

La respuesta anterior solo creará 1 archivo de salida llamado out.mov. Para crear un archivo de salida separado para cada película anterior, intente esto.

for i in *.avi;
  do name=`echo "$i" | cut -d'.' -f1`
  echo "$name"
  ffmpeg -i "$i" "${name}.mov"
done
Isaac
fuente
24
Si eres como yo y tienes muchos espacios (y algunos otros caracteres problemáticos) en los nombres de tus archivos, te sugiero agregar comillas dobles: ffmpeg -i "$ i" "$ name.mov";
Pif
77
Recibo el errori was unexpected at this time.
Keavon
55
do name=`echo "${i%.*}"`;funcionará en nombres de archivo con puntos (y espacios) en ellos.
Nepoxx
8
Wow, esta respuesta es increíblemente complicada. Vea una de las respuestas de una línea.
foobarbecue
2
¿Es este soporte para .batWindows?
Jazuly
294

Para Linux y macOS, esto se puede hacer en una línea, usando la expansión de parámetros para cambiar la extensión del nombre de archivo del archivo de salida:

for i in *.avi; do ffmpeg -i "$i" "${i%.*}.mp4"; done
lema
fuente
2
Esto es perfecto, gracias! Aquí está el comando completo que terminó funcionando muy bien para mí: para i en * .avi; do ffmpeg -i "$ i" -c: a aac -b: a 128k -c: v libx264 -crf 20 "$ {i% .avi} .mp4"; hecho
Phil Kulak
1
@Junaid 1) Asegúrese de usar un nombre diferente para el archivo de salida que la entrada, o la salida a otro directorio, porque ffmpegno puede ingresar y salir al mismo archivo. 2) No estoy seguro si los comandos Bash funcionan en Windows 10 de forma nativa. Tal vez debería agregar a la respuesta que está dirigido a sistemas que pueden usar Bash de forma nativa, como Linux y macOS. lxs proporcionó una respuesta de Windows para esta pregunta.
llogan
44
Impresionante respuesta. Funciona con nombres de archivos con espacios también!
wisbucky
1
Esta debería ser la mejor respuesta. Es cierto que la explicación de por qué {$ i%. *} No es simple, pero si puede dejar eso de lado y simplemente "usarlo", puede modificarlo rápidamente para adaptarlo. Por ejemplo, convertí cientos de .mp4 (con nombres de archivos que tienen espacios y caracteres especiales) a un formato más pequeño usando: for i en .mp4; do ffmpeg -i "$ i" -s 512x288 -c: una copia "$ {i%. } .m4v"; hecho
Tony M
1
Para ir un paso más allá, puede usar la sustitución de parámetros Bash si desea reemplazar la cadena "x265" con "x264" si está transcodificando de H.265 a H.264, que es un caso de uso común. 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

Y en Windows:

FOR /F "tokens=*" %G IN ('dir /b *.flac') DO ffmpeg -i "%G" -acodec mp3 "%~nG.mp3"
lxs
fuente
19
si ejecuta este comando en un archivo por lotes (.bat) necesita duplicar los signos% => %%
hB0
¿Alguna idea de cómo ejecutar este comando pero copiar a un nuevo archivo que incluye los metadatos del archivo original?
Barryman9000
@ Barryman9000 esto fue hace mucho tiempo, pero creo que hay una opción de archivo de salida que podría pasar
lxs
@lxs gracias por el seguimiento. Terminé haciéndolo con Powershell cambiando el nombre del nuevo archivo para que sea la fecha del archivo original creado stackoverflow.com/a/35671099/197472
Barryman9000
Lo usó para eliminar metadatos. Pero me está dando acceso denegado error. Así que cambié el nombre del archivo de salida con un espacio extra para convertirlo en un nuevo archivo. 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 de una línea sería fácil de hacer; reemplácelo *.avicon su tipo de archivo:

for i in *.avi; do ffmpeg -i "$i" -qscale 0 "$(basename "$i" .avi)".mov  ; done
yema de huevo
fuente
El codificador predeterminado para .mov es libx264 (si está disponible), pero este codificador ignora -qscale. Elimínelo y use la configuración predeterminada, o use -crfen su lugar (el valor predeterminado es -crf 23).
llogan
1
Si hay espacios en el nombre del archivo, el comando fallará porque basenameno se cita la subshell invertida . Esto es exactamente por qué bash tiene expansión de shell en su lugar: para i en * .avi; do ffmpeg -i "$ i" -qscale 0 "$ (nombre base" $ i ".avi)". mov; hecho
Calimo
gracias @Calimo totalmente de acuerdo - he actualizado mi respuesta
yema
22

Para convertir con subdirectorios, use eg

find . -exec ffmpeg -i {} {}.mp3 \;
user2707001
fuente
Usé esto, combinado con esta respuesta para convertir VTT a SRT, con gran efecto. find -name "*.vtt" -exec ffmpeg -i {} {}.srt \;
grooveplex
Este comando, con un ligero modif para convertir todos los mp4 a mp3:find *.mp4 -exec ffmpeg -i {} {}.mp3 \;
swdev
1
O, si desea convertir varios tipos de archivos:find . -name *.ogg -or -name *.wma -exec ffmpeg -i {} {}.mp3 \;
bonh
Convierte todos los archivos wma a mp3 y luego bórralos:find . -name *.wma -exec ffmpeg -i {} {}.mp3 \; -exec rm {} \;
Panagiotis
20

Para ventanas:

Aquí estoy convirtiendo todos los archivos (.mp4) a archivos (.mp3).
Simplemente abra cmd, vaya a la carpeta deseada y escriba el comando.

Acceso directo: (opcional)
1. Vaya a la carpeta donde están presentes sus archivos (.mp4)
2. Presione Mayús y haga clic con el botón izquierdo y elija "Abrir ventana de PowerShell aquí"
o "Abrir ventana de símbolo del sistema aquí"
3. Escriba "cmd" [NOTA : Omita este paso si abre directamente cmd en lugar de PowerShell]
4. Ejecute el comando

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

Si desea poner esto en un archivo por lotes en Windows 10, debe usar %% i.

shubhamr238
fuente
18

Para cualquiera que quiera convertir por lotes cualquier cosa con ffmpeg pero le gustaría tener una interfaz conveniente de Windows, desarrollé este front-end:

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

Agrega a ffmpeg una interfaz de moda de ventana, barras de progreso e información restante del tiempo, características que siempre eché de menos al usar ffmpeg.

Eibel
fuente
Ok, este es un buen proyecto! He estado persiguiendo mi cola durante una hora tratando de que ffmpeg acepte una ruta relativa de archivos en Windows y esto hace que parezca una trampa. EDITAR: utilicé esto para convertir .xwm a .flac
semtex41
6

Si tiene GNU en paralelo , puede convertir todos los archivos .avi a continuación vid_dira mp4 en paralelo, utilizando todos excepto uno de los núcleos de su CPU con

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

Para convertir de / a diferentes formatos, cambie '*.avi'o .mp4según sea necesario. GNU paralela figura en la mayoría de los repositorios de distribuciones de Linux en un paquete que generalmente se llama parallel.

conejo
fuente
¿no podrías hacer lo mismo agregando !al final de cualquiera de las frases de bash?
stib
3

Sé que esto podría ser redundante, pero uso este script para convertir archivos por lotes.

old_extension=$1
new_extension=$2

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

Se necesitan 2 argumentos para hacerlo más flexible:

  1. la extensión desde la que desea convertir
  2. la nueva extensión a la que desea convertir

Creo un alias para él, pero también puede usarlo manualmente de esta manera:

sh batch_convert.sh mkv mp4

Esto convertiría todos los mkvarchivos en mp4archivos.

Como puedes ver, es un poco más versátil. Siempre que ffmpegpueda convertirlo, puede especificar dos extensiones.

Alexander Luna
fuente
Eso es lo mejor
Andreas
3

Obteniendo un poco como el código de golf aquí, pero dado que casi todas las respuestas hasta ahora son bash (salvo una sola cmd), aquí hay un comando multiplataforma de Windows que usa powershell (porque es increíble):

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

Puede cambiar * .avi a lo que coincida con su metraje original.

stib
fuente
3

Por supuesto, ahora PowerShell ha aparecido, diseñado específicamente para hacer que algo como esto sea extremadamente fácil.

Y sí, PowerShell también está disponible en otros sistemas operativos además de Windows, pero viene preinstalado en Windows, por lo que esto debería ser útil para todos.

Primero, querrás enumerar todos los archivos dentro del directorio actual, así que comenzaremos con:

ls

También puede usar ls -Recursesi desea convertir recursivamente todos los archivos en subdirectorios también.

Luego, los filtraremos solo al tipo de archivo que queremos convertir, por ejemplo, "avi".

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

Después de eso, pasaremos esa información a FFmpeg a través de un ForEach .

Para la entrada de FFmpeg, usaremos FullName: esa es la ruta completa al archivo. Y para la salida de FFmpeg usaremos el Name- pero reemplazando el .avial final con .mp3. Entonces, se verá más o menos así:

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

Entonces, juntemos todo eso y este es el resultado:

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

Eso convertirá todos los archivos ".avi" en archivos ".mp3" a través de FFmpeg, simplemente reemplace las tres cosas entre comillas para decidir qué tipo de conversión desea y siéntase libre de agregar cualquier otro argumento a FFmpeg dentro de ForEach.

Podría llevar esto un paso más allá y agregarlo Remove-Itemal final para eliminar automáticamente los archivos antiguos.

Si ffmpegno está en su camino, y en realidad está en el directorio en el que se encuentra actualmente, escriba ./ffmpegallí en lugar de solo ffmpeg.

Espero que esto ayude a cualquiera.

ABPerson
fuente
1
PowerShell es genial, ¡gracias! En caso de que alguien más tenga problemas para ejecutar esto: coloque este comando en un .ps1archivo, no en un .batarchivo. Tendrá que ejecutar Set-ExecutionPolicy RemoteSignedcomo administrador si nunca antes ha ejecutado un script PS.
starpause
Bueno, en general, solo pensé en ejecutarlo directamente en PowerShell, ¡así que realmente no pensé en eso! Buen consejo sin embargo!
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

Procese los flacarchivos por lotes en mp3(seguro para nombres de archivos con espacios) usando [1] [2]

César D. Velandia
fuente
2

ventanas:

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

%~nd.2.mp3"
)

esta es una tasa de bits variable de calidad 2, puede establecerla en 0 si lo desea, pero a menos que tenga un sistema de altavoces realmente bueno, no tiene valor

usuario151496
fuente
1

Si desea una interfaz gráfica para procesar por lotes con ffmpegX, pruebe Quick Batcher . Es gratis y tomará su última configuración de ffmpegX para convertir los archivos que coloque en ella.

Tenga en cuenta que no puede arrastrar y soltar carpetas en Quick Batcher. Por lo tanto, seleccione los archivos y luego póngalos en Quick Batcher.

Nirav Mehta
fuente
2
El software "Quick Batcher" es SOLO para MAC OS
Mohammad ElNesr
1

Solo este funcionó para mí, tenga en cuenta que debe crear la carpeta "newfiles" manualmente donde se encuentra el archivo ffmpeg.exe.

Convert . archivos a .wav Código de audio:

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

es decir, si desea convertir todos los archivos .mp3 a .wav, cambie ("*.*")a ("*.mp3").

El autor de este script es:

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

Espero que haya ayudado 🙏.

Mehrdad995
fuente
0

Esto creará video mp4 de todos los archivos jpg del directorio actual.

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

Y para Windows, esto no funciona

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

incluso si doblo esos %.

Incluso sugeriría:

-acodec ***libmp3lame***

además:

FOR /F "tokens=*" %G IN ('dir /b *.flac') DO ffmpeg -i "%G" -acodec libmp3lame "%~nG.mp3"
Halligallator
fuente
¿Es esta una respuesta o un intento de publicar una nueva pregunta como respuesta? En el último caso, cree una pregunta completamente nueva en su lugar, aunque posiblemente vincule aquí para obtener información de fondo.
tripleee
0

Esto es lo que uso para convertir por lotes avi a 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"

Funciona bien como un archivo cmd, ejecútelo, el bucle encuentra todos los archivos avi en esa carpeta.

llama a MY (cambio por el tuyo) ffmpeg, pasa el nombre de entrada, la configuración es para reescalar con nitidez. Los problemas no necesitan CRF y " -b:v 1024k" ...

El archivo de salida es el archivo de entrada menos la extensión, con mp4 como nueva ext.

Morphy
fuente
0

Estoy usando este one-liner en linux para convertir archivos (generalmente H265) en algo que puedo jugar en Kodi sin problemas:

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

Esto se convierte en un archivo temporal y luego reemplaza el original para que los nombres sigan siendo los mismos después de la conversión.

usuario1634000
fuente
0

Además, si desea la misma conversión en subcarpetas. Aquí está el código recursivo.

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

pequeño script php para hacerlo:

#!/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
fuente
2
Una respuesta de alcance muy limitado ya que un usuario debe tener PHP instalado en su máquina. La línea de comandos y las respuestas de los archivos por lotes son mucho más fáciles y mucho menos complejas.
ProfK
2
@ProfK PHP es uno de los lenguajes más populares en SO ; en segundo lugar, la respuesta de Isaac para sh no es confiable, ya que podría cambiar el nombre de sus archivos a algo más que el original, por ejemplo, no conserva las nuevas líneas en el nombre del archivo. El script de murciélago de lyx es aún peor, COMPLETAMENTE IGNORA cualquier archivo con nuevas líneas en el nombre. No estoy seguro de por qué, ni siquiera un error de sintaxis ni nada, pero lo hace (probado en win10). mi script php no tiene problemas, gracias a escapeshellarg(), y funciona tanto en Windows como en Linux. Estoy de acuerdo en que es un caso extremo sin embargo.
hanshenrik
-1

Otra solución simple que aún no se ha sugerido sería usar xargs:

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

Un inconveniente menor es la denominación incómoda de los archivos de salida (por ejemplo input.avi.mp4). Una posible solución para esto podría ser:

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

telenachos
fuente
shellcheck.net tiene algunas sugerencias con respecto a sus ejemplos.
llogan
mywiki.wooledge.org/ParsingLs aunque se puede simplemente reemplazar lscon printf '%s\n'aquí.
tripleee