FFConcat Class: Concatenating Media Files

FFmpeg supports different approaches to concatenate media files as described on their Wiki Page. If many files are concatenated, any of these approaches results in lengthy command (or a ffconcat listing file). The ffmpegio.FFConcat class primarily focus on the concat demuxer and abstracts the ffconcat listing file when running ffmpegio commands.

class ffmpegio.FFConcat(script=None, pipe_url=None, ffconcat_url=None)

Create FFmpeg concat demuxer source generator

Parameters:
  • script (str, optional) – concat script to parse, defaults to None (empty script)

  • pipe_url (bool, optional) – stdin pipe or None to use a temp file, defaults to None

FFConcat instance is intended to be used as an input url object when invoking ffmpegprocess.run or ffmpegprocess.Popen. The FFmpeg command parser stringify the ConatDemuxer instance to either the temp file path or the pipe name, depending on the chosen operation mode. The temporary listing is automatically generated within the FFConcat context. If the listing is send in via pipe, the listing data can be obtained via ffconcat.input.

The listing can be populated either by parsing a valid ffconcat script via the constructor or ffconcat.parse(). Or an individual item (file, stream, option, or chapter) can be added by ffconcat.add_file(), ffconcat.add_stream(), ffconcat.add_option(), or ffconcat.add_chapter(). Files can also be added in batch by ffconcat.add_files().

Aside from the intended operations with ffmpegprocess, a listing file can be explicitly created by calling ffconcat.compose() with a valid writable text file object.

Alternately, the files in the listing can be used for a concat filtergraph use with as_filter().

Examples

  1. Concatenate mkv files with a temp listing file

    files = ['/video/video1.mkv','/video/video2.mkv']
    ffconcat = ffmpegio.FFConcat()
    ffconcat.add_files(files)
    with ffconcat: # generates temporary ffconcat file
        ffmpegio.transcode(ffconcat, 'output.mkv', f_in='concat', safe_in=0)
    

    Note that the files in an ffconcat listing file are defined relative to to the location of the ffconcat file. As such, both video files must be defined with absolute paths because the temporary ffconcat file is in a tempdir. Because the absolute paths are given, safe_in=0 option must be specified.

  2. Save generated ffconcat file in a same folder as the source video files

    files = ['video1.mkv','video2.mkv']
    ffconcat = ffmpegio.FFConcat(ffconcat_url='/video/concat.txt')
    ffconcat.add_files(files)
    with ffconcat: # generates ffconcat file at ffconcat_url
        ffmpegio.transcode(ffconcat, 'output.mkv', f_in='concat')
    

    By creating the ffconcat listing file in the directory where the video files are, the files in the listing can be defined relatively (i.e., just filenames). FFConcat will overwrite the file if exists, and the generated ffconcat file will not be deleted.

  3. Concatenate mkv files with listing piped to stdin

    files = ['file:video1.mkv','file:video2.mkv']
    ffconcat = ffmpegio.FFConcat(pipe_url='-')
    ffconcat.add_files(files)
    ffmpegio.transcode(ffconcat, 'output.mkv', f_in='concat',
                       protocol_whitelist_in="pipe,file", safe_in=0)
    

    Because of files are specified by data passed in via pipe (protocol) the files in the FFConcat must specify the protocol: file:. Also, additional input options are necessary: protocol_whitelist_in=”pipe,file” and safe_in=0.

  4. The concat script may be populated/altered inside the with statement, but update() must be called to update the prepared script:

    files = ['video1.mkv','video2.mkv']
    with ffmpegio.FFConcat(ffconcat_url='/video/concat.txt') as ffconcat:
        ffconcat.add_files(files)
        ffconcat.update() # must call update() before transcode
        ffmpegio.transcode(ffconcat,'output.mkv', f_in='concat')
    
  1. Rather than using demuxer, it can be used to compose concat filter command:

    inputs,fg = ffconcat.as_filter(v=1, a=1)
    
    ffmpegio.ffmpeg(
        {
            "inputs": inputs,
            "outputs": [("output.mkv", None)],
            "global_options": {"filter_complex": fg},
        }
    )
    
class FileItem(filepath, duration=None, inpoint=None, outpoint=None, metadata=None, options=None)

File listing item

Parameters:
  • filepath (str) – url of the file to be included

  • duration (str or numeric, optional) – duration of the file, defaults to None

  • inpoint (str or numeric, optional) – in point of the file, defaults to None

  • outpoint (str or numeric, optional) – out point of the file, defaults to None

  • metadata (dict, optional) – Metadata of the packets of the file, defaults to None

  • options (dict, optional) – Option to access, open and probe the file, defaults to None

duration

duration of the file, optional

Type:

str or numeric or None

inpoint

start time of the file, optional

Type:

str or numeric or None

property lines

ffconcat lines of the file

Type:

List[str]

metadata

metadata of the packets of the file, optional

Type:

dict or None

options

option key-value pairs to be included

Type:

dict[str,Any]

outpoint

end time of the file, optional

Type:

str or numeric or None

path

url of the file

Type:

str

class StreamItem(id=None, codec=None, metadata=None, extradata=None)

Stream listing item

Parameters:
  • id (str, optional) – ID of the stream, defaults to None

  • codec (str, optional) – Codec for the stream, defaults to None

  • metadata (dict, optional) – Metadata for the stream, defaults to None

  • extradata (str or bytes-like, optional) – Extradata for the stream in hexadecimal, defaults to None

codec

codec of the stream, optional

Type:

str or None

extradata

extra data of the stream, optional

Type:

bytes or str or None

id

id of the stream, optional

Type:

str or None

property lines

ffconcat lines of the stream

Type:

List[str]

metadata

of the stream, optional

Type:

dict or None

add_chapter(id, start, end)

add a chapter

Parameters:
  • id (str) – chapter ID

  • start (numeric or str) – start time

  • end (numeric or str) – end time

add_file(filepath, duration=None, inpoint=None, outpoint=None, metadata=None, options=None)

append a file to the list

Parameters:
  • filepath (str) – url of the file to be included

  • duration (str or numeric, optional) – duration of the file, defaults to None

  • inpoint (str or numeric, optional) – in point of the file, defaults to None

  • outpoint (str or numeric, optional) – out point of the file, defaults to None

  • metadata (dict, optional) – Metadata of the packets of the file, defaults to None

  • options (dict, optional) – Option to access, open and probe the file, defaults to None

add_files(files)

append files to the list

Parameters:

files (Sequence[str]) – list of files

add_glob(expr, root_dir=None, recursive=False)

append files with glob expression

Parameters:
  • expr (str) – glob expression

  • root_dir (str, optional) – the root directory for searching, defaults to None (uses the current directory)

  • recursive (bool, optional) – True to use the pattern “**” to match any files and zero or more directories, defaults to False

add_stream(id=None, codec=None, metadata=None, extradata=None)

append a stream specification to the list

Parameters:
  • id (str, optional) – ID of the stream, defaults to None

  • codec (str, optional) – Codec for the stream, defaults to None

  • metadata (dict, optional) – Metadata for the stream, defaults to None

  • extradata (str or bytes-like, optional) – Extradata for the stream in hexadecimal, defaults to None

as_filter(v=1, a=0, file_offset=0)

convert to concat filter commands

Parameters:
  • v (int, optional) – number of video streams in each file, default to 1

  • a (int, optional) – number of audio streams in each file, default to 0

  • file_offset (int, optional) – id of the first file used in the filtergraph input labels

Returns:

inputs list and concat filtergraph string

Return type:

tuple[list[tuple[str,dict]], str]

chapters

chapter id-(start,end) pairs to be included

Type:

dict[str,tuple]

compose(f=None)

compose ffconcat file

Parameters:

f (File-like object, optional) – writable file-like object, defaults to None, outputting to a StringIO object.

Returns:

passes through f or the created StringIO object

Return type:

File-like object

ffconcat_url

specify url to save generated ffconcat file instead of a temp file

Type:

str|None

property input

script as bytes

Type:

bytes

property last_file

Last added file item

Type:

FFConcat.FileItem

property last_stream

Last added stream item

Type:

FFConcat.StreamItem

parse(script, append=False)

parse ffconcat script

Parameters:
  • script (str) – ffconcat script

  • append (bool, optional) – True to append to the existing listing, False to clear existing and start new, defaults to False

pipe_url

specify pipe url if concat script to be loaded via stdin; None via a temp file

Type:

str|None

property script

composed concat listing script

Type:

str

streams

list of streams to be included in the order of appearance

Type:

ListConcatDemuxer.StreamItem]

update()

Update the prepared script for the context

property url

url to use as FFmpeg -i option

Type:

str