Ich möchte nur ein mp4-Video mit ffmpeg loopen und die aktuellen Einstellungen und den aktuellen Codec beibehalten.
Wenn beispielsweise input.mp4 0:10 lang ist und ich es 4 Mal wiederholen möchte, sodass output.mp4 0:40 lang ist, wie könnte ich die folgende Befehlszeile ändern, um dies zu tun?
ffmpeg -i input.mp4 -c copy output.mp4
Ich habe es versucht...
ffmpeg -loop 4 -i input.mp4 -c copy output.mp4
...aber ich erhalte die Fehlermeldung "Option loop not found."
-stream_loop
Möglichkeitffmpeg -stream_loop 3 -i input.mp4 -c copy output.mp4
0
bedeutet keine Schleife, -1
bedeutet Endlosschleife.Mit dem concat-Demuxer können Sie eine Eingabe loopen, ohne sie neu codieren zu müssen, da er stream copy verwenden kann .
Erstellen Sie eine Textdatei. Inhalt einer Beispieltextdatei, die 4 Mal wiederholt werden soll.
file 'input.mp4'
file 'input.mp4'
file 'input.mp4'
file 'input.mp4'
Dann laufen ffmpeg
:
ffmpeg -f concat -i list.txt -c copy output.mp4
Wenn Sie zusätzliche Eingaben hinzufügen möchten, stellen Sie sicher, dass alle dieselben Attribute haben.
list.txt
in Linux/macOS erstellenDieses Beispiel ist dasselbe wie oben, aber Sie müssen Folgendes nicht manuell vornehmen 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
Mit den am häufigsten verwendeten modernen Shells können Sie die Erstellung der list.txt
Datei sogar vollständig vermeiden. Zum Beispiel mit bash:
ffmpeg -f concat -i <(for i in {1..4}; do printf "file '%s'\n" input.mp4; done) -c copy output.mp4
Beispiel für die Verwendung des Schleifenfilters zum 4-maligen Schleifen, jede Schleife besteht aus 75 Frames, jede Schleife überspringt die ersten 25 Frames der Eingabe:
ffmpeg -i input.mp4 -filter_complex "loop=loop=3:size=75:start=25" output.mp4
loop=3:75:25
loop=3
wird 4 Mal wiederholt.-1
.ffmpeg -h filter=loop
.Die Film- und Amovie-Filter haben eine Loop-Option:
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
bedeutet keine Schleife, 0
bedeutet Endlosschleife.-loop
MöglichkeitDie -loop
Option ist spezifisch für den Bilddatei-Demuxer und den GIF- Muxer , sodass sie nicht für typische Videodateien verwendet werden kann. Aber es kann verwendet werden, um ein einzelnes Bild oder eine Reihe von Bildern endlos zu wiederholen.
In diesem Beispiel wird ein einzelnes Bild immer wieder wiederholt, aber -t 30
die Ausgabedauer wird auf 30 Sekunden begrenzt:
ffmpeg -loop 1 -i input.png -t 30 -vf format=yuv420p output.mp4
-vf format=yuv420p
ist aus Kompatibilitätsgründen.
ffmpeg -loop 1 -i %03d.jpg -t 30 -vf format=yuv420p output.mp4
Oder um ein GIF zu loopen:
ffmpeg -i input -loop 3 output.gif
Informationen zur GIF-Ausgabe finden Sie auch unter Wie konvertiere ich ein Video mit ffmpeg in GIF mit angemessener Qualität?
> <(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
Abschnitt auf dasselbe Ticket wie das erste verweist ...-i %03d.png -t 30
und -t 30 -i %03d.png
? Ich weiß, dass Sie bei der Arbeit an Videos normalerweise -t
(und -ss
) vor der Eingabe möchten, um Dekodierungszeit zu sparen, aber spielt das für Bilder eine Rolle? Ich habe kürzlich einige Befehle mit -t
vor der Eingabe ausgeführt und es hat gut funktioniert.Mit ffmpeg 2.8.4 erstellt der folgende Befehl output.mp4, das eine sich wiederholende Kopie von input.mp4 ist, bis der ffmpeg-Prozess gestoppt wird:
ffmpeg -stream_loop -1 -i input.mp4 -c copy output.mp4
Dieser Befehl wird nicht von selbst beendet, und die Ausgabedatei wächst unendlich.
-1
einer positiven Ganzzahl entsprechend ihren Anforderungen ändern. Andernfalls wächst die Datei und das System gibt einen No space left on device
Fehler aus.Zumindest auf FFmpeg 2.8.x (aber Oldie sollte auch funktionieren) können Sie lavfi
als Eingabeformat und komplexes Filterdiagramm verwenden, indem Sie movie
und setpts
Filter als Argument für die -i
Option verwenden.
Nächster Befehl, der diese Arbeit für Sie erledigt:
ffmpeg -re -f lavfi -i "movie=filename=input.mp4:loop=0, setpts=N/(FRAME_RATE*TB)" output.mp4
Nullargumente loop=
bedeuten Endlosschleife. Werte größer Null setzen Wiederholungszählungen. setpts
Filter, die für die PTS-Anpassung für zweite und spätere Wiederholungen erforderlich sind, da sonst die meisten Ausgangs-Muxer mit nicht monotoner PTS-Erhöhung fehlschlagen: Schleife berechnet PTS nicht neu.
Beachten Sie, dass die Verwendung von Filtern unter der Annahme, dass Frames ohne Dekodierung/Kodierung umgangen werden, unmöglich ist: Filter behandeln nur dekodierte Frames.
Bei FFmpeg 2.8.2 neue Eingabemöglichkeit -stream_loop
eingeführt. Ich schaue zuerst, dass es einfacher funktioniert und das Kopieren von Inhalten ohne Transcodierung ermöglicht:
ffmpeg -re -stream_loop -1 -i input.mp4 -c copy -y output.mp4
Aber PTS wird nicht neu berechnet und die Ausgabedatei ist falsch. Wenn Sie einen Filter hinzufügen, um PTS zu reparieren (siehe setpts
), müssen Sie ihn auch entfernen -c copy
. Nur Bitstream-Filter können mit codierten Paketen umgehen, aber es gibt keine Bitstream-Filter, um PTS zu reparieren (siehe: https://ffmpeg.org/ffmpeg-bitstream-filters.html )
In jedem Fall schlägt ffmpeg beim zweiten Durchgang mit Fehler fehl:
input.mp4: Resource temporarily unavailable
Bekannte Problemumgehung für mich : Container für Eingabedatei ohne PTS-Grenzen verwenden (Streaming-Container). Einer davon, mir bekannt, ist MPEG-TS. So können Sie Ihre MP4-Datei einfach in MPEG-TS konvertieren:
ffmpeg -i input.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts input.ts
Und verwenden Sie den nächsten Befehl, um eine Infinity-Datei zu erstellen:
ffmpeg -re -stream_loop -1 -i input.ts -c copy -strict -2 -bsf:a aac_adtstoasc -y output.mp4
(Bitstream-Filter sollten nur bei Bedarf verwendet werden, bei meinen Samples ist dies erforderlich)
FFmpeg >= 2.8.2 ist in diesem Fall erforderlich.
-c copy
. Antwort behoben.@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
Wenn Sie MP4-Dateien haben, können diese verlustfrei verkettet werden, indem Sie sie zuerst in MPEG-2-Transportströme umwandeln. Mit H.264-Video und AAC-Audio kann Folgendes verwendet werden:
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
Die einfache Methode, die Probleme vermeidet, welche Befehle mit welcher Version funktionieren, ist die 'triviale Lösung':
ffmpeg -i input.mp4 -i input.mp4 -i input.mp4 -i input.mp4 -c copy output.mp4
Siehe auch: https://trac.ffmpeg.org/wiki/Concatenate für viele Beispiele.
Дмитрий Мышков