Ich möchte ein großes AVI-Video in zwei kleinere aufeinanderfolgende Videos aufteilen. Ich benutze ffmpeg.
Eine Möglichkeit ist, ffmpeg zweimal auszuführen:
ffmpeg -i input.avi -vcodec copy -acodec copy -ss 00:00:00 -t 00:30:00 output1.avi
ffmpeg -i input.avi -vcodec copy -acodec copy -ss 00:30:00 -t 00:30:00 output2.avi
Laut Manpage von ffmpeg kann ich jedoch aus einer Eingabedatei mit nur one line mehrere Ausgabedateien erstellen:
ffmpeg -i input.avi -vcodec copy -acodec copy -ss 00:00:00 -t 00:30:00 output1.avi \
-vcodec copy -acodec copy -ss 00:30:00 -t 00:30:00 output2.avi
Meine Frage ist, spart der spätere Ansatz Rechenzeit und Speicherplatz?
Das ffmpeg-Wiki verweist auf diese Seite in Bezug auf "So teilen Sie Video effizient auf". Ich bin nicht überzeugt, dass diese Seite diese Frage beantwortet, also habe ich @AlcubierreDrive vorgeschlagen…
echo "Two commands"
time ffmpeg -v quiet -y -i input.ts -vcodec copy -acodec copy -ss 00:00:00 -t 00:30:00 -sn test1.mkv
time ffmpeg -v quiet -y -i input.ts -vcodec copy -acodec copy -ss 00:30:00 -t 01:00:00 -sn test2.mkv
echo "One command"
time ffmpeg -v quiet -y -i input.ts -vcodec copy -acodec copy -ss 00:00:00 -t 00:30:00 \
-sn test3.mkv -vcodec copy -acodec copy -ss 00:30:00 -t 01:00:00 -sn test4.mkv
Welche Ausgänge ...
Two commands
real 0m16.201s
user 0m1.830s
sys 0m1.301s
real 0m43.621s
user 0m4.943s
sys 0m2.908s
One command
real 0m59.410s
user 0m5.577s
sys 0m3.939s
Ich habe eine SD- & HD-Datei getestet, nach ein paar Läufen und ein paar Berechnungen.
Two commands SD 0m53.94 #2 wins
One command SD 0m49.63
Two commands SD 0m55.00
One command SD 0m52.26 #1 wins
Two commands SD 0m58.60 #2 wins
One command SD 0m58.61
Two commands SD 0m54.60
One command SD 0m50.51 #1 wins
Two commands SD 0m53.94
One command SD 0m49.63 #1 wins
Two commands SD 0m55.00
One command SD 0m52.26 #1 wins
Two commands SD 0m58.71
One command SD 0m58.61 #1 wins
Two commands SD 0m54.63
One command SD 0m50.51 #1 wins
Two commands SD 1m6.67s #2 wins
One command SD 1m20.18
Two commands SD 1m7.67
One command SD 1m6.72 #1 wins
Two commands SD 1m4.92
One command SD 1m2.24 #1 wins
Two commands SD 1m1.73
One command SD 0m59.72 #1 wins
Two commands HD 4m23.20
One command HD 3m40.02 #1 wins
Two commands SD 1m1.30
One command SD 0m59.59 #1 wins
Two commands HD 3m47.89
One command HD 3m29.59 #1 wins
Two commands SD 0m59.82
One command SD 0m59.41 #1 wins
Two commands HD 3m51.18
One command HD 3m30.79 #1 wins
SD-Datei = 1.35 GB DVB-Transportstream
HD-Datei = 3.14GB DVB-Transportstrom
Der Einzelbefehl ist besser, wenn Sie mit HD arbeiten. Er stimmt mit den Kommentaren der Handbücher überein, dass -ss nach der Eingabedatei für eine 'langsame Suche' verwendet wird. SD-Dateien haben einen geringfügigen Unterschied.
Die Version mit zwei Befehlen sollte schneller sein, indem Sie vor der Eingabedatei ein weiteres -ss für den 'schnellen Suchlauf' gefolgt vom genaueren langsamen Suchlauf hinzufügen.
Hier ist ein nützliches Skript, das Ihnen beim automatischen Aufteilen hilft: Ein Skript zum Aufteilen von Videos mit ffmpeg
#!/bin/bash
# Written by Alexis Bezverkhyy <[email protected]> in 2011
# This is free and unencumbered software released into the public domain.
# For more information, please refer to <http://unlicense.org/>
function usage {
echo "Usage : ffsplit.sh input.file chunk-duration [output-filename-format]"
echo -e "\t - input file may be any kind of file reconginzed by ffmpeg"
echo -e "\t - chunk duration must be in seconds"
echo -e "\t - output filename format must be printf-like, for example myvideo-part-%04d.avi"
echo -e "\t - if no output filename format is given, it will be computed\
automatically from input filename"
}
IN_FILE="$1"
OUT_FILE_FORMAT="$3"
typeset -i CHUNK_LEN
CHUNK_LEN="$2"
DURATION_HMS=$(ffmpeg -i "$IN_FILE" 2>&1 | grep Duration | cut -f 4 -d ' ')
DURATION_H=$(echo "$DURATION_HMS" | cut -d ':' -f 1)
DURATION_M=$(echo "$DURATION_HMS" | cut -d ':' -f 2)
DURATION_S=$(echo "$DURATION_HMS" | cut -d ':' -f 3 | cut -d '.' -f 1)
let "DURATION = ( DURATION_H * 60 + DURATION_M ) * 60 + DURATION_S"
if [ "$DURATION" = '0' ] ; then
echo "Invalid input video"
usage
exit 1
fi
if [ "$CHUNK_LEN" = "0" ] ; then
echo "Invalid chunk size"
usage
exit 2
fi
if [ -z "$OUT_FILE_FORMAT" ] ; then
FILE_EXT=$(echo "$IN_FILE" | sed 's/^.*\.\([a-zA-Z0-9]\+\)$/\1/')
FILE_NAME=$(echo "$IN_FILE" | sed 's/^\(.*\)\.[a-zA-Z0-9]\+$/\1/')
OUT_FILE_FORMAT="${FILE_NAME}-%03d.${FILE_EXT}"
echo "Using default output file format : $OUT_FILE_FORMAT"
fi
N='1'
OFFSET='0'
let 'N_FILES = DURATION / CHUNK_LEN + 1'
while [ "$OFFSET" -lt "$DURATION" ] ; do
OUT_FILE=$(printf "$OUT_FILE_FORMAT" "$N")
echo "writing $OUT_FILE ($N/$N_FILES)..."
ffmpeg -i "$IN_FILE" -vcodec copy -acodec copy -ss "$OFFSET" -t "$CHUNK_LEN" "$OUT_FILE"
let "N = N + 1"
let "OFFSET = OFFSET + CHUNK_LEN"
done
http://ffmpeg.org/trac/ffmpeg/wiki/Seeking%20with%20FFmpeg kann auch für Sie nützlich sein. Auch ffmpeg hat einen Segmentmuxer, der funktionieren könnte.
Ich vermute jedenfalls, dass die Kombination dieser Befehle Zeit spart.
Verwenden Sie nach meiner Erfahrung ffmpeg nicht zum Teilen/Verbinden. MP4Box ist schneller und leichter als ffmpeg. Bitte tryit . Wenn Sie beispielsweise eine MP4-Datei mit 1400 MB in zwei Teile mit 700 MB aufteilen möchten, können Sie die folgende Cmdl verwenden: MP4Box -splits 716800 input.mp4
eg zum Verketten zweier Dateien, die Sie verwenden können:
MP4Box -cat file1.mp4 -cat file2.mp4 output.mp4
Oder wenn Sie nach Zeit teilen müssen, verwenden Sie -splitx StartTime:EndTime
:
MP4Box -add input.mp4 -splitx 0:15 -new split.mp4
spart der spätere Ansatz Rechenzeit und Speicher?
Es gibt keinen großen Unterschied zwischen diesen beiden Beispielen, die Sie zur Verfügung gestellt haben. Im ersten Beispiel wird das Video sequenziell in zwei Schritten geschnitten, im zweiten Beispiel zur gleichen Zeit (unter Verwendung von Threads). Es wird keine besondere Beschleunigung spürbar. Lesen Sie mehr über Erstellen mehrerer Ausgaben mit FFmpeg
Darüber hinaus können Sie (in letzter Zeit FFmpeg) den stream segmenter muxer verwenden, der
ausgabe-Streams in eine Reihe von separaten Dateien von nahezu fester Dauer. Das Dateinamensmuster der Ausgabe kann auf ähnliche Weise wie image2 eingestellt werden.
Hier ist eine einfache Windows-Bat-Datei, um die eingehende Datei in 50 Teile aufzuteilen. Jeder Teil hat eine Länge von 1 Minute. Entschuldigung für so ein dummes Skript. Ich hoffe, es ist besser, ein dummes Windows-Skript zu haben, als es überhaupt nicht zu haben. Vielleicht hilft es jemandem. (Basierend auf "bat file for loop" von dieser Site.)
set var=0
@echo off
:start
set lz=
if %var% EQU 50 goto end
if %var% LEQ 9 set lz=0
echo part %lz%%var%
ffmpeg -ss 00:%lz%%var%:00 -t 00:01:00 -i %1 -acodec copy -vcodec copy %2_%lz%%var%.mp4
set /a var+=1
goto start
:end
echo var has reached %var%.
exit
Hier ist eine perfekte Möglichkeit, das Video zu teilen. Ich habe es schon einmal gemacht und es funktioniert gut für mich.
ffmpeg -i C:\xampp\htdocs\videoCutting\movie.mp4 -ss 00:00:00 -t 00:00:05 -async 1 C:\xampp\htdocs\videoCutting\SampleVideoNew.mp4
(für cmd) .Shell_exec('ffmpeg -i C:\xampp\htdocs\videoCutting\movie.mp4 -ss 00:00:00 -t 00:00:05 -async 1 C:\xampp\htdocs\videoCutting\SampleVideoNew.mp4')
(für PHP).
Bitte folgen Sie diesem und ich bin sicher, dass es perfekt funktioniert.
Hab nicht getestet, aber das sieht vielversprechend aus:
Es ist offensichtlich, dass AVI in Segmente gleicher Größe aufgeteilt wird, was bedeutet, dass diese Chunks keine Qualität verlieren oder den Speicher nicht erhöhen oder neu berechnet werden müssen.
Es verwendet auch die Codec-Kopie - bedeutet das, dass sehr große Streams verarbeitet werden können? Da dies mein Problem ist, möchte ich mein avi aufteilen, so dass ich einen Filter verwenden könnte, um die Verzerrung zu beseitigen. Aber eine ganze Avi läuft stundenlang.