You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中按起始/结束帧或精确时间戳提取视频片段?

精准提取视频片段(按帧索引/时间戳)

我需要根据给定的起始帧、结束帧索引(优先使用)或对应的时间戳从视频中提取片段,但目前找到的方案会将浮点数时间戳转换为整数,导致输出视频的帧不准确。以下是我尝试过但精度不足的代码:

方法1:使用ffmpeg-python的ffmpeg_extract_subclip

def extract_fragment(input_path, output_path):
    start_time = 3.453453
    end_time = 6.8768678

    ffmpeg_extract_subclip(
        filename=input_path,
        t1=start_time,
        t2=end_time,
        targetname=output_path,
    )

方法2:直接调用FFmpeg(带时长参数)

subprocess.call(
    [
        "ffmpeg",
        "-start_at_zero",
        "-copyts",
        "-ss",
        start_time,
        "-t",
        end_time - start_time,
        "-i",
        f"{path_to_video}",
        "-c",
        "copy",
        f"{output_video_path}",
    ]
)

方法3:另一种FFmpeg调用方式

subprocess.call(
    [
        "ffmpeg",
        "-y",
        "-ss",
        str(start_time),
        "-i",
        path_to_video,
        "-t",
        str(end_time),
        "-map",
        "0",
        "-vcodec",
        "copy",
        "-acodec",
        "copy",
        output_video_path,
    ]
)

解决方案

要实现精准提取,核心是让FFmpeg基于帧索引定位(优先),避免时间戳换算误差,同时规避流复制的关键帧限制。

1. 按帧索引提取(推荐)

先获取视频帧率,将帧索引转为高精度时间戳,再通过重新编码实现帧级切割:

import subprocess

def extract_by_frames(input_path, output_path, start_frame, end_frame):
    # 获取视频帧率
    fps_result = subprocess.run(
        ["ffmpeg", "-i", input_path, "-v", "error", "-select_streams", "v:0", "-show_entries", "stream=r_frame_rate", "-of", "default=noprint_wrappers=1:nokey=1"],
        capture_output=True,
        text=True
    )
    fps = eval(fps_result.stdout.strip())  # 解析帧率(如30/1转为30.0)

    # 计算精确时间戳
    start_time = start_frame / fps
    end_time = end_frame / fps

    # 调用FFmpeg执行精准切割
    subprocess.call([
        "ffmpeg",
        "-y",
        "-ss", f"{start_time:.6f}",  # 保留6位小数确保精度
        "-i", input_path,
        "-to", f"{end_time:.6f}",
        "-vcodec", "libx264",
        "-acodec", "aac",
        output_path
    ])

2. 优化时间戳提取(若必须用时间戳)

若只能用时间戳,需规避流复制的关键帧限制,同时保证时间戳精度:

import subprocess

def extract_by_timestamp(input_path, output_path, start_time, end_time):
    subprocess.call([
        "ffmpeg",
        "-y",
        "-ss", f"{start_time:.6f}",
        "-i", input_path,
        "-to", f"{end_time:.6f}",
        "-vcodec", "libx264",
        "-acodec", "aac",
        output_path
    ])

关键注意点

  • 禁用-c copy:流复制只能在关键帧处切割,会自动对齐到最近的关键帧,导致片段偏移。重新编码虽耗时,但能实现帧级精准切割。
  • 保留时间戳精度:传递时间戳时保留至少6位小数,避免浮点数精度丢失。
  • -ss参数位置:-ss放在-i前时速度更快(先跳转再读文件);放在-i后精度更高(先读文件再跳转),追求极致精度可选择后者。

内容的提问来源于stack exchange,提问作者cxnt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 18:05:19