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

使用FFmpeg裁剪视频时出现帧序号偏移问题

解决FFmpeg裁剪59.94fps视频时的帧偏移问题

我之前处理非整数帧率视频时也碰到过一模一样的问题,尤其是你用的59.94fps(实际是60000/1001≈59.94fps)的MTS格式,很容易因为帧率特性和封装格式的细节出现帧偏移。下面给你拆解原因和解决办法:

核心问题分析

  1. 非整数帧率的计算偏差:59.94不是严格的整数,帧索引和实际时间的对应关系并非绝对线性,直接用start_frame/end_frame指定范围时,FFmpeg内部的帧计数逻辑容易出现累积误差,导致最终偏移。
  2. MTS视频的帧顺序差异:MTS属于MPEG-TS封装,视频流通常包含B帧(双向预测帧)——这类帧的存储顺序(DTS)和显示顺序(PTS)不一致。trim滤镜的start_frame是按显示顺序计数的,但实际裁剪时会受存储顺序影响,导致选中的帧和预期出现偏移。

解决方案

方案1:改用时间戳裁剪(最可靠)

先把目标帧索引转换成对应的时间,再用时间参数代替帧索引:

  • 开始时间:36435 / 59.94 ≈ 607.86秒
  • 结束时间:36786 / 59.94 ≈ 613.71秒

修改后的代码如下:

import os
import ffmpeg

print(os.listdir('C:/Users/sgris/Downloads'))
(
    ffmpeg
    .input('C:/Users/sgris/Downloads/apid/18-2-19 6.04pm.MTS')
    .trim(start=607.86, end=613.71)
    .setpts('PTS-STARTPTS')  # 重置时间戳,避免播放卡顿
    .output('C:/Users/sgris/Downloads/testtest2.mp4')
    .run()
)

如果想要极致精准,可以先用ffprobe查看目标帧的实际显示时间:

ffprobe -v error -select_streams v:0 -show_entries frame=frame_number,pkt_pts_time -of csv=p=0 "C:/Users/sgris/Downloads/apid/18-2-19 6.04pm.MTS" | grep "36435"

把返回的时间值直接填入start参数即可。

方案2:用select滤镜按帧索引选择(必须用帧索引时)

如果一定要基于帧索引裁剪,select滤镜的筛选逻辑更直接,会严格按显示顺序的帧序号挑选,同时重新计算时间戳:

import os
import ffmpeg

print(os.listdir('C:/Users/sgris/Downloads'))
(
    ffmpeg
    .input('C:/Users/sgris/Downloads/apid/18-2-19 6.04pm.MTS')
    .filter('select', 'between(n,36435,36786)')  # n代表显示顺序的帧序号
    .setpts('N/FRAME_RATE/TB')  # 基于实际帧率重新生成时间戳
    .output('C:/Users/sgris/Downloads/testtest2.mp4', vsync='vfr')  # 可变帧率输出,避免丢帧
    .run()
)

验证方法

裁剪后可以用以下命令检查输出视频的总帧数,确认是否符合预期(预期帧数:36786 - 36435 + 1 = 352帧):

ffprobe -v error -select_streams v:0 -show_entries stream=nb_frames "C:/Users/sgris/Downloads/testtest2.mp4"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 00:37:41