The Video Frame Extraction operator supports extracting frames from the input video at a specified frame rate and uploading the extracted image frames to a designated TOS storage path. After the task is completed, you can obtain the video metadata and the TOS storage path for each frame. Supports configurable frame extraction frequency, maximum frame count limit, output image format, and scaling strategy. Suitable for scenarios such as video understanding, detection, moderation, summarization, and cover generation.
Operator ID: las_video_frame_extract
max_frames parameter to control the upper limit of output frames. If the limit is exceeded, the first N frames are retained in chronological order to avoid generating too many frames from long videos.jpg and png image formats.resize_short_side) or specifying the target resolution (resize_hw) to meet different scenario requirements.max_frames.Sub-items | Performance impact explanation |
|---|---|
Maximum RPM | 600 |
Maximum concurrency | 10 |
Category | Detailed description |
|---|---|
Supported input data modalities |
|
Input format: Video |
|
Input path requirements | Provide input data to the operator via the request parameter
|
Category | Detailed description |
|---|---|
Output data modality |
|
Output format: Image |
|
Output path and naming: TOS | Set the output TOS path and naming rules via the request parameter
|
Billing standards
Item breakdown | Billing standards description |
|---|---|
Billing item | The usage is calculated based on the number of images sampled from the input video, and billed accordingly. |
Billing type | Usage-based billing, unit: |
Unit price | 0.1 CNY per 1,000 images |
Billing details
Billing formula: Total cost = unit price * usage
Details | Caution and prerequisites |
|---|---|
Costs | Before calling an operator, you need to understand the model invocation costs associated with using the operator. For details, see Large model invocation billing. |
Authentication (API Key) | Before calling an operator, you need to generate an API Key for operator invocation. It is recommended to configure the API Key as an environment variable to ensure safer operator calls. For details, see Obtain and configure API Key. |
BaseURL | Before calling an operator, you need to determine the BaseURL for operator invocation based on the region where your current LAS service is deployed. This is used to configure the path parameter values for operator calls. |
When calling las_video_frame_extract, you must first submit an asynchronous task using Submit. Once the task reaches the completed state, use Poll to retrieve the frame extraction results.
Submit interface to obtain the task_id of the task, then use the Poll interface to get the running status of the corresponding task (task_id) and obtain the operator processing result.task_id is valid for 3 days. After 3 days, the operator processing result cannot be obtained using this task_id.Call the Video Frame Extraction operator to submit an asynchronous task, extract frames from the input video at the specified frame rate, and upload the extracted image frames to the specified TOS path. After successful submission, the task ID is returned. You can obtain the processing result (including video metadata and the TOS storage path for each frame) through the task query interface.
const properties = ({ "columns": [ { "title": "参数", "dataIndex": "column_0", "key": "column_0", "width": 300 }, { "title": "类型", "dataIndex": "column_1", "key": "column_1", "width": 150 }, { "title": "Required", "dataIndex": "column_2", "key": "column_2", "width": 80 }, { "title": "Example", "dataIndex": "column_3", "key": "column_3", "width": 150 }, { "title": "Description", "dataIndex": "column_4", "key": "column_4" } ], "data": [ { "key": "1", "column_0": "operator_id", "column_1": "string", "column_2": "YES", "column_3": "las_video_frame_extract", "column_4": "Operator ID." }, { "key": "2", "column_0": "operator_version", "column_1": "string", "column_2": "YES", "column_3": "v1", "column_4": "Operator version." }, { "key": "3", "column_0": "data", "column_1": "VideoFrameExtractData", "column_2": "YES", "column_3": "", "column_4": "Video frame extraction request parameters.", "children": [ { "key": "3-1", "column_0": "video_url", "column_1": "string", "column_2": "YES", "column_3": "tos://bucket/path/video.mp4", "column_4": < div> Input video address. Supports < code> http/https</ code> and < code> tos://bucket/key</ code>. The address must be accessible by the service; if the video cannot be downloaded, parsed, or the format is unsupported, the following will be returned respectively: < code> Video.DownloadFailed</ code>, < code> Video.Invalid</ code>, or < code> Video.FormatUnsupported</ code>. </div> }, { "key": "3-2", "column_0": "output_path_template", "column_1": "string", "column_2": "YES", "column_3": "tos://bucket/frames/frame_{index:06d}.{autoext}", "column_4": < div> Output path template. The target bucket must have write permissions; it must point to a specific file in the form of < code> tos://bucket/path/file</ code>, cannot be rendered as a directory, and must include the < code>{ index}</ code> placeholder. Only < code>{ index}</ code> and < code>{ autoext}</ code> placeholders are supported;< ul>< li>< code>{ index}</ code> is the frame index starting from 0, supports formatted output (for example, < code>{ index:06d}</ code> outputs < code> 000000</ code>, < code> 000001</ code>); if no format is specified, outputs < code> 0</ code>, < code> 1</ code>. </ li>< li>< code>{ autoext}</ code> will be replaced with the actual output format suffix < code> jpg</ code> or < code> png</ code>. </ li></ ul> When writing the output object, the same-named TOS object will be overwritten. </div> }, { "key": "3-3", "column_0": "fps", "column_1": "float", "column_2": "No", "column_3": "1.0", "column_4": < div> Frame extraction rate, measured in frames per second. Value range < code>[ 0.1, 10.0]</ code>, default < code> 1.0</ code>. The operator starts from < code> 0</ code> seconds, constructs sampling time points at intervals of < code> 1/fps</ code> seconds, until the video duration or the < code> max_frames</ code> limit is reached; actual frames are extracted by ffmpeg at the corresponding time points. Invalid values return < code> Parameter.Invalid</ code>. </div> }, { "key": "3-4", "column_0": "max_frames", "column_1": "integer", "column_2": "No", "column_3": "200", "column_4": < div> Maximum number of frames to extract. Greater than 0; if not specified, there is no limit. If the sampling points calculated by < code> fps</ code> exceed < code> max_frames</ code>, the first < code> max_frames</ code> frames are retained in chronological order and extraction stops. Invalid values return < code> Parameter.Invalid</ code>; unlimited duration videos may generate a large number of images and TOS writes. </div> }, { "key": "3-5", "column_0": "image_format", "column_1": "string", "column_2": "No", "column_3": "jpg", "column_4": < div> Output image format. Optional values: < code> jpg</ code>, < code> png</ code>, default < code> jpg</ code>. When < code> output_path_template</ code> contains < code>{ autoext}</ code>, the system uses this format as the output file suffix. </div> }, { "key": "3-6", "column_0": "resize_short_side", "column_1": "integer", "column_2": "No", "column_3": "720", "column_4": < div> Scale the short side to the specified pixel value while maintaining the aspect ratio. Must be greater than 0; the actual upper limit for the short side is < code> 1080</ code>. If a larger value is provided, it will be processed as < code> 1080</ code>; the output width and height will be adjusted to even numbers. The original video frame may be enlarged or reduced. Mutually exclusive with < code> resize_hw</ code>; cannot be set simultaneously. </div> }, { "key": "3-7", "column_0": "resize_hw", "column_1": "array", "column_2": "No", "column_3": "[720, 1080]", "column_4": < div> Specify the output resolution < code>[ width, height]</ code>; element type is integer or null. The array length must be 2, and at least one element must be an integer greater than 0. It cannot be < code>[ null, null]</ code>. If only one side is specified, the original aspect ratio is maintained during scaling; if both width and height are specified, the output will use the specified dimensions, which may change the original aspect ratio; the output width and height will be adjusted to even numbers. Mutually exclusive with < code> resize_short_side</ code>; cannot be set simultaneously. </div> } ] } ] }); return <Table border={{ cell: true, wrapper: true }} pagination={false} {...properties} />;
参数 | 类型 | 示例值 | 描述 |
|---|---|---|---|
metadata | metadata | Request metadata. | |
task_id | string | task-xxx | Task ID in asynchronous mode, used for job status queries. |
task_status | string | PENDING | Task status in asynchronous mode.
|
business_code | string | 0 | Business code. |
error_msg | string | If an exception occurs, detailed error information will be returned. |
Request example
curl --location "https://operator.las.ap-southeast-1.volces.com/api/v1/submit" \ --header "Content-Type: application/json" \ --header "Authorization: Bearer $LAS_API_KEY" \ --data '{ "operator_id": "las_video_frame_extract", "operator_version": "v1", "data": { "video_url": "tos://my-bucket/videos/sample.mp4", "output_path_template": "tos://my-bucket/frames/frame_{index:06d}.{autoext}", "fps": 1.0, "max_frames": 200, "image_format": "jpg", "resize_short_side": 720 } }'
Response example
{ "metadata": { "task_id": "task-20260420120000-abc123", "task_status": "PENDING", "business_code": "0", "error_msg": "" } }
HttpStatusCode | Error code | Error message | Description |
|---|---|---|---|
|
|
| The request parameter is invalid. |
|
|
| Required parameter is missing. |
|
|
| The input video URL is invalid. |
|
|
| The video file is invalid or cannot be parsed. |
|
|
| Video download failed. |
|
|
| Video format is not supported. |
|
|
| Video processing timed out. |
|
|
| Video frame extraction failed. |
|
|
| TOS access failed. Please check credentials, Endpoint, and path write permissions. |
|
|
| Authorization information is missing. |
|
|
| API Key is invalid. |
Query the execution status and result of the Video Frame Extraction task. When the task status is COMPLETED and business_code=0, video metadata and the list of extracted frames are returned. In the PENDING, RUNNING, FAILED, or TIMEOUT states, data is usually not returned. The failure reason is returned via metadata.business_code and metadata.error_msg.
Name | Type | Required | Example value | Description |
|---|---|---|---|---|
| string | Yes |
| Operator ID. |
| string | Yes |
| Operator version. |
| string | Yes |
| The task ID returned after submitting the task. |
Parameter | Type | Example value | Description |
|---|---|---|---|
metadata | metadata | Request metadata. | |
data | VideoFrameExtractResponse | Data returned only when the task is completed and successful. |
Request example
curl --location "https://operator.las.ap-southeast-1.volces.com/api/v1/poll" \ --header "Content-Type: application/json" \ --header "Authorization: Bearer $LAS_API_KEY" \ --data '{ "operator_id": "las_video_frame_extract", "operator_version": "v1", "task_id": "task-20260420120000-abc123" }'
Response example
{ "metadata": { "task_id": "task-20260420120000-abc123", "task_status": "COMPLETED", "submit_time": "2026-07-21T16:04:06+08:00", "end_time": "2026-07-21T16:04:06+08:00", "business_code": "0", "error_msg": "" }, "data": { "video_duration": 11.234, "video_resolution": "1920x1080", "frame_count": 3, "frames": [ { "index": 0, "timestamp_seconds": 0.00, "width": 720, "height": 405, "tos_path": "tos://my-bucket/frames/frame_000000.jpg" }, { "index": 1, "timestamp_seconds": 1.00, "width": 720, "height": 405, "tos_path": "tos://my-bucket/frames/frame_000001.jpg" }, { "index": 2, "timestamp_seconds": 2.00, "width": 720, "height": 405, "tos_path": "tos://my-bucket/frames/frame_000002.jpg" } ] } }
HttpCode | Error code | Error message | Description |
|---|---|---|---|
400 | Parameter.Invalid | invalid parameter | The request parameter is invalid. |
400 | Parameter.Missing | Missing required parameter | Required parameter is missing. |
400 | Url.Invalid | invalid url | The input video URL is invalid. |
400 | Video.Invalid | invalid video file | The video file is invalid or cannot be parsed. |
400 | Video.DownloadFailed | Video download failed | Video download failed. |
400 | Video.FormatUnsupported | Video format not supported | Video format is not supported. |
400 | Video.Timeout | Video processing timeout | Video processing timed out. |
400 | Video.FrameExtractionFailed | Video frame extraction failed | Video frame extraction failed. |
400 | Tos.AccessFailed | Failed to access TOS path with provided credentials | TOS access failed. Please check credentials, Endpoint, and path write permissions. |
400 | Task.NotFound | Task not found | Task does not exist. |
401 | Authorization.Missing | Missing Authorization | Authorization information is missing. |
401 | ApiKey.InValid | The api key is invalid | API Key is invalid. |
500 | Internal.ServerError | Internal server error | Internal server error. |
Input column name | Description |
|---|---|
video_paths | Input video path column (local or remote URI), type string, default None |
video_binaries | Input video binary column, type binary, default None |
video_formats | The format corresponding to the binary input (such as "mp4", "mov"), type string, default None |
video_durations | Video duration column (seconds), type float, default None |
Struct array. Fields include:
If a parameter does not have a default value, it is required.
Parameter name | Type | Default value | Description |
|---|---|---|---|
sample_mode | str | by_count_uniform | Sampling mode. Optional values: ["by_count_uniform", "by_interval_time", "by_interval_frames", "by_fps", "by_timestamps"] |
start_time_sec | float | 0.0 | Start time (seconds) |
end_time_sec | float or None | End time (seconds). None indicates the end of the video | |
count_k | int or None | Number of frames for uniform/random sampling (used by by_count_uniform) | |
interval_sec | float or None | Time interval Δt (seconds, used by by_interval_time) | |
interval_frames | int or None | Decoded frame interval N (used by by_interval_frames) | |
target_fps | float or None | Target FPS (used by by_fps) | |
timestamps_sec | list or None | Target timestamp list (seconds, used by by_timestamps) | |
img_type | str | .jpg | Output image format (for base64 and optional saving to TOS), options: [".jpg", ".png", ".webp"], default is ".jpg" |
output_tos_dir | str | If not empty, sampled frames will be saved locally and uploaded to the target directory in TOS (each video in a separate subdirectory) | |
max_frames | int or None | Maximum number of frames returned (defensive limit). None means no limit | |
seed | int | 42 | When the total duration of the video cannot be determined in advance, the operator uses the reservoir sampling algorithm to uniformly randomly sample the specified number of frames from the video stream. This parameter is used to set the random seed to ensure the sampling results are reproducible. The default value is 42. |
output_frames | bool | True | Whether to output the original frame array (which can be large, default is True). Caution: Even if set to False, the returned result still contains the frames field, but its content is an empty list. |
output_base64 | bool | True | Whether to output base64 encoding (which can be large, default is True). Caution: Even if set to False, the returned result still contains the base64 field, but its content is an empty list. |
The following code demonstrates how to use Daft (for distributed scenarios) to sample several image frames from a video at frame intervals. In this example, interval_frames=100 is set, and 6 images are actually produced.
from __future__ import annotations import os import daft from daft import col from daft.las.functions.udf import las_udf from daft.las.functions.video.video_frame_sampler import VideoFrameSampler if __name__ == "__main__": # After sampling, the frames will be saved to the specified TOS path. Therefore, you need to set the environment variables to ensure you have permission to write to TOS, including: ACCESS_KEY, SECRET_KEY, TOS_ENDPOINT, TOS_REGION, TOS_TEST_DIR TOS_DIR = os.getenv("TOS_TEST_DIR", "tos_bucket") output_tos_dir = f"tos://{TOS_DIR}/video/video_frame_sampler" if os.getenv("DAFT_RUNNER", "native") == "ray": import logging import ray def configure_logging(): logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", datefmt="%Y-%m-%d %H:%M:%S.%s".format(), ) logging.getLogger("tracing.span").setLevel(logging.WARNING) logging.getLogger("daft_io.stats").setLevel(logging.WARNING) logging.getLogger("DaftStatisticsManager").setLevel(logging.WARNING) logging.getLogger("DaftFlotillaScheduler").setLevel(logging.WARNING) logging.getLogger("DaftFlotillaDispatcher").setLevel(logging.WARNING) ray.init(dashboard_host="0.0.0.0", runtime_env={"worker_process_setup_hook": configure_logging}) daft.set_runner_ray() daft.set_execution_config(actor_udf_ready_timeout=600) daft.set_execution_config(min_cpu_per_task=0) # Construct the URL using environment variables tos_dir_url = os.getenv("TOS_DIR_URL", "las-cn-beijing-public-online.tos-cn-beijing.volces.com") samples = { "video_path": [ f"https://{tos_dir_url}/public/shared_video_dataset/sample.mp4" ] } ds = daft.from_pydict(samples) sampler = las_udf( VideoFrameSampler, construct_args={ "sample_mode": "by_interval_frames", "interval_frames": 100, "output_tos_dir": output_tos_dir, "img_type": ".jpg", }, ) # Use Daft for distributed processing ds = ds.with_column("results", sampler(col("video_path"))) ds = ds.select( "video_path", col("results")["frames"].alias("frames"), col("results")["base64"].alias("base64"), col("results")["timestamps"].alias("timestamps"), col("results")["frame_indices"].alias("frame_indices"), col("results")["tos_paths"].alias("tos_paths"), ) ds.show() # ╭────────────────────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ # │ video_path ┆ results │ # │ --- ┆ --- │ # │ Utf8 ┆ Struct[frames: List[Binary], base64: List[Utf8], timestamps: List[Float64], frame_indices: List[Int64], tos_paths: List[Utf8]] │ # ╞════════════════════════════════╪══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╡ # │ https://las-cn-beijing-publi-… ┆ {frames: […], base64: […], timestamps: […], frame_indices: […], tos_paths: ["tos://tos_bucket/video/video_frame_sampler/frame_0.jpg", …]} │ # ╰────────────────────────────────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯