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,

  • 2
    Have you read the answers to this question? A few of them suggest GUI-based solutions too. – usmanayubsh Jan 30 '16 at 21:30
  • 3
  • 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 – Info-Screen Jan 30 '16 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 '16 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 '16 at 21:56

2 Answers2

7

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}"

jbrock
  • 3,307
  • 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 '21 at 03: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 '21 at 20:31
  • Works great for me, thank you :+1: – Wim Jul 20 '23 at 15:32
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"