Video stream (RTSP/RTMP/HLS) (Beta)

Updated at:

The video stream connector continuously reads video streams such as RTSP, RTMP, and HTTP/HLS by using FFmpeg, converts live video into JPEG images or MP4 video clips at fixed intervals, and outputs them as streaming records. This topic describes how to use the video stream connector in Flink SQL and data ingestion YAML.

Overview

The following table lists the capabilities of the video stream connector.

Category

Details

Supported type

Source table

Execution mode

Streaming mode only

Changelog mode

INSERT only

Data format

Fixed schema

API types

Flink SQL and data ingestion YAML

Output

JPEG images or MP4 video clips

Note

To use the video stream connector, you must upgrade to Realtime Compute engine VVR 11.9 (including preview versions) or later.

Features

  • Two output modes: KEYFRAME_EXTRACT extracts JPEG images at a fixed interval, and MOVIE_CLIP splits the stream by duration and outputs MP4 video clips.

  • Parallel reading of multiple video streams: you can configure a static URL list. Each URL corresponds to one source split, and source splits can be assigned to different source readers for parallel processing.

  • Multi-protocol access: protocol parsing is handled by FFmpeg, so you can access video sources that FFmpeg supports, such as RTSP, RTMP, and HTTP/HLS.

  • FFmpeg parameter pass-through: you can use ffmpeg.properties. and ffmpeg-video.properties. to configure FFmpeg parameters such as the transport protocol, timeout, and decoding threads.

  • URL-based routing: data ingestion YAML can extract a table ID from each video URL by using a regular expression and route different video streams to different source tables.

  • Backpressure buffering: each source reader uses a bounded queue to buffer generated media records. When downstream is congested, the number of pending records in memory is limited.

Prerequisites

Before you use the video stream connector, make sure that the following requirements are met.

Configurations

Requirement

Video source

A continuously available video stream URL is prepared, and the video stream contains a video track.

Network connectivity

The network of Flink TaskManagers can access the video stream URL and its associated media URLs.

Protocol and codec

The video stream uses a protocol, container format, and codec that FFmpeg supports.

Access credentials (optional)

If the video source requires authentication, an authenticated URL or protocol parameters that FFmpeg can use are prepared.

Limits

  • Only source tables are supported. Dimension tables and result tables are not supported.

  • Only unbounded streaming reads are supported. Snapshots, batch reads, and historical backtracking are not supported.

  • The video URL list is determined when the job starts. Automatic discovery, addition, or removal of video sources at runtime is not supported.

SQL

Syntax

CREATE TEMPORARY TABLE video_stream_source (
  video_source STRING NOT NULL,
  start_ts BIGINT NOT NULL,
  end_ts BIGINT NOT NULL,
  `blob` BYTES NOT NULL,
  mime_type STRING NOT NULL
) WITH (
  'connector' = 'video-stream',
  'video-stream.url-list' = '<videoStreamUrl>',
  'mode' = 'KEYFRAME_EXTRACT',
  'sample-interval' = '5s'
);

The DDL must declare all five columns of the fixed schema in the order shown above. The NULL constraints of the columns do not affect validation, but we recommend that you declare all columns as NOT NULL to match the connector output.

WITH parameters

The following table lists the WITH parameters of the video stream connector in Flink SQL. Set connector to video-stream.

Parameter

Description

Type

Required

Default value

Remarks

connector

The connector type.

STRING

Yes

None

Set the value to video-stream.

video-stream.url-list

A static list of video stream URLs.

STRING

Yes

None

URLs are separated by commas (,) by default. The list must contain at least one non-empty, unique URL.

video-stream.url-list-separator

The separator of the URL list.

STRING

No

,

The separator is parsed as a plain string, not a regular expression. It cannot be empty.

mode

The media output mode.

STRING

Yes

None

Valid values: KEYFRAME_EXTRACT and MOVIE_CLIP.

sample-interval

The frame extraction interval or the target duration of video clips.

DURATION

Yes

None

The value must be greater than or equal to 1 millisecond, for example, 500ms, 5s, or 1min.

record-queue-capacity

The maximum number of generated media records that each source reader can buffer.

INTEGER

No

16

The value must be a positive integer. A larger value better absorbs data jitter but consumes more memory.

ffmpeg.properties.*

General input parameters passed to the FFmpeg grabber.

STRING

No

None

Parameters with the prefix removed are forwarded to FFmpeg.

For example, if you set ffmpeg.properties.rtsp_transport = tcp, it is equivalent to passing the rtsp_transport=tcp command-line argument to FFmpeg.

Note

For all configurable options, see FFmpeg Formats and FFmpeg Protocols.

ffmpeg-video.properties.*

Video input parameters passed to the FFmpeg grabber.

STRING

No

None

Parameters with the prefix removed are forwarded to the FFmpeg video codec.

For example, if you set ffmpeg-video.properties.threads = 1, it is equivalent to passing the threads=1 codec parameter to FFmpeg.

Note

For all configurable options, see FFmpeg Codecs.

Metadata field mapping

The video stream connector uses a fixed schema. The SQL DDL must declare all of the following columns in the same order.

Field

Flink SQL type

Nullable

Description

video_source

STRING

No

The video stream URL that produced the current record. It matches the URL in the configuration.

start_ts

BIGINT

No

The start time of the image or video clip. The value is a UNIX timestamp in milliseconds. The time of the first frame is the system time when the connector starts receiving frames from the video stream. Subsequent times increase along the media timeline.

end_ts

BIGINT

No

The end time of the image or video clip. The value is a UNIX timestamp in milliseconds. For image records, the value is the same as start_ts.

blob

BYTES

No

The binary content of the JPEG image or MP4 video clip.

mime_type

STRING

No

The media type. The value is image/jpeg for images and video/mp4 for video clips.

Examples

Example 1: Read an RTSP video and extract JPEG images

The following example extracts one frame every 5 seconds and connects to the RTSP service over TCP.

CREATE TEMPORARY TABLE video_stream_source (
  video_source STRING NOT NULL,
  start_ts BIGINT NOT NULL,
  end_ts BIGINT NOT NULL,
  `blob` BYTES NOT NULL,
  mime_type STRING NOT NULL
) WITH (
  'connector' = 'video-stream',
  'video-stream.url-list' = 'rtsp://<host>:<port>/<path>',
  'mode' = 'KEYFRAME_EXTRACT',
  'sample-interval' = '5s',
  -- The following parameters are passed through directly to the FFmpeg library
  'ffmpeg.properties.rtsp_transport' = 'tcp',
  'ffmpeg-video.properties.threads' = '1'
);

INSERT INTO paimon_catalog.default.video_stream_table
SELECT video_source, start_ts, end_ts, `blob`, mime_type
FROM video_stream_source;

Example 2: Read an RTMP video and generate MP4 clips

The following example splits the live stream into MP4 clips with a target duration of 10 seconds.

CREATE TEMPORARY TABLE video_clip_source (
  video_source STRING NOT NULL,
  start_ts BIGINT NOT NULL,
  end_ts BIGINT NOT NULL,
  `blob` BYTES NOT NULL,
  mime_type STRING NOT NULL
) WITH (
  'connector' = 'video-stream',
  'video-stream.url-list' = 'rtmp://<host>:<port>/<app>/<stream>',
  'mode' = 'MOVIE_CLIP',
  'sample-interval' = '10s',
  'record-queue-capacity' = '4'
);

Example 3: Read multiple video streams

The following example uses | to separate two URLs. We recommend this format when the query parameters of a URL contain commas.

CREATE TEMPORARY TABLE multi_video_source (
  video_source STRING NOT NULL,
  start_ts BIGINT NOT NULL,
  end_ts BIGINT NOT NULL,
  `blob` BYTES NOT NULL,
  mime_type STRING NOT NULL
) WITH (
  'connector' = 'video-stream',
  'video-stream.url-list' = 'https://<host>/live.m3u8?tracks=video,audio|rtsp://<host>/<camera>',
  'video-stream.url-list-separator' = '|',
  'mode' = 'KEYFRAME_EXTRACT',
  'sample-interval' = '3s'
);

Example 4: Write video content to a Paimon Blob column

The following example writes the media binaries output by the video stream connector to a Paimon Blob column. A Paimon Blob table is an append-only table. Do not define a primary key.

CREATE TABLE my_catalog.my_db.video_archive (
  video_source STRING,
  start_ts BIGINT,
  end_ts BIGINT,
  `blob` BYTES,
  mime_type STRING
) WITH (
  'blob-field' = 'blob',
  'row-tracking.enabled' = 'true',
  'data-evolution.enabled' = 'true'
);

INSERT INTO paimon_catalog.default.video_stream_table
SELECT video_source, start_ts, end_ts, `blob`, mime_type
FROM video_stream_source;

Data ingestion

Syntax

source:
  type: video-stream
  name: Video Stream Source
  video-stream.url-list: rtsp://<host>:<port>/<path>
  mode: KEYFRAME_EXTRACT
  sample-interval: 5s

transform:
  - source-table: default
    projection: video_source, start_ts, end_ts, blob, mime_type
    table-options: blob-field=blob;row-tracking.enabled=true;data-evolution.enabled=true

route:
  - source-table: default
    sink-table: <sinkDatabase>.<sinkTable>

sink:
  type: paimon
  name: Paimon Sink
  catalog.properties.metastore: rest
  catalog.properties.uri: <catalogEndpoint>
  catalog.properties.warehouse: <warehouseName>

If url.to.table-id.matching.pattern is not configured, all video streams are written to a source table named default.

Configurations

The following table lists the configurations of the video stream connector in data ingestion YAML. Set type to video-stream.

Parameter

Description

Type

Required

Default value

Remarks

type

The connector type.

STRING

Yes

None

Set the value to video-stream.

name

The name of the source.

STRING

No

None

Used to identify the current source.

video-stream.url-list

A static list of video stream URLs.

STRING

Yes

None

URLs are separated by commas (,) by default. The list must contain at least one non-empty, unique URL.

video-stream.url-list-separator

The separator of the URL list.

STRING

No

,

The separator is parsed as a plain string, not a regular expression. It cannot be empty.

mode

The media output mode.

STRING

Yes

None

Valid values: KEYFRAME_EXTRACT and MOVIE_CLIP.

sample-interval

The frame extraction interval or the target duration of video clips.

DURATION

Yes

None

The value must be greater than or equal to 1 millisecond.

record-queue-capacity

The maximum number of generated media records that each source reader can buffer.

INTEGER

No

16

The value must be a positive integer.

url.to.table-id.matching.pattern

A regular expression that extracts a table ID from each full video URL.

STRING

No

None

The regular expression must contain 1 to 3 capturing groups and match the full URL. Unmatched URLs are written to the default table.

ffmpeg.properties.*

General input parameters passed to the FFmpeg grabber.

STRING

No

None

The name with the prefix removed is used as an FFmpeg parameter name.

ffmpeg-video.properties.*

Video input parameters passed to the FFmpeg grabber.

STRING

No

None

The name with the prefix removed is used as an FFmpeg video parameter name.

URL to Table ID mapping

url.to.table-id.matching.pattern matches the full URL by using a Java regular expression and generates a table ID based on the number of capturing groups. For example, if the video URL is rtmp://server/video/shop001/camera_01, you can use the following configuration to map it to shop001.camera_01:

url.to.table-id.matching.pattern: ^rtmp://[^/]+/video/([^/]+)/([^/?]+)$

The regular expression must contain exactly 1 to 3 capturing groups, and the captured results cannot be empty. If no regular expression is configured or a URL does not match, the connector uses default as the table ID.

Examples

Example 1: Write a single video stream to Paimon

The following example extracts one JPEG image every 5 seconds and stores the image content in a Paimon Blob column.

source:
  type: video-stream
  name: Camera Source
  video-stream.url-list: rtsp://<host>:<port>/<camera>
  mode: KEYFRAME_EXTRACT
  sample-interval: 5s
  record-queue-capacity: 8
  ffmpeg.properties.rtsp_transport: tcp
  ffmpeg.properties.timeout: 10000000

transform:
  - source-table: default
    projection: video_source, start_ts, end_ts, blob, mime_type
    table-options: blob-field=blob;row-tracking.enabled=true;data-evolution.enabled=true

route:
  - source-table: default
    sink-table: video_db.camera_frames

sink:
  type: paimon
  name: Paimon Sink
  catalog.properties.metastore: rest
  catalog.properties.uri: <catalogEndpoint>
  catalog.properties.warehouse: <warehouseName>

pipeline:
  name: Camera Frames Pipeline
  parallelism: 1

Example 2: Map multiple video streams to different tables by URL

The following example maps two RTMP video streams to shop001.camera_01 and shop002.camera_02 respectively. You can then use the table matching rules supported by the pipeline in the route section to route these source tables to the corresponding sink tables.

source:
  type: video-stream
  name: Multi-camera Source
  video-stream.url-list: rtmp://server/video/shop001/camera_01,rtmp://server/video/shop002/camera_02
  mode: MOVIE_CLIP
  sample-interval: 10s
  url.to.table-id.matching.pattern: ^rtmp://[^/]+/video/([^/]+)/([^/?]+)$

route:
  - source-table: shop001.camera_01
    sink-table: video_db.shop001_camera_01
  - source-table: shop002.camera_02
    sink-table: video_db.shop002_camera_02

sink:
  type: paimon
  name: Paimon Sink
  catalog.properties.metastore: rest
  catalog.properties.uri: <catalogEndpoint>
  catalog.properties.warehouse: <warehouseName>

pipeline:
  name: Multi-camera Clips Pipeline
  parallelism: 2

FAQ

No data is output after the job starts

Check the following items in order:

  1. Whether the TaskManager can access the video URL.

  2. Whether FFmpeg supports the protocol, container format, and codec.

  3. Whether the video stream contains a decodable video track.

  4. Whether sample-interval is set too large.

  5. Whether the RTSP service requires ffmpeg.properties.rtsp_transport: tcp.

Why does the job not resume reading from the interruption point after a recovery?

Live streams have no stable, recoverable media position. A checkpoint can only restore the assignment of URL splits. Frames during a failure may not be captured, and duplicate records may be generated after reconnection. Therefore, the video stream connector does not support resuming from the interruption point and does not provide end-to-end exactly-once guarantees.

How do I reduce CPU and memory consumption?

  • Increase sample-interval to reduce the number of images or the video clipping frequency.

  • Use KEYFRAME_EXTRACT when only single-frame analysis is required.

  • Decrease record-queue-capacity to limit the number of buffered media records.

  • Distribute multiple URLs across an appropriate source parallelism so that a single source reader does not handle too many video streams at the same time.

  • We recommend that you set ffmpeg-video.properties.threads to 1 to reduce CPU usage.