基于Tapo TC70视频媒体创建时间提取帧时间戳的问题咨询
问题:基于Tapo TC70视频帧生成准确时间戳的偏差问题
我的目标是基于视频的媒体创建时间获取每帧的准确日期和时间戳,并通过cv2.putText()在输出视频中显示。
实现思路:获取视频文件媒体创建时间的UNIX格式时间戳,结合每帧的毫秒位置(cap.get(cv2.CAP_PROP_POS_MSEC))转换为秒后相加,公式为:
UNIX格式媒体创建时间 + cap.get(cv2.CAP_PROP_POS_MSEC)/1000 = 第n帧的日期时间戳
对应代码如下:
from win32com.propsys import propsys, pscon # excluded from the for loop, only imported once from datetime import datetime import cv2 # Get media created UNIX-formatted timestamp of the input video properties = propsys.SHGetPropertyStoreFromParsingName(videofilepath.replace('/', '\\')) dt_property = properties.GetValue(pscon.PKEY_Media_DateEncoded).GetValue() input_video_creation_timestamp_unix = dt_property.timestamp() # Calculate the date and timestamp of the frame then display it using cv2.putText(). Please do note that this is applied to each frame of the input video im0 = cv2.putText(im0, f'{datetime.fromtimestamp(input_video_creation_timestamp_unix + (vid_cap.get(cv2.CAP_PROP_POS_MSEC)/1000))}', (50,150), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 2, cv2.LINE_AA)
但我在媒体创建时间取值和帧时间戳计算上遇到两个问题:
- 视频来自TP-Link的Tapo TC70摄像头,属性详情中显示的媒体创建时间与代码获取的
dt_property值存在约2秒偏差,请问原因及解决方法? - 对于2分钟的视频,计算出的帧最终日期时间戳存在约1秒偏差,如何实现与Tapo TC70显示一致的准确时间戳?
解决方案
问题1:媒体创建时间的2秒偏差
可能原因
- Tapo TC70的
PKEY_Media_DateEncoded字段记录的是视频编码完成时间,而非实际开始录制的起始时间,摄像头启动录制流程到完成编码会产生几秒延迟 - Windows属性面板显示的通常是文件的系统创建时间(即视频文件写入本地磁盘的时间),和媒体内部的编码时间存在天然差异
解决方法
- 尝试读取视频的EXIF元数据或摄像头专属元数据:部分监控摄像头会在视频流中嵌入精确的录制起始时间,可借助
exifread或ffprobe工具提取 - 改用文件系统创建时间对比:替换
pscon.PKEY_Media_DateEncoded为pscon.PKEY_DateCreated,获取Windows属性面板显示的时间,再根据偏差调整偏移量 - 手动校准偏移:录制一段已知精确起始时间的视频,计算代码获取时间与实际起始时间的差值,在代码中固定增减该偏移量(例如
input_video_creation_timestamp_unix - 2)
问题2:2分钟视频的1秒累计偏差
可能原因
cv2.CAP_PROP_POS_MSEC是基于视频文件头标注的帧率估算的时间,而非每帧的实际时间戳,当视频存在丢帧、帧率波动时,累计误差会随时间放大- Tapo TC70的实际录制帧率可能和文件头标注的帧率不一致(例如标注25fps,实际为24.97fps),长期计算会产生偏差
解决方法
- 用帧索引计算精确时间:优先通过帧索引和实际帧率计算时间,替代
CAP_PROP_POS_MSEC,代码示例:frame_idx = vid_cap.get(cv2.CAP_PROP_POS_FRAMES) fps = vid_cap.get(cv2.CAP_PROP_FPS) frame_time = frame_idx / fps exact_timestamp = input_video_creation_timestamp_unix + frame_time im0 = cv2.putText(im0, f'{datetime.fromtimestamp(exact_timestamp)}', (50,150), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 255, 0), 2, cv2.LINE_AA) - 提取视频原始时间戳:如果Tapo TC70在录制文件中嵌入了每帧的UTC时间戳,可使用
ffprobe工具提取时间戳列表,再映射到处理的每帧 - 校准累计误差:录制一段时长精确的视频,计算总偏差值,按时间比例在每帧中调整(例如2分钟误差1秒,每帧减去
1/(120*fps)秒)
内容的提问来源于stack exchange,提问作者Jco
相关产品推荐
相关产品推荐

