使用ffmpeg按大小分割视频文件

use*_*469 5 bash video split ffmpeg clip

我正在尝试使用ffmpeg编写批处理文件,以自动执行从4gb块(大多数DSLR相机和GoPro的标准配置)中录制的镜头中获取素材的日常日常任务,并将片段分成2gb文件以进行流式传输。这个想法是让脚本在2gb之后检查外部驱动器FOOTAGE的文件夹@import并分割文件(由于最大大小为4gb,这将减少对多个分割的需要)。

我还试图修改拆分文件的文件名,因此FILE1为4gb,它将拆分为FILE1_1和FILE1_2,它们分别为2gb。我尝试过的所有操作都只是将原始文件复制到两个相同的新文件中-没有拆分或任何内容。

在做完谷歌搜索并阅读了一些答案之后,我发现了这篇文章,但这是根据持续时间而不是大小(录制质量不同的视频片段使这毫无意义):分成相等的部分,并使用ffmpeg转换许多mp4视频

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

更新:也发现了这一点,但是四年来它都没有更新,我在那儿看不到任何有关拆分的信息,这将证明是有帮助的:

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

Luk*_*eLR 6

我只是遇到了同样的问题,在这里找不到解决方案之后,我为此工作编写了一个快速的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"
Run Code Online (Sandbox Code Playgroud)

最后,脚本的源代码:

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

希望有帮助:)

  • 我可以知道您提供的这个解决方案是否会降低块的视频质量?ffmpeg菜鸟在这里 (2认同)
  • 你的剧本太棒了!我认为默认行为应该是未修改的副本,并且不需要重新编码。 (2认同)

Gya*_*yan 5

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

mp4box -splits 2000000 filename.mp4
Run Code Online (Sandbox Code Playgroud)

其中,splits参数取值(以千字节为单位)。由于关键帧的存在,段将不完全是2GB。


小智 2

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

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

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

ffprobe -i input.file -show_format -v quiet | sed -n 's/duration=//p'
Run Code Online (Sandbox Code Playgroud)

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

之后再进行一轮编码,直到整个文件被分割。您还可以使用音频和视频的流副本

  • 您可以发布使用 -fs 和 -ss 的脚本示例吗? (3认同)