FFmpeg: Jak efektywnie podzielić wideo?


103

Chciałbym podzielić duży film avi na dwa kolejne mniejsze filmy. Używam ffmpeg.

Jednym ze sposobów jest dwukrotne uruchomienie ffmpeg:

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

Ale zgodnie ze stroną podręcznika ffmpeg, mogę utworzyć więcej niż jeden plik wyjściowy z jednego pliku wejściowego, używając tylko jednej linii:

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

Moje pytanie brzmi, czy późniejsze podejście oszczędza czas obliczeń i pamięć?


3
przy korzystaniu z "-vcodec copy -acodec copy" działa bardzo szybko :))
Savas Adar

@Antony, dlaczego nie zmierzysz czasu dla obu wersji (i nie spojrzysz na monitor pamięci, taki jak htop) i nie powiesz nam, jaka jest odpowiedź?
AlcubierreDrive

Pierwszy przykład robi to sekwencyjnie, podczas gdy drugi przykład używa wątków. Oba zrobią to samo, nie powinno nastąpić żadne zauważalne przyspieszenie. Jednak aby uprościć, można użyć ffmpeg strumień muxer segmentacji: ffmpeg.org/...
Mladen B.

1
Ten przykład wygląda bardzo źle! Dokumentacja ffmpeg mówi o opcji -ss: "Kiedy jest używana jako opcja wejściowa (przed -i), szuka w tym pliku wejściowym pozycji. Gdy jest używana jako opcja wyjściowa (przed nazwą pliku wyjściowego), dekoduje, ale odrzuca wejście do sygnatury czasowe osiągają pozycję ”. Używasz go w pozycji wyjściowej, więc twoja druga linia marnuje wysiłek dekodowania i odrzucania pierwszych 30 minut.
Lucian Wischik,

1
@LucianWischik, ale użycie -ssopcji wejściowej w drugim splicie może nie być dokładne, więc możesz nie uzyskać czystego podziału. IMO przykład OP jest bardziej poprawny.
jiggunjer,

Odpowiedzi:


82

Wiki ffmpeg odsyłają do tej strony w odniesieniu do „Jak efektywnie podzielić wideo”. Nie jestem przekonany, że ta strona odpowiada na to pytanie, więc zrobiłem zgodnie z sugestią @AlcubierreDrive…

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

Które wyjścia ...

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

Przetestowałem plik SD i HD po kilku uruchomieniach i odrobinie matematyki.

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  

Plik SD = 1,35 GB strumień transportowy DVB
Plik HD = 3,14 GB strumień transportowy DVB

Wniosek

Pojedyncze polecenie jest lepsze, jeśli obsługujesz HD, zgadza się z komentarzami podręczników na temat używania opcji -ss po pliku wejściowym w celu „powolnego wyszukiwania”. Pliki SD mają znikomą różnicę.

Wersja z dwoma poleceniami powinna być szybsza, dodając kolejne -ss przed plikiem wejściowym dla „szybkiego wyszukiwania”, po którym następuje dokładniejsze powolne wyszukiwanie.


Jeśli TS zawiera wiele programów (programy telewizyjne przechwycone przez DVB-T), jak można je podzielić? Na przykład mam plik TS zawierający piłkę nożną + gotowanie + kreskówkę. Jak mogę podzielić ten plik TS na 3 pliki mpg?
Dr Jacky

Użyłem twojej odpowiedzi w moim pytaniu tutaj ( stackoverflow.com/questions/41983940/… ), ale to nie zadziałało, jak myślisz, co robię źle?
utdev

1
W moim przypadku plik wynikowy nie zawierał wideo (tylko dźwięk). Po kilku eksperymentach znalazłem soultion. W ten sposób należy określić klucz „nie modyfikuj jakości” -q:v 0.
oklas

19

Oto przydatny skrypt, który pomaga w automatycznym dzieleniu: Skrypt do dzielenia filmów za pomocą ffmpeg

#!/bin/bash
 
# Written by Alexis Bezverkhyy <alexis@grapsus.net> 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

2
Ten sam komentarz dotyczy Ciebie, co w przypadku SEARAS. Pisanie plików wsadowych jest przydatne, gdy jest to absolutnie potrzebne i gdy nie masz innej dostępnej opcji, ponieważ nie jest przenośne. Na przykład nie będzie można uruchomić tego samego skryptu w systemie Windows. Gdy istnieją bardziej ogólne / przenośne sposoby, należy unikać skryptów wsadowych, aby zaoszczędzić czas potrzebny do ich przeniesienia. Ponieważ ffmpeg ma wiele sposobów rozwiązania tego problemu, właściwym sposobem byłoby użycie samego ffmpeg, bez pomocy skryptów.
Mladen B.

Niezły scenariusz. Napisałeś to? Czy jest na GitHubie? Chciałbym podać kilka sugestii :)
głosy

w przypadku mp4 sceny są uszkodzone. lepiej zamień kopię na: -vcodec libx264 -acodec aac
kishu

8

Z mojego doświadczenia wynika, że ​​nie używaj ffmpeg do dzielenia / łączenia. MP4Box, jest szybszy i lekki niż ffmpeg. Proszę, spróbuj. Np. Jeśli chcesz podzielić plik MP4 o wielkości 1400 MB na dwie części a 700 MB, możesz użyć następującego polecenia cmdl: MP4Box -splits 716800 input.mp4 np. Do połączenia dwóch plików możesz użyć:

MP4Box -cat file1.mp4 -cat file2.mp4 output.mp4

Lub jeśli potrzebujesz podziału według czasu, użyj -splitx StartTime:EndTime:

MP4Box -add input.mp4 -splitx 0:15 -new split.mp4


To było dokładnie to, czego potrzebowałem! Kiedy wycinałem za pomocą ffmpeg, klipy nie zaczynały się na klatkach kluczowych i miały dziwne zawieszanie się na końcach. Użycie MP4Box -splitz załatwiło sprawę!
mat.

1
jak mogę przyciąć wideo za pomocą Mp4Box z wieloma numerami? na przykład muszę mieć klipy podrzędne w ciągu kilku sekund: 5 - 8, 21 - 30, 12 - 18, więc potrzebuję trzech wyjściowych plików wideo.
mhndev

I jest znacznie łatwiejszy w użyciu EndTimeniż -t.
vmassuchetto


2

czy późniejsze podejście oszczędza czas i pamięć obliczeń?

Nie ma dużej różnicy między tymi dwoma przykładami, które podałeś. Pierwszy przykład tnie wideo sekwencyjnie, w 2 krokach, podczas gdy drugi przykład robi to w tym samym czasie (używając wątków). Żadne szczególne przyspieszenie nie będzie zauważalne. Możesz przeczytać więcej o tworzeniu wielu wyników za pomocą FFmpeg

Co więcej, to, czego możesz użyć (w ostatnim FFmpeg), to muxer segmentacji strumienia, który może:

strumienie wyjściowe do wielu oddzielnych plików o prawie ustalonym czasie trwania. Wzorzec nazwy pliku wyjściowego można ustawić w sposób podobny do image2 .


2

Oto prosty plik nietoperza systemu Windows do podzielenia przychodzącego pliku na 50 części. Każda część ma 1 minutę. Przepraszam za taki głupi scenariusz. Mam nadzieję, że lepiej jest mieć głupi skrypt Windows, zamiast go w ogóle nie mieć. Może to komuś pomoże. (Na podstawie „pliku bat for loop” z tej witryny).

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

Zasadniczo jest to pierwszy fragment kodu w pytaniu (kolejne ffmpegpolecenia) przepisany jako pętla. Nie odpowiada to na pytanie, czy takie podejście lub pojedyncze polecenie „zaoszczędzi czas obliczeń i pamięć”.
BACON

1

Nie testowałem ist, ale wygląda to obiecująco:

Podstawowy segmenter strumienia

Jest to oczywiście dzielenie AVI na segmenty o tym samym rozmiarze, co oznacza, że ​​te fragmenty nie tracą jakości, nie zwiększają pamięci ani nie muszą być ponownie obliczane.

Używa również kopii kodeka - czy to oznacza, że ​​może obsługiwać bardzo duże strumienie? Ponieważ to jest mój problem, chcę zepsuć moje avi, aby móc użyć filtra, aby pozbyć się zniekształceń. Ale całe avi działa godzinami.


-1

Oto doskonały sposób na podzielenie wideo. Robiłem to już wcześniej i dobrze mi się to sprawdza.

ffmpeg -i C:\xampp\htdocs\videoCutting\movie.mp4 -ss 00:00:00 -t 00:00:05 -async 1 C:\xampp\htdocs\videoCutting\SampleVideoNew.mp4 (Dla 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')(dla php).

Postępuj zgodnie z tym i jestem pewien, że będzie działać idealnie.


Dlaczego jest to „doskonały sposób” podziału wideo? Podobnie jak w przypadku wiersza poleceń w pytaniu, przechodzisz, -ia po nim następują -ssi -t. Pytanie dotyczy jednak tego, jak skutecznie wyodrębnić wiele segmentów z tego samego pliku wejściowego, podczas gdy wyodrębniasz tylko jeden segment. Nie rozumiem, jak to odpowiada na pytanie.
BACON

-2

jednym prostym sposobem jest użycie opcji przycinania z interfejsem API opartym na adresie URL publikacji .

po przesłaniu filmu wystarczy ustawić przesunięcie początkowe i końcowe w adresie URL (so_2, eo_2) w następujący sposób:

    https://media.publit.io/file/so_2,eo_2/tummy.mp4

spowoduje to natychmiastowe utworzenie nowych filmów, zaczynając od drugiej sekundy i długości 2 sekund. możesz w dowolny sposób dzielić filmy w ten sposób.


Pytanie brzmi, które jest bardziej wydajne z dwóch podejść do wyodrębniania wielu segmentów z pliku wejściowego z ffmpeg. Jeśli nie masz naprawdę, naprawdę szybkiego połączenia internetowego, myślę, że konieczność przesłania całego filmu do usługi w chmurze, a następnie pobrania wyników, znacznie wydłuży czas przetwarzania. Nawet tak, to nadal nie jest odpowiedź na pytanie, które podejście zffmpeg bardziej wydajne.
BACON
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.