Solo quiero reproducir un video mp4 con ffmpeg y mantener la configuración y el códec actuales.
Por ejemplo, si input.mp4 tiene una duración de 0:10 y me gustaría repetirlo 4 veces para que output.mp4 tenga una duración de 0:40, ¿cómo podría cambiar la siguiente línea de comando para hacer eso?
ffmpeg -i input.mp4 -c copy output.mp4
Lo intenté...
ffmpeg -loop 4 -i input.mp4 -c copy output.mp4
... pero aparece el error "No se encontró el bucle de opción".
-stream_loop
opciónffmpeg -stream_loop 3 -i input.mp4 -c copy output.mp4
0
significa sin bucle, -1
significa bucle infinito.El demuxer concat le permite hacer un bucle de una entrada sin necesidad de volver a codificar porque puede usar la copia de flujo .
Haz un archivo de texto. Contenido de un archivo de texto de ejemplo para repetir 4 veces.
file 'input.mp4'
file 'input.mp4'
file 'input.mp4'
file 'input.mp4'
Luego ejecuta ffmpeg
:
ffmpeg -f concat -i list.txt -c copy output.mp4
Si desea agregar entradas adicionales, asegúrese de que todas tengan los mismos atributos.
list.txt
en Linux/macOSEste ejemplo es el mismo que el anterior, pero no tiene que hacer manualmente list.txt
:
for i in {1..4}; do printf "file '%s'\n" input.mp4 >> list.txt; done
ffmpeg -f concat -i list.txt -c copy output.mp4
Con los shells modernos más utilizados, incluso puede evitar la creación del list.txt
archivo por completo. Por ejemplo, con bash:
ffmpeg -f concat -i <(for i in {1..4}; do printf "file '%s'\n" input.mp4; done) -c copy output.mp4
Ejemplo usando el filtro de bucle para hacer un bucle 4 veces, cada bucle tiene 75 fotogramas, cada bucle salta los primeros 25 fotogramas de la entrada:
ffmpeg -i input.mp4 -filter_complex "loop=loop=3:size=75:start=25" output.mp4
loop=3:75:25
loop=3
se repetirá 4 veces.-1
.ffmpeg -h filter=loop
También veaLos filtros de película y amovie tienen una opción de bucle:
ffmpeg -f lavfi -i "movie=filename=input.mp4:loop=4,setpts=N/FRAME_RATE/TB" -f lavfi -i "amovie=filename=input.mp4:loop=4,asetpts=N/SR/TB" output.mp4
1
significa sin bucle, 0
significa bucle infinito.-loop
opciónLa -loop
opción es específica para el demuxer de archivos de imagen y gif muxer , por lo que no se puede usar para archivos de video típicos. Pero se puede usar para repetir infinitamente una sola imagen o una serie de imágenes.
Este ejemplo repetirá una sola imagen una y otra vez, pero -t 30
limitará la duración de la salida a 30 segundos:
ffmpeg -loop 1 -i input.png -t 30 -vf format=yuv420p output.mp4
-vf format=yuv420p
es por razones de compatibilidad.
ffmpeg -loop 1 -i %03d.jpg -t 30 -vf format=yuv420p output.mp4
O para reproducir un GIF:
ffmpeg -i input -loop 3 output.gif
Para la salida de GIF también vea ¿Cómo convierto un video a GIF usando ffmpeg, con una calidad razonable?
> <(for i in {1..4}; do printf "file '%s'\n" input.mp4; done) -bash: /dev/fd/63: Permission denied
ffmpeg -i video.mp4 -filter_complex "loop=4:32767" output.mp4
-stream_loop
sección apunta al mismo ticket que el primero...-i %03d.png -t 30
y -t 30 -i %03d.png
? Sé que cuando trabajas en video, por lo general deseas -t
(y -ss
) antes de la entrada para ahorrar tiempo de decodificación, pero ¿importa esto para las imágenes? Recientemente ejecuté algunos comandos -t
antes de la entrada y funcionó bien.Con ffmpeg 2.8.4, el siguiente comando crea output.mp4 que es una copia repetida de input.mp4 hasta que se detiene el proceso de ffmpeg:
ffmpeg -stream_loop -1 -i input.mp4 -c copy output.mp4
Este comando no terminará por sí solo y el archivo de salida crecerá infinitamente.
-1
algún número entero positivo de acuerdo con sus requisitos. De lo contrario, el archivo crece y el sistema arroja No space left on device
un error.Al menos en FFmpeg 2.8.x (pero el antiguo también debería funcionar) puede usar lavfi
como formato de entrada y un gráfico de filtro complejo usando movie
y setpts
filtros como argumento para la -i
opción.
Siguiente comando haciendo este trabajo por usted:
ffmpeg -re -f lavfi -i "movie=filename=input.mp4:loop=0, setpts=N/(FRAME_RATE*TB)" output.mp4
Cero loop=
argumentos significa bucle infinito. Los valores superiores a cero establecen recuentos repetidos. setpts
Se requieren filtros para el ajuste de PTS para la segunda y posteriores repeticiones; de lo contrario, la mayoría de los muxers de salida fallarán con el aumento de PTS no monótono: el bucle no vuelve a calcular PTS.
Tenga en cuenta que el uso de filtros asumiendo que eluden los marcos sin decodificar/codificar es imposible: por diseño, los filtros se ocupan solo de los marcos decodificados.
En FFmpeg 2.8.2 se introdujo una nueva opción de entrada -stream_loop
. Primero veo que funciona de manera más simple y permite copiar contenido sin transcodificar:
ffmpeg -re -stream_loop -1 -i input.mp4 -c copy -y output.mp4
Pero no vuelve a calcular PTS y el archivo de salida es incorrecto. Si agrega un filtro para corregir PTS (consulte setpts
), también debe eliminarlo -c copy
. Solo los filtros de flujo de bits pueden manejar paquetes codificados, pero no hay filtros de flujo de bits para corregir PTS (ver: https://ffmpeg.org/ffmpeg-bitstream-filters.html )
En cualquier caso, ffmpeg en el segundo paso falla con un error:
input.mp4: Resource temporarily unavailable
Solución conocida para mí : use el contenedor para el archivo de entrada sin límites PTS (contenedor de transmisión). Uno de ellos, conocido por mí, es MPEG-TS. Entonces, puede simplemente convertir su archivo MP4 a MPEG-TS:
ffmpeg -i input.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts input.ts
Y use el siguiente comando para componer el archivo infinito:
ffmpeg -re -stream_loop -1 -i input.ts -c copy -strict -2 -bsf:a aac_adtstoasc -y output.mp4
(Los filtros de flujo de bits deben usarse solo si es necesario, en mis muestras es obligatorio)
En este caso, se requiere FFmpeg >= 2.8.2.
-c copy
. Respuesta arreglada.@echo off
setlocal ENABLEDELAYEDEXPANSION
REM When not there gives file not found message
for /f "tokens=*" %%I in ('dir /b "*.mkv"') do (
if exist "%%~nI.nl.srt" (
call :BURN_FILE "%%~nI" "%%I"
)
if exist "%%~nI.en.srt" (
call :BURN_FILE "%%~nI" "%%I"
)
)
for /f "tokens=*" %%I in ('dir /b "*.mp4"') do (
if exist "%%~nI.nl.srt" (
call :BURN_FILE "%%~nI" "%%I"
)
if exist "%%~nI.en.srt" (
call :BURN_FILE "%%~nI" "%%I"
)
)
for /f "tokens=*" %%I in ('dir /b "*.webm"') do (
if exist "%%~nI.nl.srt" (
call :BURN_FILE "%%~nI" "%%I"
)
if exist "%%~nI.en.srt" (
call :BURN_FILE "%%~nI" "%%I"
)
)
pause
if not exist ORIGINAL mkdir ORIGINAL
move "%%I" ORIGINAL >NUL
move "%%~nI.*" ORIGINAL >NUL
exit /b
:BURN_FILE
set hoppa=%1
set input=%2
echo hoppa=!hoppa!
echo input=!input!
ffprobe.exe -v error -select_streams v:0 -show_entries format=bit_rate -of default=nw=1 !input! > bit_rate2.txt
ffprobe.exe -v error -show_entries format=duration -of default=nw=1 !input! > duration2.txt
ffprobe.exe -v error -show_entries format=duration -of default=nw=1 intro.wav > duration_intro.txt
for /F "tokens=*" %%R in (bit_rate2.txt) do (
for /f "tokens=1,2 delims==" %%a in ("%%R") do set NAME=%%a & set bit_rate=%%b
)
for /F "tokens=*" %%R in (duration2.txt) do (
for /f "tokens=1,2 delims==" %%a in ("%%R") do set NAME=%%a & set duration=%%b
)
for /F "tokens=*" %%R in (duration_intro.txt) do (
for /f "tokens=1,2 delims==" %%a in ("%%R") do set NAME=%%a & set duration_intro=%%b
)
for /f "tokens=1 delims=." %%a in ('echo !duration!') do set /a number=%%a
for /f "tokens=1 delims=." %%a in ('echo !duration_intro!') do set /a number_intro=%%a
set /A number_offset = !number! - !number_intro! - 1
set /A number_offset = !number_offset! * 1000
sof.exe "!hoppa!.nl.srt"
if not exist DUTCH mkdir DUTCH
for %%x in ("!hoppa!.nl.srt.fixed") do (
if not %%~zx == 0 (
if not exist "DUTCH/!hoppa!.nl.mp4" (
ffmpeg -y -hide_banner -i !input! -i intro.wav -i intro.wav -i pacman2.mp4 -loop 20 -filter_complex "[1]adelay=500|500[s1];[1]adelay=!number_offset!|!number_offset![s2];[0][s1][s2]amix=inputs=3;[0:v]scale=1920:1080[j];[3:v]split[m][a];[a]geq='lum(X,Y)',hue=s=0[al];[m][al]alphamerge[ovr];[ovr]scale=150:-1[sml];[j][sml]overlay=main_w-overlay_w-2:main_h-overlay_h-2[l];[l]subtitles='!hoppa!.nl.srt.fixed':force_style='FontName=Mada Black,FontSize=32,BackColour=&HA0000000,BorderStyle=4'[k]" -map "[k]" -map 0:a -strict -2 -c:v h264_nvenc -pix_fmt yuv420p -rc-lookahead 32 -b:v !bit_rate! -ac 2 -ar 44100 -acodec aac -shortest "DUTCH/!hoppa!.nl.PART.mp4"
rem ffmpeg -y -hide_banner -i !input! -filter_complex "[0:v]scale=1920:1080[j];[j]subtitles='!hoppa!.nl.srt.fixed':force_style='FontName=Mada Black,FontSize=32'[k]" -map "[k]" -map 0:a -strict -2 -c:v h264_nvenc -pix_fmt yuv420p -rc-lookahead 32 -b:v !bit_rate! -ac 2 -ar 44100 -acodec aac "DUTCH/!hoppa!.nl.PART.mp4"
rem ffmpeg -y -hide_banner -i !input! -filter_complex "[0:v]scale=1920:1080[j];[j]subtitles='!hoppa!.nl.srt.fixed'[k]" -map "[k]" -map 0:a -strict -2 -c:v h264_nvenc -pix_fmt yuv420p -rc-lookahead 32 -b:v !bit_rate! -ac 2 -ar 44100 -acodec aac "DUTCH/!hoppa!.nl.PART.mp4"
rem ffmpeg -y -hide_banner -i !input! -filter_complex "[0:v]scale=1920:1080[j];[j]subtitles='!hoppa!.nl.srt.fixed'[k]" -map "[k]" -map 0:a -strict -2 -c:v libx264 -preset slow -crf 23 -pix_fmt yuv420p -b:v !bit_rate! -ac 2 -ar 44100 -acodec aac "DUTCH/!hoppa!.nl.PART.mp4"
) else (
echo Already exists: "DUTCH/!hoppa!.nl.mp4"
)
) else (
echo Subtitle file empty: !hoppa!.nl.srt.fixed
)
)
if exist "DUTCH/!hoppa!.nl.PART.mp4" rename "DUTCH\!hoppa!.nl.PART.mp4" "!hoppa!.nl.mp4"
rem if not exist SUBTITLES mkdir SUBTITLES
rem if exist "!hoppa!.nl.srt.fixed" move "!hoppa!.nl.srt.fixed" SUBTITLES
rem if exist "!hoppa!.nl.srt" move "!hoppa!.nl.srt" SUBTITLES
rem remark (rem) goto for making second language
goto :ENDING
sof.exe "!hoppa!.en.srt"
if not exist ENGLISH mkdir ENGLISH
for %%x in ("!hoppa!.en.srt.fixed") do (
if not %%~zx == 0 (
if not exist "ENGLISH/!hoppa!.en.mp4" (
ffmpeg -y -hide_banner -i !input! -filter_complex "[0:v]scale=1920:1080[j];[j]subtitles='!hoppa!.en.srt.fixed'[k]" -map "[k]" -map 0:a -strict -2 -c:v h264_nvenc -pix_fmt yuv420p -rc-lookahead 32 -b:v !bit_rate! -ac 2 -ar 44100 -acodec aac "ENGLISH/!hoppa!.en.PART.mp4"
rem ffmpeg -y -hide_banner -i !input! -filter_complex "[0:v]scale=1920:1080[j];[j]subtitles='!hoppa!.en.srt.fixed'[k]" -map "[k]" -map 0:a -strict -2 -c:v libx264 -preset slow -crf 23 -pix_fmt yuv420p -b:v !bit_rate! -ac 2 -ar 44100 -acodec aac "ENGLISH/!hoppa!.en.PART.mp4"
) else (
echo Already exists: "DUTCH/!hoppa!.en.mp4"
)
) else (
echo Subtitle file empty: !hoppa!.en.srt.fixed
)
)
if exist "ENGLISH/!hoppa!.en.PART.mp4" rename "ENGLISH\!hoppa!.en.PART.mp4" "!hoppa!.en.mp4"
rem if exist "!hoppa!.en.srt.fixed" move "!hoppa!.en.srt.fixed" SUBTITLES >NUL
rem if exist "!hoppa!.en.srt" move "!hoppa!.en.srt" SUBTITLES >NUL
:ENDING
if not exist ORIGINAL mkdir ORIGINAL
move !input! ORIGINAL >NUL
move "!hoppa!.*" ORIGINAL >NUL
exit /b
Si tiene archivos MP4, estos pueden concatenarse sin pérdidas volviéndolos a empaquetar primero en flujos de transporte MPEG-2. Con video H.264 y audio AAC, se puede usar lo siguiente:
ffmpeg -i input.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate.ts
ffmpeg -i "concat:intermediate.ts|intermediate.ts|intermediate.ts|intermediate.ts" -c copy -bsf:a aac_adtstoasc output.mp4
El método simple que evita problemas de qué comandos funcionan con qué versión es la 'solución trivial':
ffmpeg -i input.mp4 -i input.mp4 -i input.mp4 -i input.mp4 -c copy output.mp4
Consulte también: https://trac.ffmpeg.org/wiki/Concatenate para ver muchos ejemplos.
Дмитрий Мышков