Video keyframe extraction processor that supports dynamic detection using multiple algorithms.
Input column names | Description |
|---|---|
video_paths | Input video path column, type: array. Default value: None |
video_binaries | Input video binary data column, type: array. Default value: None |
video_formats | Input video format column (such as 'mp4', 'avi'), type: array. Default value: None |
The processed array, with struct fields including:
If a parameter does not have a default value, it is required
Parameter name | Type | Default value | Description |
|---|---|---|---|
method | str | I_frame | Method for extracting keyframes. Supports "difference" (pixel difference method), "optical_flow" (optical flow method), "histogram" (histogram method), and "I_frame" (I-frame identification). Optional values: ["difference", "optical_flow", "histogram", "I_frame"] Default value: "I_frame" |
img_type | str | .jpg | Output keyframe image format. Supports ".jpg" and ".png". Optional values: [".jpg", ".png"] Default value: ".jpg" |
threshold | float | 0 | Threshold for determining keyframes. Recommended values: difference 2000000, histogram 0.01, optical_flow 2.0. Default value: 0 |
keyframes_cnt | int | 10 | Specifies the number of keyframes to extract; -1 means no limit on the number of keyframes. Default value: 10 |
seconds_per_frame | int | -1 | Frame extraction interval, unit: seconds; -1 means no specific interval. Default value: -1 |
output_tos_dir | str | Target path for saving keyframe images to TOS. If set to an empty string, images are not uploaded. Default value: "" |
The following code demonstrates how to use Daft in a distributed environment to run the operator and extract video keyframes.
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 import VideoKeyframes if __name__ == "__main__": # After extraction, keyframes will be saved to the specified TOS path. Therefore, environment variables must be set to ensure write permissions 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_keyframes" 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 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) extractor = las_udf( VideoKeyframes, construct_args={ "method": "I_frame", "keyframes_cnt": 5, "output_tos_dir": output_tos_dir, }, ) # Use Daft for distributed processing ds = ds.with_column("results", extractor(col("video_path"))) ds.show() # ╭────────────────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ # │ video_path ┆ results │ # │ --- ┆ --- │ # │ Utf8 ┆ Struct[keyframes: List[List[List[List[Int64]]]], base64: List[Utf8], timestamps: List[Float64], tos_paths: │ # │ ┆ List[Utf8]] │ # ╞════════════════════════════════╪════════════════════════════════════════════════════════════════════════════════════════════════════════════╡ # │ https://las-cn-beijing-publi-… ┆ {keyframes: [[[[9, 17, 16], [… │ # ╰────────────────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────╯