Skip to content

Transcoding Live Simple Filtergraphs

What are Simple filtergraphs?

Before heading straight into recipes we will talk about Simple filtergraphs:

Simple filtergraphs are those filters that have exactly one input and output, both of the same type.

They can be processed by simply inserting an additional step between decoding and encoding of video frames:

Simple filtergraphs

Simple filtergraphs are configured with the per-stream -filter option (with -vf for video).

DeFFcode's FFdecoder API handles a single chain of filtergraphs (through -vf FFmpeg parameter) to the to real-time frames quite effortlessly.

We'll discuss the transcoding of live simple filtergraphs in the following recipes:

DeFFcode APIs requires FFmpeg executable

DeFFcode APIs MUST requires valid FFmpeg executable for all of its core functionality, and any failure in detection will raise RuntimeError immediately. Follow dedicated FFmpeg Installation doc ➶ for its installation.

Additional Python Dependencies for following recipes

Following recipes requires additional python dependencies which can be installed easily as below:

  • OpenCV: OpenCV is required for previewing and encoding video frames. You can easily install it directly via pip:

    OpenCV installation from source

    You can also follow online tutorials for building & installing OpenCV on Windows, Linux, MacOS and Raspberry Pi machines manually from its source.

    ⚠ Make sure not to install both pip and source version together. Otherwise installation will fail to work!

    Other OpenCV binaries

    OpenCV maintainers also provide additional binaries via pip that contains both main modules and contrib/extra modules opencv-contrib-python, and for server (headless) environments like opencv-python-headless and opencv-contrib-python-headless. You can also install any one of them in similar manner. More information can be found here.

    pip install opencv-python       
    

Always use FFdecoder API's terminate() method at the end to avoid undesired behavior.

OpenCV's' VideoWriter() class lacks the ability to control output quality, bitrate, compression, and other important features which are only available with VidGear's WriteGear API.

Transcoding Trimmed and Reversed video

Big Buck Bunny Reversed

Big Buck Bunny Reversed

In this example we will take the first 5 seconds of a video clip (using trim filter) and reverse it (by applying reverse filter), and encode them using OpenCV Library's VideoWriter() method in real-time.

The reverse filter requires memory to buffer the entire clip, so applying trim filter first is strongly recommended. Otherwise you might probably run Out of Memory.

OpenCV's VideoWriter() class requires a valid Output filename (e.g. output_foo.avi), FourCC code, framerate, and resolution as input.

You can use FFdecoder's metadata property object that dumps source Video's metadata information (as JSON string) to retrieve output framerate and resolution.

By default, OpenCV expects BGR format frames in its write() method.

# import the necessary packages
from deffcode import FFdecoder
import json, cv2

# define the Video Filter definition
# trim 5 sec from end and reverse
ffparams = {
    "-vf": "trim=end=5,reverse" 
}

# initialize and formulate the decoder for BGR24 output with given params
decoder = FFdecoder(
    "foo.mp4", frame_format="bgr24", verbose=True, **ffparams
).formulate()

# retrieve JSON Metadata and convert it to dict
metadata_dict = json.loads(decoder.metadata)

# prepare OpenCV parameters
FOURCC = cv2.VideoWriter_fourcc("M", "J", "P", "G")
FRAMERATE = metadata_dict["output_framerate"]
FRAMESIZE = tuple(metadata_dict["output_frames_resolution"])

# Define writer with parameters and suitable output filename for e.g. `output_foo.avi`
writer = cv2.VideoWriter("output_foo.avi", FOURCC, FRAMERATE, FRAMESIZE)

# grab the BGR24 frame from the decoder
for frame in decoder.generateFrame():

    # check if frame is None
    if frame is None:
        break

    # {do something with the frame here}

    # writing BGR24 frame to writer
    writer.write(frame)

# terminate the decoder
decoder.terminate()

# safely close writer
writer.release()

 

Transcoding Cropped video

Big Buck Bunny Cropped

Big Buck Bunny Cropped

In this example we will crop real-time video frames by an area with size ⅔ of the input video (say foo.mp4) by applying crop filter in FFdecoder API, all while encoding them using OpenCV Library's VideoWriter() method in real-time.

OpenCV's VideoWriter() class requires a valid Output filename (e.g. output_foo.avi), FourCC code, framerate, and resolution as input.

You can use FFdecoder's metadata property object that dumps source Video's metadata information (as JSON string) to retrieve output framerate and resolution.

More complex examples using crop filter can be found here ➶ and can be applied similarly.

# import the necessary packages
from deffcode import FFdecoder
import json, cv2

# define the Video Filter definition
# cropped the central input area with size 2/3 of the input video
ffparams = {
    "-vf": "crop=2/3*in_w:2/3*in_h"
}

# initialize and formulate the decoder for BGR24 output with given params
decoder = FFdecoder(
    "foo.mp4", frame_format="bgr24", verbose=True, **ffparams
).formulate()

# retrieve JSON Metadata and convert it to dict
metadata_dict = json.loads(decoder.metadata)

# prepare OpenCV parameters
FOURCC = cv2.VideoWriter_fourcc("M", "J", "P", "G")
FRAMERATE = metadata_dict["output_framerate"]
FRAMESIZE = tuple(metadata_dict["output_frames_resolution"])

# Define writer with parameters and suitable output filename for e.g. `output_foo.avi`
writer = cv2.VideoWriter("output_foo.avi", FOURCC, FRAMERATE, FRAMESIZE)

# grab the BGR24 frame from the decoder
for frame in decoder.generateFrame():

    # check if frame is None
    if frame is None:
        break

    # {do something with the frame here}

    # writing BGR24 frame to writer
    writer.write(frame)

# terminate the decoder
decoder.terminate()

# safely close writer
writer.release()

 

Transcoding Rotated video (with rotate filter)

FFmpeg features Rotate Filter that is used to rotate videos by an arbitrary angle (expressed in radians).

Big Buck Bunny Rotated

Big Buck Bunny Rotated (with rotate filter)

In this example we will rotate real-time video frames at an arbitrary angle by applying rotate filter in FFdecoder API and also using green color to fill the output area not covered by the rotated image, all while encoding them using OpenCV Library's VideoWriter() method in real-time.

OpenCV's VideoWriter() class requires a valid Output filename (e.g. output_foo.avi), FourCC code, framerate, and resolution as input.

You can use FFdecoder's metadata property object that dumps source Video's metadata information (as JSON string) to retrieve output framerate and resolution.

# import the necessary packages
from deffcode import FFdecoder
import json, cv2

# define the Video Filter definition
# rotate by 0.35 rad and fill green
ffparams = {
    "-vf": "rotate=angle=-20*PI/180:fillcolor=green" 
}

# initialize and formulate the decoder for BGR24 output with given params
decoder = FFdecoder(
    "foo.mp4", frame_format="bgr24", verbose=True, **ffparams
).formulate()

# retrieve JSON Metadata and convert it to dict
metadata_dict = json.loads(decoder.metadata)

# prepare OpenCV parameters
FOURCC = cv2.VideoWriter_fourcc("M", "J", "P", "G")
FRAMERATE = metadata_dict["output_framerate"]
FRAMESIZE = tuple(metadata_dict["output_frames_resolution"])

# Define writer with parameters and suitable output filename for e.g. `output_foo.avi`
writer = cv2.VideoWriter("output_foo.avi", FOURCC, FRAMERATE, FRAMESIZE)

# grab the BGR24 frame from the decoder
for frame in decoder.generateFrame():

    # check if frame is None
    if frame is None:
        break

    # {do something with the frame here}

    # writing BGR24 frame to writer
    writer.write(frame)

# terminate the decoder
decoder.terminate()

# safely close writer
writer.release()

 

Transcoding Rotated video (with transpose filter)

FFmpeg also features Transpose Filter that is used to rotate videos by 90 degrees clockwise and counter-clockwise direction as well as flip them vertically and horizontally.

Big Buck Bunny Rotated

Big Buck Bunny Rotated (with transpose filter)

In this example we will rotate real-time video frames by 90 degrees counterclockwise and preserve portrait geometry by applying transpose filter in FFdecoder API, all while encoding them using OpenCV Library's VideoWriter() method in real-time.

OpenCV's VideoWriter() class requires a valid Output filename (e.g. output_foo.avi), FourCC code, framerate, and resolution as input.

You can use FFdecoder's metadata property object that dumps source Video's metadata information (as JSON string) to retrieve output framerate and resolution.

# import the necessary packages
from deffcode import FFdecoder
import json, cv2

# define the Video Filter definition
# rotate by 90 degrees counter-clockwise and preserve portrait layout
ffparams = {
    "-vf": "transpose=dir=2:passthrough=portrait"
}

# initialize and formulate the decoder for BGR24 output with given params
decoder = FFdecoder(
    "foo.mp4", frame_format="bgr24", verbose=True, **ffparams
).formulate()

# retrieve JSON Metadata and convert it to dict
metadata_dict = json.loads(decoder.metadata)

# prepare OpenCV parameters
FOURCC = cv2.VideoWriter_fourcc("M", "J", "P", "G")
FRAMERATE = metadata_dict["output_framerate"]
FRAMESIZE = tuple(metadata_dict["output_frames_resolution"])

# Define writer with parameters and suitable output filename for e.g. `output_foo.avi`
writer = cv2.VideoWriter("output_foo.avi", FOURCC, FRAMERATE, FRAMESIZE)

# grab the BGR24 frame from the decoder
for frame in decoder.generateFrame():

    # check if frame is None
    if frame is None:
        break

    # {do something with the frame here}

    # writing BGR24 frame to writer
    writer.write(frame)

# terminate the decoder
decoder.terminate()

# safely close writer
writer.release()

 

Transcoding Horizontally flipped and Scaled video

Big Buck Bunny Horizontally flipped and Scaled

Big Buck Bunny Horizontally flipped and Scaled

In this example we will horizontally flip and scale real-time video frames to half its original size by applying hflip and scale filter one-by-one in FFdecoder API, all while encoding them using OpenCV Library's VideoWriter() method in real-time.

OpenCV's VideoWriter() class requires a valid Output filename (e.g. output_foo.avi), FourCC code, framerate, and resolution as input.

You can use FFdecoder's metadata property object that dumps source Video's metadata information (as JSON string) to retrieve output framerate and resolution.

More complex examples using scale filter can be found here ➶ and can be applied similarly.

# import the necessary packages
from deffcode import FFdecoder
import json, cv2

# define the Video Filter definition
# horizontally flip and scale to half its original size
ffparams = {
    "-vf": "hflip,scale=w=iw/2:h=ih/2"
}

# initialize and formulate the decoder for BGR24 output with given params
decoder = FFdecoder(
    "foo.mp4", frame_format="bgr24", verbose=True, **ffparams
).formulate()

# retrieve JSON Metadata and convert it to dict
metadata_dict = json.loads(decoder.metadata)

# prepare OpenCV parameters
FOURCC = cv2.VideoWriter_fourcc("M", "J", "P", "G")
FRAMERATE = metadata_dict["output_framerate"]
FRAMESIZE = tuple(metadata_dict["output_frames_resolution"])

# Define writer with parameters and suitable output filename for e.g. `output_foo.avi`
writer = cv2.VideoWriter("output_foo.avi", FOURCC, FRAMERATE, FRAMESIZE)

# grab the BGR24 frame from the decoder
for frame in decoder.generateFrame():

    # check if frame is None
    if frame is None:
        break

    # {do something with the frame here}

    # writing BGR24 frame to writer
    writer.write(frame)

# terminate the decoder
decoder.terminate()

# safely close writer
writer.release()

 


Last update: January 10, 2023