You need to enable JavaScript to run this app.
Lake AI Service

Lake AI Service

Copy page
Download PDF
Video processing
Video keyframe extraction
Copy page
Download PDF
Video keyframe extraction

Operator introduction

Description

Video keyframe extraction processor that supports dynamic detection using multiple algorithms.

Key features

  • Multi-algorithm support:
    • Pixel difference method (difference)
    • Optical flow method (optical_flow)
    • Histogram method (histogram)
    • I-frame identification (I_frame)
  • Supports custom threshold and quantity control
  • Provides timestamp positioning functionality
  • Supports multiple output formats and storage options

Format support

  • Input: MP4, AVI, MOV, and other common video formats
  • Output: JPG, PNG image formats

Performance recommendations

  • The I_frame method is the most efficient and is recommended as the preferred method

Daft invocation

Operator parameters

Input

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

Output

The processed array, with struct fields including:

  • keyframes: list[list[list[list[int]]]], array format of keyframe images
  • base64: list[str], base64 encoding of keyframe images
  • timestamps: list[float], timestamps corresponding to keyframes (unit: seconds)
  • tos_paths: list[str], storage paths of keyframes on TOS

Parameters

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: ""

Examples

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], […                                                                             │
    # ╰────────────────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Last updated: 2026.05.12 19:06:35