feat: backfill_frames 支持压缩缓存回退 — 补齐全部历史事件帧图

原始视频被 Surveillance Station 保留策略删除后,回退到
/tmp/fam_compressed/task_{id}/ 的 480p 压缩副本抽帧。实测
event 18-27(08-14 晚间 10 事件)补 78 帧全部成功,至此
所有历史事件帧图齐全,UI 不再出现暂无帧图。
This commit is contained in:
ericwyuan
2026-08-20 22:42:08 +08:00
parent 3a3b68c428
commit 80cc3249e5

View File

@@ -81,7 +81,7 @@ def main():
try: try:
with conn.cursor() as cur: with conn.cursor() as cur:
sql = """ sql = """
SELECT me.event_id, me.event_start_time, pt.video_path, SELECT me.event_id, me.task_id, me.event_start_time, pt.video_path,
(SELECT COUNT(*) FROM event_details ed (SELECT COUNT(*) FROM event_details ed
WHERE ed.event_id = me.event_id) AS detail_count WHERE ed.event_id = me.event_id) AS detail_count
FROM monitor_events me FROM monitor_events me
@@ -115,8 +115,16 @@ def main():
continue continue
video = ev.get('video_path') or '' video = ev.get('video_path') or ''
source = '原始视频'
if not video or not os.path.isfile(video): if not video or not os.path.isfile(video):
print(f'[event {eid}] 视频不存在,跳过 {len(missing)} 帧: {video}') # 原始视频被监控保留策略清理时,回退到 dispatcher 压缩缓存480p 副本)
cached = os.path.join(
f'/tmp/fam_compressed/task_{ev["task_id"]}', os.path.basename(video)) if video else ''
if cached and os.path.isfile(cached):
video = cached
source = '压缩缓存'
if not video or not os.path.isfile(video):
print(f'[event {eid}] 原始视频与压缩缓存均不存在,跳过 {len(missing)} 帧: {video}')
stat['skip_no_video'] += 1 stat['skip_no_video'] += 1
continue continue
@@ -127,7 +135,7 @@ def main():
os.makedirs(edir, exist_ok=True) os.makedirs(edir, exist_ok=True)
stat['events'] += 1 stat['events'] += 1
print(f'[event {eid}] 补 {len(missing)}/{len(frames)} 帧 (视频 {os.path.basename(video)}, {dur:.0f}s)') print(f'[event {eid}] 补 {len(missing)}/{len(frames)} · {source} (视频 {os.path.basename(video)}, {dur:.0f}s)')
for f in missing: for f in missing:
out_path = os.path.join(edir, f'frame_{f["frame_index"]}.jpg') out_path = os.path.join(edir, f'frame_{f["frame_index"]}.jpg')