2011-04-13 105 views
70

我希望將大型avi視頻分成兩個較小的連續視頻。我正在使用ffmpeg。FFmpeg:如何高效地分割視頻?

一種方法是運行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 

但根據的ffmpeg的聯機幫助,我可以只使用一個線從一個輸入文件進行多份輸出中的文件:

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 

我的問題是,後面的方法是否節省了計算時間和內存?

+3

stackoverflow.com用於編程相關的問題。嘗試superuser.com(這個問題可能會移到那裏,只需要更多的移動投票)。 – 2011-04-13 15:33:41

+0

那麼它可以節省時間嗎? – rogerdpack 2011-09-27 18:29:00

+2

當使用「-vcodec副本-acodec副本」它是非常快:)) – 2012-05-02 20:39:55

回答

54

ffmpeg維基鏈接參考「如何高效地分割視頻」鏈接回到此頁面。我不相信這個頁面可以回答這個問題,所以我就像@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 

哪個輸出...

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 

我測試了SD & HD文件,幾運行&一點數學之後。

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文件 = 1.35GB DVB傳輸流
HD文件 = 3.14GB DVB傳輸流

結論

單指令是更好,如果你正在處理HD,它同意在輸入文件之後使用-ss進行「慢搜尋」的手冊評論。 SD文件的差異可以忽略不計。

這兩個命令版本應該更快,在輸入文件之前添加另一個-ss,以進行「快速搜索」,然後進行更準確的慢搜索。

+3

完美工作,讚美你的努力! – Kartos 2014-01-03 03:22:03

+0

如果TS包含多個節目(由DVB-T捕獲的電視節目),如何分割?例如,我有一個包含足球+烹飪+卡通的TS文件。如何將此TS文件分割爲3 mpg文件? – 2015-07-20 12:35:13

+0

我在這裏用我的問題的答案(http://stackoverflow.com/questions/41983940/ffmpeg-disassemble-video-into-parts)但它沒有工作,你認爲我做錯了什麼? – utdev 2017-02-01 15:58:14

-5

事實證明,在後面的情況下文件大小將與時間片成比例地等效。

+2

我不確定這會回答提問者提出的問題:他擔心計算時間和內存,而不是文件大小。 – 2012-11-12 19:40:36

15

這裏是一個有用的腳本,它可以幫助你自動分割:A script for splitting videos using 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 
+1

對於你來說,SEARAS同樣也有評論。編寫批處理文件在絕對需要時以及當您沒有其他選項可用時非常有用,因爲它不可移植。例如,您將無法在Windows上運行相同的腳本。當有更多的通用/便攜式方法時,應避免使用批處理腳本,以節省移植它們所需的時間。由於ffmpeg有多種方法來解決這個問題,所以正確的方法是單獨使用ffmpeg,而不需要腳本的幫助。 – 2013-08-24 10:00:53

+2

tnx腳本) – gaRex 2015-12-23 19:17:05

+0

尼斯腳本。你寫了嗎?它在GitHub上嗎?我想提出一些建議:) – user3155368 2017-01-21 04:41:07

1

並在後一種方法節省計算時間和內存?

您提供的這兩個示例之間沒有太大的區別。第一個示例按2個步驟順序剪切視頻,而第二個示例同時剪裁視頻(使用線程)。沒有特別的加速將是顯而易見的。你可以閱讀更多關於creating multiple outputs with FFmpeg

更進一步,你可以使用(在最近的FFmpeg)什麼是stream segmenter muxer它可以:

輸出流的數量近固定時長的單獨的文件。輸出文件名稱模式可以以類似於image2的方式設置。

0

沒有測試IST,但是這看起來很有希望:

Basic stream segmenter

這顯然是分裂成AVI大小相同,這意味着這些細分大塊不鬆質量或增加內存或必須重新計算。

它也使用編解碼器副本 - 這是否意味着它可以處理非常大的流?因爲這是我的問題,我想分解我的AVI,所以我可以使用過濾器來擺脫失真。但是整個avi運行數小時。

3

根據我的經驗,不要使用ffmpeg進行拆分/連接。 MP4Box,比ffmpeg更快更輕。請嘗試。 比如,如果你想要一個1400MB MP4文件分割成兩個部分,你可以使用下面的CMDL一個700MB: MP4Box -splits 716800 input.mp4 例如,用於連接兩個文件,你可以使用:

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

這正是我需要的!當我用ffmpeg剪輯時,剪輯沒有從關鍵幀開始,並且在結尾處有奇怪的凍結。使用MP4Box -splitz取得了訣竅! – matt 2016-12-12 00:12:44

2

下面是一個簡單的Windows BAT文件將傳入文件分成50個部分。每個部分的長度均爲1分鐘。對不起,這種愚蠢的腳本。我希望最好有一個愚蠢的Windows腳本,而不是根本沒有它。也許它有助於某人。 (基於來自本網站的「bat for loop」)

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