How do I split a long video into multiple shorter videos efficiently?

6,910

This can be done with a simple shell script, in this case a Bash script. If you have a whitespace-delimited file as input, which contains the output file name, the start timestamp and the end timestamp, e.g.:

$ cat cuts.txt
foo.mp4 00:00:00 00:00:01
bar.mp4 00:01:20 00:02:00

Then read this with a simple loop and construct your ffmpeg command:

while read -r filename start end; do
  ffmpeg -i "input.mp4" -ss "$start" -to "$end" -c copy "$filename"
done < cuts.txt

This just cuts the bitstream without encoding – -c copy is a shorthand for -vcodec copy -acodec copy (and it copies subtitles as well). You can specify a video encoder (e.g. -c:v libx264) and an audio encoder (e.g., -c:a aac -b:a 192k) to re-encode the video.

A more portable, but basic version with Python 3:

#!/usr/bin/env python3
import subprocess
with open("cuts.txt") as f:
  for line in f.readlines():
    filename, start, end = line.strip().split(' ')
    cmd = ["ffmpeg", "-i", "input.mp4", "-ss", start, "-to", end, "-c", "copy", filename]
    subprocess.run(cmd, stderr=subprocess.STDOUT)

Note: If you run this on Windows, you should add ffmpeg to your PATH, or specify its full path like C:/Program Files/ffmpeg/bin/ffmpeg.exe.

Share:
6,910

Related videos on Youtube

Michael Horwitz
Author by

Michael Horwitz

Updated on September 18, 2022

Comments

  • Michael Horwitz
    Michael Horwitz almost 2 years

    Using ffmpeg I can specify the start time and duration of each segment. For example I wrote

    ffmpeg -i "originalvideo.mp4" -ss 00:00 -t 2:34 -vcodec copy -acodec copy "smallervideo1.mp4"
    

    I have a spreadsheet where I have 3 columns; name of smaller video, start time and end time. I could create each command separately for each video but that would take some time given I am splitting the sources files into close to 100 smaller videos.

    Is there a method where i can pass the values from the spreadsheet into ffmpeg and output each video with the appropriate name automatically?

  • Michael Horwitz
    Michael Horwitz almost 7 years
    Thanks @slhck. I have a spreadsheet but I a assume I can get it into that format easily. I will try this out.
  • slhck
    slhck almost 7 years
    You can just export it to CSV from Excel, for example, but use a single space as delimiter. Or if you have a comma as delimiter, use while read -r -d, filename start end … to specify another delimiter. (Use .split(',') in Python in that case.)
  • Michael Horwitz
    Michael Horwitz almost 7 years
    since I use Windows I went with the Python approach. I am stuck and Im not sure what the issue is. My Code is import subprocess with open("cuts3.txt") as f: for line in f.readlines(): filename, start, end = line.strip().split(' ') cmd = 'C:\ffmpeg\bin\ffmpeg.exe -i Recordings\recording6.6.17.mp4 -ss {start} -to {end} -c copy "{filename}"'.format(**locals()) subprocess.run(cmd, shell=True) print ("loop over") The txt file is Greetings.mp4 0:00:00 0:02:35 Introduction.mp4 0:02:35 0:05:10
  • slhck
    slhck almost 7 years
    @MichaelHorwitz Comments are not really useful for this kind of troubleshooting… block code formatting doesn't work there. But do you get any error messages? Note that for Windows you should use forward slashes to run the command.
  • slhck
    slhck almost 7 years
    See my edits above, maybe this works better for you.
  • Michael Horwitz
    Michael Horwitz almost 7 years
    I figured it out. My path had backslashes in it. Once I escaped them everything worked. import subprocess with open("cuts3.txt") as f: lines=f.readlines() for line in lines: filename, start, end = line.strip().split(' ') cmd = 'C:\\ffmpeg\\bin\\ffmpeg.exe -i recordings\\recording6.6.17.mp4 -ss {} -to {} -c copy "{}"'.format(start,end,filename) subprocess.run(cmd, shell=True)