FFmpeg:如何有效地分割视频?

Ant*_*ony 98 ffmpeg

我希望将大型AVI视频分成两个较小的连续视频.我正在使用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
Run Code Online (Sandbox Code Playgroud)

但根据的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
Run Code Online (Sandbox Code Playgroud)

我的问题是,后一种方法是否节省了计算时间和内存?

小智 79

ffmpeg wiki链接回此页面,参考"如何有效地分割视频".我不相信这个页面回答了这个问题,所以我做了@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
Run Code Online (Sandbox Code Playgroud)

哪个输出......

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
Run Code Online (Sandbox Code Playgroud)

经过几次运行和一些数学运算后,我测试了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  
Run Code Online (Sandbox Code Playgroud)

SD文件 = 1.35GB DVB传输流
HD文件 = 3.14GB DVB传输流

结论

如果您正在处理HD,单个命令会更好,它同意手册在输入文件后使用-ss进行"慢速搜索"的注释.SD文件的差异可以忽略不计.

两个命令版本应该更快,在输入文件之前添加另一个-ss用于'快速搜索',然后是更准确的慢搜索.

  • 在我的情况下,结果文件没有视频(只有音频)。经过一些实验,我找到了灵魂。它需要像这样`-q:v 0` 指定“不修改质量”的键。 (2认同)

Mar*_* C. 19

这是一个有用的脚本,它可以帮助您自动分割:使用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
Run Code Online (Sandbox Code Playgroud)

  • 与SEARAS相同的评论.编写批处理文件在绝对需要时以及没有其他可用选项时非常有用,因为它不可移植.例如,您将无法在Windows上运行相同的脚本.当存在更多通用/可移植方式时,应避免使用批处理脚本,以节省移植它们所需的时间.由于ffmpeg有多种方法可以解决这个问题,因此正确的方法是单独使用ffmpeg,而无需脚本的帮助. (2认同)

rog*_*ack 5

http://ffmpeg.org/trac/ffmpeg/wiki/Seeking%20with%20FFmpeg也可能对你有用.此外,ffmpeg还有一个可能有效的段复用器.

无论如何,我的猜测是将它们组合成一个命令可以节省时间.


Cla*_*sic 5

根据我的经验,不要使用ffmpeg进行拆分/连接.MP4Box比ffmpeg更快更轻.请尝试.例如,如果要将1400mb MP4文件拆分为两个部分700mb,则可以使用以下cmdl: MP4Box -splits 716800 input.mp4 例如,对于连接两个文件,您可以使用:

MP4Box -cat file1.mp4 -cat file2.mp4 output.mp4
Run Code Online (Sandbox Code Playgroud)

或者如果您需要按时间拆分,请使用-splitx StartTime:EndTime:

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