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

OpenCV如何读取动态FPS的H.265视频并计算已播放时长?

核心思路

动态FPS场景下计算累计播放时长的核心逻辑是不依赖固定帧率换算,直接使用每帧的实际显示时长或者帧的显示时间戳(PTS)判断,有两种常用实现方案:


方案1:预计算拆分点(批量处理优先)

适合不需要逐帧处理内容、只需要先确定拆分位置的场景,直接用你已经拿到的ffprobe输出计算即可:

  • ffprobe返回的每个视频packet的duration_time字段就是当前帧的实际显示时长,单位为秒,25FPS时该值为0.04,1FPS时该值为1.0,直接累加该值即可得到精确的累计播放时长。
  • 示例代码如下:
import json

# 加载ffprobe输出的JSON文件
with open("ffprobe_output.json", "r", encoding="utf-8") as f:
    ffprobe_data = json.load(f)

split_frame_indexes = []  # 存储每个5分钟分段的最后一帧索引
accumulated_duration = 0.0
split_threshold = 5 * 60  # 5分钟等于300秒

for frame_idx, packet in enumerate(ffprobe_data["packets"]):
    # 跳过非视频帧
    if packet["codec_type"] != "video":
        continue
    accumulated_duration += float(packet["duration_time"])
    # 累计时长达到阈值则记录拆分点
    if accumulated_duration >= split_threshold:
        split_frame_indexes.append(frame_idx)
        accumulated_duration = 0.0 # 重置下一个分段的时长计数器

方案2:OpenCV逐帧处理时实时判断

适合边读帧边分析内容的场景,直接读取OpenCV提供的帧时间戳判断即可:

  • OpenCV的VideoCapture接口提供了CAP_PROP_POS_MSEC参数,可以直接返回当前帧对应的实际播放时间戳,单位为毫秒,不需要自己累加计算。
  • 示例代码如下:
import cv2

cap = cv2.VideoCapture("你的视频文件路径.mp4")
current_segment_start_ms = 0
split_threshold_ms = 5 * 60 * 1000 # 5分钟换算为毫秒

while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        break
    # 读取当前帧的实际播放时间戳
    current_time_ms = cap.get(cv2.CAP_PROP_POS_MSEC)
    # 判断是否到达拆分点
    if current_time_ms - current_segment_start_ms >= split_threshold_ms:
        # 此处执行你的分段保存、分段统计逻辑
        print(f"到达5分钟拆分点,当前累计播放时长:{current_time_ms/1000}秒")
        current_segment_start_ms = current_time_ms
    # 此处执行你的单帧分析逻辑

cap.release()

注意事项

  • 不要依赖OpenCV返回的CAP_PROP_FPS值计算时长,动态FPS视频的该值一般是平均帧率或者最高帧率,计算出来的时长和实际播放时长误差极大
  • 如果发现CAP_PROP_POS_MSEC返回值不准,优先用ffprobe预读所有帧的duration_time累加的方案,精度更高

内容的提问来源于stack exchange,提问作者s.paszko

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 02:42:00