Skip to content

Updating Video Metadata

In addition of using metadata property object in FFdecoder API for probing metadata information (only as JSON string) for each multimedia stream available in the given video source, you can also easily update the video metadata on-the-fly by assigning desired data as python dictionary to the same overloaded metadata property object. This feature can be used either for adding new custom properties to metadata, or to override source metadata properties used by FFdecoder API to formulate its default Decoder Pipeline for real-time video-frames generation.

We'll discuss video metadata extraction using both these APIs briefly in the following recipes:

This feature is not yet fully explored, but in the near future you'll be able to use it to dynamically override any Video frames Decoder Pipeline property (such as frame-size, pixel-format, etc.) in real-time like a pro. Stay tuned for more updates 👀

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.

Never name your python script deffcode.py

When trying out these recipes, never name your python script deffcode.py otherwise it will result in ModuleNotFound error.

Added new properties to metadata in FFdecoder API

In FFdecoder API, you can easily define any number of new properties for its metadata (formatted as python dictionary) with desired data of any datatype(s)1 , without affecting its default Video frames Decoder pipeline.

In this example we will probe all metadata information available within foo.mp4 video file on Windows machine, thereby add new propertys (formatted as python dictionary) with desired data of different datatype(s) through overloaded metadata property object, and then finally print it as JSON string using the same metadata property object in FFdecoder API.

The value assigned to metadata property object can be of dictionary datatype only. Any other type will immediately raise ValueError!

# import the necessary packages
from deffcode import FFdecoder
import json

# initialize the decoder using suitable source
decoder = FFdecoder("foo.mp4", verbose=True)

# format your data as dictionary (with data of any [printable] datatype)
data = dict(
    mystring="abcd",  # string data
    myint=1234,  # integers data
    mylist=[1, "Rohan", ["inner_list"]],  # list data
    mytuple=(1, "John", ("inner_tuple")),  # tuple data
    mydict={"anotherstring": "hello"},  # dictionary data
    myjson=json.loads('{"name": "John", "age": 30, "city": "New York"}'),  # json data
)

# assign your dictionary data
decoder.metadata = data

# finally formulate the decoder
decoder.formulate()

# print metadata as `json.dump`
print(decoder.metadata)

# terminate the decoder
decoder.terminate()
After running above python code, the resultant Terminal Output will look something as following on Windows machine:
{
  "ffmpeg_binary_path": "C:\\Users\\foo\\AppData\\Local\\Temp\\ffmpeg-static-win64-gpl/bin/ffmpeg.exe",
  "source": "D:\\foo.mp4",
  "source_extension": ".mp4",
  "source_video_resolution": [
    1920,
    1080
  ],
  "source_video_framerate": 29.97,
  "source_video_pixfmt": "yuv420p",
  "source_video_decoder": "h264",
  "source_duration_sec": 21.03,
  "approx_video_nframes": 630,
  "source_video_bitrate": "4937k",
  "source_audio_bitrate": "256k",
  "source_audio_samplerate": "48000 Hz",
  "source_has_video": true,
  "source_has_audio": true,
  "source_has_image_sequence": false,
  "ffdecoder_operational_mode": "Video-Only",
  "output_frames_pixfmt": "rgb24",
  "mystring": "abcd",
  "myint": 1234,
  "mylist": [
    1,
    "Rohan",
    [
      "inner_list"
    ]
  ],
  "mytuple": [
    1,
    "John",
    "inner_tuple"
  ],
  "mydict": {
    "anotherstring": "hello"
  },
  "myjson": {
    "name": "John",
    "age": 30,
    "city": "New York"
  }
}

 

Overriding source video metadata in FFdecoder API

In FFdecoder API, you can also use its metadata to manually override the source properties (as frame-size, frame pixel-format, video-framerate, video-decoder etc.) that directly affects its default Video frames Decoder pipeline that decodes real-time video-frames.

The "source" property in metadata cannot be altered in any manner.

Source Video metadata values must be handled carefully

Source Video metadata information is used by FFdecoder API to formulate its default Video frames Decoder pipeline, and any improper or invalid inputted source property could crash the pipeline with RuntimeError.

Therefore to safeguard against it, FFdecoder API discards any Source Video metadata dictionary keys, if its value's datatype fails to match the exact valid datatype defined in following table:

Only either source_demuxer or source_extension property can be present in source metadata.

Not all Source Video metadata properties directly affects the pipeline (as mentioned in the table). But this might change in future versions.

Source Video Metadata Keys Valid Value Datatype Effect on Pipeline
"source_extension" string None
"source_demuxer" string Direct
"source_video_resolution" list of integers e.g. [1280,720] Direct
"source_video_framerate" float Direct
"source_video_pixfmt" string Direct
"source_video_decoder" string Direct
"source_duration_sec" float None
"approx_video_nframes" integer Direct
"source_video_bitrate" string None
"source_audio_bitrate" string None
"source_audio_samplerate" string None
"source_has_video" bool Direct
"source_has_audio" bool None
"source_has_image_sequence" bool Direct
"ffdecoder_operational_mode" str None
"output_frames_pixfmt" str Direct

Hence for instance, if "source_video_resolution" is assigned "1280x720" (i.e. string datatype value instead of list), then it will be discarded.

In this example we will probe all metadata information available within foo.mp4 video file, and override frame size (originally 1920x1080) and pixel-format (originally rgb24) to our desired values through overloaded metadata property object in FFdecoder API, and thereby preview them using OpenCV Library's cv2.imshow() method.

The value assigned to metadata property object can be of dictionary datatype only. Any other type will immediately raise ValueError!

Once the formulate() method is called, the metadata information present in FFdecoder API is finalized and thereby used to formulate its default pipeline for decoding real-time video-frames. Therefore make all changes to video properties beforehand.

# import the necessary packages
from deffcode import FFdecoder
import cv2

# initialize and formulate the decoder using suitable source
decoder = FFdecoder("foo.mp4", verbose=True)

# override source metadata values
# !!! [WARNING] Make sure each value datatype matches the table !!!
decoder.metadata = {
    "output_frames_pixfmt": "gray",  # gray frame-pixfmt
    "source_video_resolution": [1280, 720],  # 1280x720 frame-size
}

# finally formulate the decoder
decoder.formulate()

# [NOTE] uncomment following line to debug values
# print(decoder.metadata)

# let's grab the 1280x720 sized gray frames from decoder
for frame in decoder.generateFrame():

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

    # {do something with gray frame here}

    # Show gray frames in output window
    cv2.imshow("Output gray", frame)

    # check for 'q' key if pressed
    key = cv2.waitKey(1) & 0xFF
    if key == ord("q"):
        break

# close output window
cv2.destroyAllWindows()

# terminate the decoder
decoder.terminate()

 


  1. ⚠ There is no concept of tuple datatype in the JSON format. Thereby, Python's json module auto-converts all tuple python values into JSON list because that's the closest thing in JSON format to a tuple. 


Last update: August 9, 2022