Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

There is often a need in the open source or active developer community to publish large video segments online. (Meet-up videos, campouts, tech talks...) Being that I am a developer and not a videographer I have no desire to fork out the extra scratch on a premium Vimeo account. How then do I take a 12.5 GB (1:20:00) MPEG tech talk video and slice it into 00:10:00 segments for easy uploading to video sharing sites?

share|improve this question
    
Special thanks to @StevenD for accommodating the new tags. –  Gabriel Sep 6 '10 at 17:24

4 Answers 4

up vote 21 down vote accepted
$ ffmpeg -i source-file.foo -ss 0 -t 600 first-10-min.m4v
$ ffmpeg -i source-file.foo -ss 600 -t 600 second-10-min.m4v
$ ffmpeg -i source-file.foo -ss 1200 -t 600 third-10-min.m4v
...

Wrapping this up into a script to do it in a loop wouldn't be hard.

Beware that if you try to calculate the number of iterations based on the duration output from an ffprobe call that this is estimated from the average bit rate at the start of the clip and the clip's file size. ffprobe doesn't scan the entire file for speed reasons, so it can be quite inaccurate.

Another thing to be aware of is that the position of the -ss option on the command line matters. Where I have it now is slow but accurate. The first version of this answer gave the fast but inaccurate alternative. The linked article also describes a mostly-fast-but-still-accurate alternative, which you pay for with a bit of complexity.

All that aside, I don't think you really want to be cutting at exactly 10 minutes for each clip. That will put cuts right in the middle of sentences, even words. I think you should be using a video editor or player to find natural cut points just shy of 10 minutes apart.

Assuming your file is in a format that YouTube can accept directly, you don't have to reencode to get segments. Just pass the natural cut point offsets to ffmpeg, telling it to pass the encoded A/V through untouched by using the "copy" codec:

$ ffmpeg -i source.m4v -ss 0 -t 593.3 -vcodec copy -acodec copy part1.m4v
$ ffmpeg -i source.m4v -ss 593.3 -t 551.64 -vcodec copy -acodec copy part2.m4v
$ ffmpeg -i source.m4v -ss 1144.94 -t 581.25 -vcodec copy -acodec copy part3.m4v
...

The start point for every command after the first is the previous command's start point plus the previous command's duration.

share|improve this answer
1  
"cutting at exactly 10 minutes for each clip" is a good point. –  Chris Sep 7 '10 at 11:42
    
maybe by using the -show_packets param you can make it more accurate. –  rogerdpack Jun 13 '11 at 21:36
    
Using -ss after specifying the input file with -i is much slower but more accurate. Here for details. –  Francesco Turco Sep 14 '12 at 10:30
    
Thanks, @FrancescoTurco. I've updated the answer accordingly. –  Warren Young Sep 14 '12 at 10:40
    
How can I find these "natural cut point offsets"? –  JBernardo Sep 14 '12 at 19:58

Actually you can upload bigger files to youtube, if you verify your account with your mobile phone number.

share|improve this answer

Faced the same problem earlier and put together a simple Python script to do just that (using FFMpeg). Available here: https://github.com/c0decracker/video-splitter, and pasted below:

#!/usr/bin/env python
import subprocess
import re
import math
from optparse import OptionParser
length_regexp = 'Duration: (\d{2}):(\d{2}):(\d{2})\.\d+,'
re_length = re.compile(length_regexp)
def main():
    (filename, split_length) = parse_options()
    if split_length <= 0:
        print "Split length can't be 0"
        raise SystemExit
    output = subprocess.Popen("ffmpeg -i '"+filename+"' 2>&1 | grep 'Duration'",
                              shell = True,
                              stdout = subprocess.PIPE
    ).stdout.read()
    print output
    matches = re_length.search(output)
    if matches:
        video_length = int(matches.group(1)) * 3600 + \
                       int(matches.group(2)) * 60 + \
                       int(matches.group(3))
        print "Video length in seconds: "+str(video_length)
else:
    print "Can't determine video length."
    raise SystemExit
split_count = int(math.ceil(video_length/float(split_length)))
if(split_count == 1):
    print "Video length is less then the target split length."
    raise SystemExit
split_cmd = "ffmpeg -i '"+filename+"' -vcodec copy "
for n in range(0, split_count):
    split_str = ""
    if n == 0:
        split_start = 0
else:
    split_start = split_length * n
    split_str += " -ss "+str(split_start)+" -t "+str(split_length) + \
                 " '"+filename[:-4] + "-" + str(n) + "." + filename[-3:] + \
                 "'"
print "About to run: "+split_cmd+split_str
output = subprocess.Popen(split_cmd+split_str, shell = True, stdout =
                          subprocess.PIPE).stdout.read()
def parse_options():
    parser = OptionParser()
    parser.add_option("-f", "--file",
                      dest = "filename",
                      help = "file to split, for example sample.avi",
                      type = "string",
                      action = "store"
    )
parser.add_option("-s", "--split-size",
                  dest = "split_size",
                  help = "split or chunk size in seconds, for example 10",
                  type = "int",
                  action = "store"
)
(options, args) = parser.parse_args()
if options.filename and options.split_size:
    return (options.filename, options.split_size)
else:
    parser.print_help()
    raise SystemExit
if __name__ == '__main__':
    try:
        main()
except Exception, e:
    print "Exception occured running main():"
    print str(e)
share|improve this answer
1  
Next time do this please in a comment. Link-only answers aren't really liked here, and the same if you advert your site. If it is an opensource project with source code, maybe it is an exception, but I now risked my reviewing privileges by not voting for the removal of your answer. And yes, you can't post comments, but after you collected 5 upvotes (which seems very fast in your case) you will. –  Peter Horvath Nov 21 at 0:40
    
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. –  HalosGhost Nov 21 at 1:18
    
Hi and welcome to the site. Please don't post link only answers. While your script itself would probably make a great answer, a link to it is not an answer. It is a signpost pointing to an answer. More on that here. Since you kindly gave the link, I went ahead and included the script in the body of your answer. If you object to that, please delete the answer altogether. –  terdon Nov 21 at 1:54

Note the exact punctuation of the alternative format is -ss mm:ss.xxx. I struggled for hours trying to use the intuitive-but-wrong mm:ss:xx to no avail.

$ man ffmpeg | grep -C1 position

-ss position
Seek to given time position in seconds. "hh:mm:ss[.xxx]" syntax is also supported.

References here and here.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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