【问题标题】:Using ffmpeg to split video files by size [closed]使用 ffmpeg 按大小分割视频文件 [关闭]
【发布时间】:2016-11-10 14:28:02
【问题描述】:

我正在尝试使用 ffmpeg 编写一个批处理文件,以自动执行多余的日常任务,即从以 4gb 块(这是大多数 DSLR 相机和 GoPro 的标准)记录的工作中获取素材,并将剪辑分割成 2gb 文件流媒体目的。这个想法是让脚本检查外部驱动器 FOOTAGE 的文件夹 @import 并在 2gb 之后拆分文件(因为最大大小为 4gb,这将减少多次拆分的需要)。

我也在尝试修改拆分文件的文件名,因此 FILE1 为 4gb,它拆分为 FILE1_1 和 FILE1_2,分别为 2gb。我所尝试的一切都只是将原始文件复制到两个新的相同文件中 - 没有拆分或任何东西。

在进行了一些谷歌搜索并阅读了此处的一些答案后,我找到了这篇文章,但它基于持续时间,而不是大小(以不同质量水平录制视频片段使这毫无意义):Split into equal parts and convert many mp4 videos using ffmpeg

有人可以帮我解决这个问题吗?我没有遇到任何可用的解决方案,使用我理解的方法,使用 -fs limit_size,我真的很想了解它是如何工作的。

更新:也发现了这个,但它已经四年没有更新了,我没有看到任何关于拆分的内容会被证明有帮助:

https://github.com/kcm1700/VideoSplitter/blob/master/

【问题讨论】:

    标签: bash video split ffmpeg clip


    【解决方案1】:

    我也遇到了同样的问题,在这里没有找到解决方案后,我为该工作编写了一个快速的 bash 脚本。

    特点:

    • 使用 ffmpeg 的 -fs-flag 来限制文件大小
    • 检查生成的视频部分的长度并计算下一部分的开始位置
    • 列举视频部分
    • 根据需要继续处理尽可能多的部分以包含整个源文件。
    • 允许自定义 ffmpeg 参数也可以一次性降低分辨率和质量。

    它只需要三个参数:源文件名、每个部分所需的文件大小和 ffmpeg 所需的参数。

    将文件拆分为 64MB 部分的示例调用:

    ./split-video.sh huge-video.mov 64000000 "-c:v libx264 -crf 23 -c:a copy -vf scale=960:-1"
    

    最后是脚本的源码:

    #!/bin/bash
    # Short script to split videos by filesize using ffmpeg by LukeLR
    
    if [ $# -ne 3 ]; then
        echo 'Illegal number of parameters. Needs 3 parameters:'
        echo 'Usage:'
        echo './split-video.sh FILE SIZELIMIT "FFMPEG_ARGS'
        echo 
        echo 'Parameters:'
        echo '    - FILE:        Name of the video file to split'
        echo '    - SIZELIMIT:   Maximum file size of each part (in bytes)'
        echo '    - FFMPEG_ARGS: Additional arguments to pass to each ffmpeg-call'
        echo '                   (video format and quality options etc.)'
        exit 1
    fi
    
    FILE="$1"
    SIZELIMIT="$2"
    FFMPEG_ARGS="$3"
    
    # Duration of the source video
    DURATION=$(ffprobe -i "$FILE" -show_entries format=duration -v quiet -of default=noprint_wrappers=1:nokey=1|cut -d. -f1)
    
    # Duration that has been encoded so far
    CUR_DURATION=0
    
    # Filename of the source video (without extension)
    BASENAME="${FILE%.*}"
    
    # Extension for the video parts
    #EXTENSION="${FILE##*.}"
    EXTENSION="mp4"
    
    # Number of the current video part
    i=1
    
    # Filename of the next video part
    NEXTFILENAME="$BASENAME-$i.$EXTENSION"
    
    echo "Duration of source video: $DURATION"
    
    # Until the duration of all partial videos has reached the duration of the source video
    while [[ $CUR_DURATION -lt $DURATION ]]; do
        # Encode next part
        echo ffmpeg -i "$FILE" -ss "$CUR_DURATION" -fs "$SIZELIMIT" $FFMPEG_ARGS "$NEXTFILENAME"
        ffmpeg -ss "$CUR_DURATION" -i "$FILE" -fs "$SIZELIMIT" $FFMPEG_ARGS "$NEXTFILENAME"
    
        # Duration of the new part
        NEW_DURATION=$(ffprobe -i "$NEXTFILENAME" -show_entries format=duration -v quiet -of default=noprint_wrappers=1:nokey=1|cut -d. -f1)
    
        # Total duration encoded so far
        CUR_DURATION=$((CUR_DURATION + NEW_DURATION))
    
        i=$((i + 1))
    
        echo "Duration of $NEXTFILENAME: $NEW_DURATION"
        echo "Part No. $i starts at $CUR_DURATION"
    
        NEXTFILENAME="$BASENAME-$i.$EXTENSION"
    done
    

    希望,这会有所帮助:)

    【讨论】:

    • 我可以知道您提供的此解决方案是否会降低块的视频质量? ffmpeg 菜鸟在这里
    • 这完全取决于您传递的 FFMPEG_ARGS (第三个参数)。如果你什么都不传递,ffmpeg 会根据你的输出容器自动选择设置,这很可能意味着它会重新压缩内容,导致不必要的 CPU 负载和质量损失。因此建议至少将-c copy 作为该脚本的第三个参数传递,因为这将指示ffmpeg 复制视频和音频数据而不复制它。这使得转换速度更快(唯一的限制是硬盘速度),同时保持原始质量。
    • 谢谢。自从发表此评论以来,我对 FFMPEG 有了更多的了解。我当时用过这个脚本,但是遇到了一些麻烦,不记得了,我再看一遍。
    • 你的剧本太棒了!我认为默认行为应该是未修改的副本,并且没有重新编码。
    • 这个脚本只制作了第一部分并且失败了。获取持续时间的ffprobe 命令为源文件和第一部分文件返回相同的持续时间。因为那个while循环只执行一次。
    【解决方案2】:

    您可以使用 mp4box 在一个命令中执行此操作。

    mp4box -splits 2000000 filename.mp4
    

    splits 参数的值以千字节为单位。由于存在关键帧,片段不会正好是 2GB。

    【讨论】:

    • 我以为是字节?那不是 2MB 吗?
    • 不,它以 kB 为单位。
    • 当我尝试这个工具时,它把视频分成了 3 个部分,而它只需要 2 个部分。最后一段是120kb。前一部分剩余超过 100 MB 的可用空间。
    • 这个命令不起作用。它只创建 1 个文件,其大小在参数上设置
    • 取决于关键帧的位置。
    【解决方案3】:

    一个想法是使用带有选项 -fs 的 ffmpeg。这将限制文件大小。输出文件的大小略大于请求的文件大小。

    这只会创建一个文件。但是你可以建立一个循环,直到整个文件被分割。

    首先创建文件的一部分,然后检查它的长度:

    ffprobe -i input.file -show_format -v quiet | sed -n 's/duration=//p'
    

    然后使用 -ss 启动另一个具有偏移量的文件

    之后进行另一轮编码,直到整个文件被分割。您还可以对音频和视频使用流式复制

    【讨论】:

    • 你能发布一个使用 -fs 和 -ss 的脚本示例吗?
    猜你喜欢
    • 2016-09-08
    • 2021-01-02
    • 1970-01-01
    • 1970-01-01
    • 2021-01-16
    • 2019-02-13
    • 2015-05-18
    相关资源
    最近更新 更多