Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an elegant way to split a file by chapter using ffmpeg?

Tags:

ffmpeg

In this page, Albert Armea share a code to split videos by chapter using ffmpeg. The code is straight forward, but not quite good-looking.

ffmpeg -i "$SOURCE.$EXT" 2>&1 | grep Chapter | sed -E "s/ *Chapter #([0-9]+\.[0-9]+): start ([0-9]+\.[0-9]+), end ([0-9]+\.[0-9]+)/-i \"$SOURCE.$EXT\" -vcodec copy -acodec copy -ss \2 -to \3 \"$SOURCE-\1.$EXT\"/" | xargs -n 11 ffmpeg 

Is there an elegant way to do this job?

like image 277
Kattern Avatar asked May 18 '15 14:05

Kattern


People also ask

How do I split mp4 into chapters?

Split MP4 Into Chapters 1st a) Double click on a video in the Video Folder. 1st b) Or open a video directly via the menu File → Open Video. 2nd The video will be opened in a separate section where you can check and uncheck the chapters. 3rd Click Export Chapters Separately and choose a folder.

How to split a video into parts using FFmpeg?

1 Open Terminal (in Mac) and enter the following command to navigate to your video folder. ... 2 The next command splits your video into frames and stores each one as a separate image thumbnail file. ffmpeg -i video.mp4 thumb%04d.jpg -hide_banner That’s it. ... 3 FFmpeg Split Video into Parts of Equal Duration

What is the difference between-I and-Vcodec in FFmpeg?

-i is the input file, in the above case it's a file called 'input.mp4'. -vcodec stands for the video codec to encode the output file. 'copy' means you're using the same codec as the input file. -acodec is the audio codec. output.mp4 is the output file, you can rename it as you need. Method 1. FFmpeg Split Video into Frames

How to silence audio files in FFmpeg?

ffmpeg -i input.mp3 -af silencedetect -f null - Note the default minimum length for silence is set to 2 seconds, but it can be adjusted. See ffmpeg -h filter=silencedetect. There is also a silenceremove filter.

How to create chunks with ffmpeg?

Here's the source and list of Commonly used FFmpeg commands. If you want to create really same Chunks must force ffmpeg to create i-frame on the every chunks' first frame so you can use this command for create 0.5 second chunk. Faced the same problem earlier and put together a simple Python script to do just that (using FFMpeg).


1 Answers

(Edit: This tip came from https://github.com/phiresky via this issue: https://github.com/harryjackson/ffmpeg_split/issues/2)

You can get chapters using:

ffprobe -i fname -print_format json -show_chapters -loglevel error 

If I was writing this again I'd use ffprobe's json options

(Original answer follows)

This is a working python script. I tested it on several videos and it worked well. Python isn't my first language but I noticed you use it so I figure writing it in Python might make more sense. I've added it to Github. If you want to improve please submit pull requests.

#!/usr/bin/env python import os import re import subprocess as sp from subprocess import * from optparse import OptionParser  def parseChapters(filename):   chapters = []   command = [ "ffmpeg", '-i', filename]   output = ""   try:     # ffmpeg requires an output file and so it errors      # when it does not get one so we need to capture stderr,      # not stdout.     output = sp.check_output(command, stderr=sp.STDOUT, universal_newlines=True)   except CalledProcessError, e:     output = e.output     for line in iter(output.splitlines()):     m = re.match(r".*Chapter #(\d+:\d+): start (\d+\.\d+), end (\d+\.\d+).*", line)     num = 0      if m != None:       chapters.append({ "name": m.group(1), "start": m.group(2), "end": m.group(3)})       num += 1   return chapters  def getChapters():   parser = OptionParser(usage="usage: %prog [options] filename", version="%prog 1.0")   parser.add_option("-f", "--file",dest="infile", help="Input File", metavar="FILE")   (options, args) = parser.parse_args()   if not options.infile:     parser.error('Filename required')   chapters = parseChapters(options.infile)   fbase, fext = os.path.splitext(options.infile)   for chap in chapters:     print "start:" +  chap['start']     chap['outfile'] = fbase + "-ch-"+ chap['name'] + fext     chap['origfile'] = options.infile     print chap['outfile']   return chapters  def convertChapters(chapters):   for chap in chapters:     print "start:" +  chap['start']     print chap     command = [         "ffmpeg", '-i', chap['origfile'],         '-vcodec', 'copy',         '-acodec', 'copy',         '-ss', chap['start'],         '-to', chap['end'],         chap['outfile']]     output = ""     try:       # ffmpeg requires an output file and so it errors        # when it does not get one       output = sp.check_output(command, stderr=sp.STDOUT, universal_newlines=True)     except CalledProcessError, e:       output = e.output       raise RuntimeError("command '{}' return with error (code {}): {}".format(e.cmd, e.returncode, e.output))  if __name__ == '__main__':   chapters = getChapters()   convertChapters(chapters) 
like image 67
Harry Avatar answered Oct 14 '22 13:10

Harry