首页 文章

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

提问于
浏览
89

我希望将大型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

但是根据ffmpeg的联机帮助页,我可以使用 one 行从一个输入文件中创建多个输出文件:

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

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

10 回答

  • 0

    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
    

    哪个输出......

    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 file = 1.35GB DVB传输流
    HD file = 3.14GB DVB传输流

    结论

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

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

  • 71

    这是一个有用的脚本,它可以帮助您自动拆分:A script for splitting videos using 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
    
  • 1

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

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

  • -1

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

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

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

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

  • 0

    后面的方法是否节省了计算时间和内存?

    您提供的这两个示例之间没有太大区别 . 第一个示例以2个步骤顺序切割视频,而第二个示例同时执行(使用线程) . 没有特别的加速将是显而易见的 . 你可以阅读更多关于creating multiple outputs with FFmpeg的信息

    此外,您可以使用的(最近的FFmpeg)是stream segmenter muxer,它可以:

    输出流到几乎固定持续时间的多个单独文件 . 输出文件名模式可以以类似于image2的方式设置 .

  • 5

    这是一个简单的Windows bat文件,用于将传入的文件拆分为50个部分 . 每个部分的长度为1分钟 . 抱歉这样的哑剧本 . 我希望有一个愚蠢的Windows脚本,而不是根本没有它 . 也许它对某人有帮助 . (基于此站点的“bat file 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
    
  • 17

    没有测试,但看起来很有希望:

    Basic stream segmenter

    显然,将AVI分成相同大小的段,这意味着这些块不会降低质量或增加内存,或者必须重新计算 .

    它还使用编解码器副本 - 这是否意味着它可以处理非常大的流?因为这是我的问题,我想打破我的avi所以我可以使用过滤器摆脱扭曲 . 但整个avi运行了几个小时 .

  • 5

    这是分割视频的完美方式 . 我以前做过,而且对我来说效果很好 .

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

    请遵循这一点,我相信它会完美运作 .

  • 1

    一种简单的方法是使用publitio url-based api的修剪选项 .

    上传视频后,只需在网址(so_2,eo_2)中设置起始偏移量和结束偏移量,如下所示:

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

    这将立即创建从第2秒和2秒开始的新视频 . 无论如何,你都可以通过这种方式分割视频 .

  • -6

    事实证明,后一种情况下的文件大小将与时间片成比例相等 .

相关问题