Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using ffmpeg to split video files by size [closed]

I'm trying to write a batch file using ffmpeg to automate the redundant daily task of taking footage from work that's recorded in 4gb blocks (which is standard in most DSLR cameras & GoPro's), and split the clips into 2gb files for streaming purposes. The idea is to have the script check external drive FOOTAGE's folder @import and split files after 2gb (since the max size is 4gb, this will alleviate the need for more than one split).

I'm also trying to amend the filenames of the split files, so FILE1 is 4gb, it splits into FILE1_1 and FILE1_2 which are 2gb each, respectively. Everything I've tried has just copied the original file into two new, identical files - no split or anything.

After doing some Googling and reading some of the answers here, I found this post, but it's based on duration, not size (recording video footage at varying levels of quality makes this pointless): Split into equal parts and convert many mp4 videos using ffmpeg

Can someone help me with this? I haven't come across any usable solutions utilizing what I understand to be the method, using -fs limit_size, and I really want to understand how this works.

UPDATE: Also found this, but it hasn't been updated in four years and I don't see anything in there regarding splitting that will prove helpful:

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

like image 670
user2548469 Avatar asked Jul 08 '16 05:07

user2548469


People also ask

How can I split a video into parts online?

You can split your video into several parts in a few simple steps using VEED. Simply upload your video to VEED and move the indicator or slider across the timeline. Click on the 'Split' button right above the editing pane or press the 'S' key on your keyboard. You can do this process as many times as needed.

How do I set video duration in ffmpeg?

Use the -t option to specify a time limit: `-t duration' Restrict the transcoded/captured video sequence to the duration specified in seconds. hh:mm:ss[.


1 Answers

I just had the same problem, and after I didn't find a solution here, I wrote a quick bash script for that job.

Features:

  • Use ffmpeg's -fs-flag to limit filesize
  • Check length of resulting video part and calculate where to start next part
  • Enumerate video parts
  • proceed with as many parts as needed to contain the whole source file.
  • Allow for custom ffmpeg arguments to also reduce resolution and quality in one pass.

It takes only three arguments: The source filename, the desired filesize of each part and the desired arguments for ffmpeg.

Example call to split a file into 64MB parts:

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

Finally, the source code of the script:

#!/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

Hope, that helps :)

like image 153
LukeLR Avatar answered Sep 25 '22 03:09

LukeLR