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 overloadedmetadata
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()