Video functions
This topic describes how to use the video functions in the Python multimodal function library. With the built-in python module, you can read video metadata, generate video segment references, and extract video frames by all frames, key frames, or a fixed time interval in Flink SQL deployments.
Limits
Supported only by Realtime Compute engine VVR 11.8 or later.
Usage
Usage notes
In SQL deployments on the platform, video functions are provided by the built-in python module, and no additional dependencies are required in the deployment. Before you use a function provided by the python module, load the module first and then enable the python and core modules:
LOAD MODULE python;
USE MODULES python, core;
Basic invocation
LOAD MODULE python;
USE MODULES python, core;
-- Read the video metadata.
SELECT id, VIDEO_METADATA(uri, 'null') AS metadata
FROM videos;
-- Extract one frame every second and expand the result into one frame per row.
SELECT v.id, f.frame, f.metadata
FROM videos AS v
CROSS JOIN LATERAL TABLE(
VIDEO_EXPLODE_FRAMES(v.uri, 'sample', 1000)
) AS f(frame, metadata);
Parameters
SQL functions take arguments in the order defined in the signature and support only positional arguments. In a function signature, [ ] indicates an optional parameter. For example, the signature of VIDEO_METADATA is as follows:
VIDEO_METADATA(
uri
[, on_error
[, read_chunk_size
[, max_cached_blocks
[, read_ahead_blocks]]]]
)
The following rules apply to invocation:
-
Omitted optional parameters are filled with their default values.
-
To explicitly set a later optional parameter, you must also explicitly specify all preceding optional parameters.
-
NULLis passed as a parameter value, which is not equivalent to the default value used when the parameter is omitted. When a polymorphic data parameter requiresNULL, useCAST(NULL AS <exact type>)to specify the type explicitly. -
Except for
video_input,VIDEO_METADATAofuri, andVIDEO_SPLITofmetadata, all other parameters are configuration parameters and must use SQL literals, includingNULL. Table fields andCASTexpressions are not supported. -
VIDEO_SPLITandVIDEO_EXPLODE_FRAMESis a table-valued function (UDTF) and must be called by usingLATERAL TABLE.
Data types
Video data forms
|
Data form |
SQL type |
Description |
|
Video URI |
|
A video URI accessible to the Flink file system. |
|
|
Points to a time segment in the original video without copying the video content. |
VIDEO_METADATA accepts only a video URI. The other three video functions accept both a URI and a video segment reference. Only the first video stream is selected when a video is read.
Video segment reference
ROW<uri STRING, start_time_ms BIGINT, end_time_ms BIGINT>
|
Field |
Type |
Description |
|
|
|
The path of the original video file or the object storage URI. |
|
|
|
The start time of the segment, in milliseconds. The value is |
|
|
|
The end time of the segment, in milliseconds. The value is |
VIDEO_SPLIT returns this data structure. A video segment uses the closed interval [start_time_ms, end_time_ms]. For example, for [0, 999], the next adjacent segment starts at 1000.
Video metadata
VIDEO_METADATA returns the following structure:
ROW<
width INT,
height INT,
fps DOUBLE,
duration_ms BIGINT,
frame_count BIGINT,
time_base DOUBLE,
codec_name STRING,
video_stream_index INT
>
|
Field |
Type |
Description |
|
|
|
The video width, in pixels. |
|
|
|
The video height, in pixels. |
|
|
|
The video frame rate. |
|
|
|
The video duration, in milliseconds. |
|
|
|
The number of video frames. |
|
|
|
The time base of the video stream, which is used to calculate frame time. |
|
|
|
The name of the video encoding format, such as |
|
|
|
The number of the selected video stream. |
A metadata field may be NULL.
Video frame metadata
VIDEO_EXPLODE_FRAMES returns the following metadata for each output frame:
ROW<
uri STRING,
video_stream_index INT,
frame_index BIGINT,
pts BIGINT,
time_ms BIGINT,
key_frame BOOLEAN,
start_time_ms BIGINT,
end_time_ms BIGINT
>
|
Field |
Type |
Description |
|
|
|
The path of the original video file or the object storage URI. |
|
|
|
The number of the video stream to which the output frame belongs. |
|
|
|
The sequence number of the output frame in the current frame extraction result, starting from |
|
|
|
The original frame timestamp in the video file, which is usually used for alignment with video processing tools. The value is |
|
|
|
The video time of the frame, in milliseconds. The value is |
|
|
|
Indicates whether the frame is a key frame. |
|
|
|
The start time of the input segment for the current frame extraction, in milliseconds. The value is |
|
|
|
The end time of the input segment for the current frame extraction, in milliseconds. The value is |
Video metadata
VIDEO_METADATA
Reads basic video information such as resolution, frame rate, duration, and encoding format. This function reads only the container and video stream metadata and does not decode video frames.
VIDEO_METADATA(
uri
[, on_error
[, read_chunk_size
[, max_cached_blocks
[, read_ahead_blocks]]]]
)
|
Parameter |
Type |
Default value |
Description |
|
|
|
Required |
The video URI. |
|
|
|
|
The error handling policy. |
|
|
|
|
The number of bytes read from the Java file system bridge at a time. The value must be greater than 0 and cannot exceed 16 MiB. |
|
|
|
|
The maximum number of blocks cached for each file. The value must be greater than or equal to 0. |
|
|
|
|
The number of blocks to read ahead after a cache miss. The value must be greater than or equal to 0. |
Return type: video metadata ROW. If the input URI is NULL, the function returns NULL.
WITH source_with_metadata AS (
SELECT id, VIDEO_METADATA(uri, 'null') AS metadata
FROM videos
)
SELECT id, metadata.width AS width, metadata.duration_ms AS duration_ms
FROM source_with_metadata;
Video splitting and frame extraction
VIDEO_EXTRACT_FRAMES
Extracts frames from a complete video or a video segment and collects the results of the same input video into an array in a single row. For long videos or a large number of extracted frames, we recommend that you use VIDEO_EXPLODE_FRAMES to avoid holding too many images in a single row.
VIDEO_EXTRACT_FRAMES(
video_input
[, frame_selector
[, sample_interval_ms
[, max_frames
[, image_height, image_width
[, on_error
[, read_chunk_size
[, max_cached_blocks
[, read_ahead_blocks]]]]]]]]]
)
|
Parameter |
Type |
Default value |
Description |
|
|
|
Required |
The video URI or the video segment reference returned by |
|
|
|
|
The frame extraction strategy. Supported values: |
|
|
|
|
The sampling interval when |
|
|
|
|
The safe upper limit on the number of frames retained in the same output row. The value must be greater than 0. |
|
|
|
|
The output image height, in pixels. This parameter must be set together with |
|
|
|
|
The output image width, in pixels. This parameter must be set together with |
|
|
|
|
The error handling policy. |
|
|
|
|
The number of bytes read from the Java file system bridge at a time. The value must be greater than 0 and cannot exceed 16 MiB. |
|
|
|
|
The maximum number of blocks cached for each file. The value must be greater than or equal to 0. |
|
|
|
|
The number of blocks to read ahead after a cache miss. The value must be greater than or equal to 0. |
Return type: ARRAY<IMAGE>.
-
image_heightandimage_widthspecify the exact output size and do not preserve the original aspect ratio. -
When the input is a video segment reference, the closed interval
[start_time_ms, end_time_ms]is used to filter frames whosetime_mscan be determined.'all_frames'and'keyframe'strategy, frames whosetime_mscannot be determined may still be output. The'sample'strategy skips such frames. -
frame_selector='sample'establishes sampling time points from the start of the segment, and the output time is not earlier than the first frame at each sampling point. Frames whosetime_mscannot be determined are not used as sampling results. -
If the input is
NULLor processing fails under the'null'strategy, the function returnsNULL. If processing succeeds but no frame is selected, an empty array is returned.
-- Extract one frame every second, return at most 10 frames per video, and scale them to 224 × 224.
SELECT VIDEO_EXTRACT_FRAMES(
uri, 'sample', 1000, 10, 224, 224, 'null'
) AS frames
FROM videos;
VIDEO_SPLIT
Splits a complete video or an existing video segment into multiple segment references and expands them into one segment reference per row. This function does not copy video content or read video frames. It only calculates time windows.
VIDEO_SPLIT(
video_input
[, metadata
[, segment_duration_ms
[, num_segments
[, video_duration_ms
[, max_segments
[, on_error
[, read_chunk_size
[, max_cached_blocks
[, read_ahead_blocks]]]]]]]]]
)
|
Parameter |
Type |
Default value |
Description |
|
|
|
Required |
The video URI or an existing video segment reference. |
|
|
Video metadata |
|
The video metadata that contains a valid |
|
|
|
|
The fixed segment length, in milliseconds. The value must be greater than 0. Exactly one of this parameter and |
|
|
|
|
The number of segments of approximately equal length. The value must be greater than 0. Exactly one of this parameter and |
|
|
|
|
The explicit video duration, in milliseconds. The value must be greater than 0. It is used as a fallback when the input has no end time and |
|
|
|
|
The maximum number of segments output in a single row. The value must be greater than 0. Remaining segments are not output after the limit is reached. |
|
|
|
|
The error handling policy. |
|
|
|
|
The number of bytes read from the Java file system bridge at a time. The value must be greater than 0 and cannot exceed 16 MiB. |
|
|
|
|
The maximum number of blocks cached for each file. The value must be greater than or equal to 0. |
|
|
|
|
The number of blocks to read ahead after a cache miss. The value must be greater than or equal to 0. |
Returned column: segment ROW<uri STRING, start_time_ms BIGINT, end_time_ms BIGINT>, one segment per row.
read_chunk_size, max_cached_blocks and read_ahead_blocks is used only when the function probes the metadata by itself.
-
If the input reference already contains
end_time_ms, the segment boundaries are used directly. -
If the input has no
end_time_ms, the duration inmetadataandvideo_duration_msare used in sequence. If neither provides a valid value, the function probes the video duration. -
When splitting by fixed duration, each segment is a closed interval. For example, a 2-second video split by 1000 milliseconds produces
[0, 999]and[1000, 1999]. -
When splitting by the number of segments, the function rounds up the segment duration, so the actual number of segments may be less than
num_segments.
-- Use a typed NULL as a placeholder for metadata, and split by 1 second.
SELECT v.id, s.segment
FROM videos AS v
CROSS JOIN LATERAL TABLE(
VIDEO_SPLIT(v.uri, CAST(NULL AS BIGINT), 1000)
) AS s(segment);
-- Reuse the metadata that has already been read, and split by the target number of segments.
WITH source_with_metadata AS (
SELECT id, uri, VIDEO_METADATA(uri) AS metadata
FROM videos
)
SELECT v.id, s.segment
FROM source_with_metadata AS v
CROSS JOIN LATERAL TABLE(
VIDEO_SPLIT(
v.uri,
v.metadata,
NULL,
4
)
) AS s(segment);
VIDEO_EXPLODE_FRAMES
Extracts frames from a complete video or a video segment and expands the results into one frame per row.
VIDEO_EXPLODE_FRAMES(
video_input
[, frame_selector
[, sample_interval_ms
[, max_frames
[, image_height, image_width
[, on_error
[, read_chunk_size
[, max_cached_blocks
[, read_ahead_blocks]]]]]]]]]
)
|
Parameter |
Type |
Default value |
Description |
|
|
|
Required |
The video URI or the video segment reference returned by |
|
|
|
|
The frame extraction strategy. Supported values: |
|
|
|
|
The sampling interval when |
|
|
|
|
The maximum number of frames output for each input. The value must be greater than 0. |
|
|
|
|
The output frame height, in pixels. This parameter must be set together with |
|
|
|
|
The output frame width, in pixels. This parameter must be set together with |
|
|
|
|
The error handling policy. |
|
|
|
|
The number of bytes read from the Java file system bridge at a time. The value must be greater than 0 and cannot exceed 16 MiB. |
|
|
|
|
The maximum number of blocks cached for each file. The value must be greater than or equal to 0. |
|
|
|
|
The number of blocks to read ahead after a cache miss. The value must be greater than or equal to 0. |
Returned column: frame IMAGE, metadata ROW<...>, one video frame per row.
The rules for frame selection, scaling, and segment boundaries are the same as those of VIDEO_EXTRACT_FRAMES. When on_error='skip' is used, no rows are output if decoding fails before the first frame is output. If an error occurs after some frames have been output, the rows already output are retained.
SELECT v.id, f.frame, f.metadata.time_ms AS frame_time_ms
FROM videos AS v
CROSS JOIN LATERAL TABLE(
VIDEO_EXPLODE_FRAMES(
v.uri, 'sample', 1000, 10, 224, 224, 'skip'
)
) AS f(frame, metadata);
Complete pipeline example
The following example reads the video metadata, splits the video into 1-second segments, and then extracts one frame from each segment:
LOAD MODULE python;
USE MODULES python, core;
-- Step 1: Read each video URI and extract the corresponding video metadata.
WITH source_with_metadata AS (
SELECT
id,
uri,
VIDEO_METADATA(uri, 'null') AS metadata
FROM videos
),
-- Step 2: Split each video into multiple video segments based on the video URI and metadata.
video_segments AS (
SELECT
v.id,
s.segment
FROM source_with_metadata AS v
CROSS JOIN LATERAL TABLE(
VIDEO_SPLIT(v.uri, v.metadata, 1000, NULL, NULL, 1024, 'skip')
) AS s(segment)
)
-- Step 3: Extract video frames from each video segment in sampling mode, and output the frame time and the start and end times of the segment to which it belongs.
SELECT
s.id,
f.frame,
f.metadata.time_ms AS frame_time_ms,
f.metadata.start_time_ms AS segment_start_ms,
f.metadata.end_time_ms AS segment_end_ms
FROM video_segments AS s
CROSS JOIN LATERAL TABLE(
VIDEO_EXPLODE_FRAMES(s.segment, 'sample', 1000, 1)
) AS f(frame, metadata);