3

I have a bunch of .mp4 files (DRM free). Each file comprises two episodes of a kids TV show. I would like to simply split the file in two without re-encoding. What's the best way to do this? Preferably with a GUI (as I need to skip to the correct part of each file to find the divider between the two episodes).

Thanks,

5
  • 2
    Have you read the answers to this question? A few of them suggest GUI-based solutions too. Jan 30, 2016 at 21:30
  • 3
    Possible duplicate of Splitting an MP4 file Jan 30, 2016 at 21:32
  • You could simply find out the point where to split by watching it in a normal viewer (VLC, etc) and then use the terminal, as most things are command line based in ubuntu Jan 30, 2016 at 21:34
  • I have been trimming a lot of videos lately using something similar to what I posted below. The combo of opening in VLC, and then running the script is probably just as fast if not faster than a GUI application.
    – jbrock
    Jan 31, 2016 at 21:54
  • If they all split at exactly the same place, then I'd be glad to update the below script so it is a batch operation. That would save a lot of time.
    – jbrock
    Jan 31, 2016 at 21:56

2 Answers 2

5

I recommend opening the video in a media player to find the time where you want to split it. Then you can use ffmpeg with the following script. It does not re-encode the video.

#!/bin/bash

# Split Video Script
# Usage: script_name file_name split-point
# Example: split_video_script bugs_bunny.mp4 31:23
# Instructions:     
# 1. Type the name of your script (if it is already added to ~/bin and marked as executable). 
# 2. Type the file name including path to it if necessary. 
# 3. Type the time where you want to split the video. It goes in minutes:seconds

# Get length in seconds
length=$(echo "$2" | awk -F: '{print ($1 * 60) + $2}')

# Get filename without extension
fname="${1%.*}"

# First half
ffmpeg -i "${fname}.mp4" -c copy -t "$length" "${fname}1.mp4"

# Second half
ffmpeg -i "${fname}.mp4" -c copy -ss "$length" "${fname}2.mp4"

Update: I recently needed to update this script because of an issue with the second half. So, now I have to process the second half of it. You would add in the parameters that are specific to your original video. You can use mediainfo, ffprobe or ffmpeg -i to find the needed information about your original video.

#!/bin/bash

if [ -z "$1" ]; then
    echo "Usage: $0 file-name"
    exit 1
fi

read -p "Enter time to split video (hh:mm:ss.mmm) " split_time

ext="${1##*.}"
fname="${1%.*}"

# First half
ffmpeg -i "$1" -c copy -t "$split_time" -c:s copy "${fname}1.${ext}"

# Second half
ffmpeg -ss "$split_time" -i "$1" -c:v libx264 -crf 17 -preset veryfast -r 30 -s 1920x1080 -c:a aac -ac 2 -b:a 256k -ar 44100 -pix_fmt yuv420p -movflags faststart -c:s copy "${fname}2.${ext}"
2
  • The command generates two parts. The first part is fine. But the second video plays with a black screen for the first couple of seconds. Any idea how to fix that problem?
    – nbkhope
    Apr 24, 2021 at 3:59
  • Thank you for bringing this to my attention. I had updated my script recently due to the same issue. I have posted it above. Best of luck.
    – jbrock
    Apr 24, 2021 at 20:31
0

I needed to use your script to split a video into thirds instead of splitting the mp4 into two. Here is my version of the script:

#!/bin/bash

NUM_OF_SPLITS=3

main() {
    # Requires: $ `brew install ffmpeg`

    # total length in seconds 
    total_length=$(ffprobe -v quiet -of csv=p=0 -show_entries format=duration "$1")

    # Get filename without extension
    fname="${1%.*}"
    split_time=$(echo "$total_length"/"$NUM_OF_SPLITS" | bc -l)

    declare -a start_times
    declare -a end_times

    for((i=0; i < $num_of_splits; i++)); do
        local output_file="${fname}_"part$i".mp4"
        if [[ "$i" -eq 0 ]]; then
            local start_time=0
            local end_time="$split_time"

            ffmpeg -i "${fname}.mp4" -c copy -t "$end_time" "$output_file"
        else
            local start_time="${end_times[$i-1]}"
            local end_time=$(echo "$start_time "*" 2" | bc -l)

            # echo "Start time: $start_time"
            # echo "End time: $end_time"

            ffmpeg -ss "$start_time" -to "$end_time"  -i "${fname}.mp4" -c copy "$output_file"
        fi

        start_times+=($start_time)
        end_times+=("$end_time")
    done

}

# Split Video Script
# Example: split_video_script bugs_bunny.mp4
# Instructions:     
# 1. Type the name of your script (if it is already added to ~/bin and marked as executable). 
# 2. Type the file name including path to it if necessary. 

main "$1"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.