feat(events): 每个事件生成对应时间点画面截图 - oracle_db.mark_video_processed 返回 event_ids;video_processor 按事件时间戳-视频起始时间偏移跳帧截图存 ev_{id}.jpg;新增 /api/oracle/event/{id}/thumb 接口;fam-ui 事件列表每条显示对应截图

This commit is contained in:
ericwyuan
2026-08-21 13:44:16 +08:00
parent 41485072bf
commit 05f727a9ef
4 changed files with 95 additions and 13 deletions

View File

@@ -279,7 +279,7 @@ def page_header(icon: str, title: str, sub: str = ''):
def render_event_list(events: list):
"""渲染事件时间线:左相对时间 + 右事件卡(人物/关注徽章 + 描述)"""
"""渲染事件时间线:左相对时间 + 右事件卡(事件画面截图 + 人物/关注徽章 + 描述)"""
items = []
for e in events:
ts = parse_ts(e.get('ts'))
@@ -288,6 +288,16 @@ def render_event_list(events: list):
persons = parse_persons(e.get('person_list_json'))
attention = bool(e.get('is_attention_event'))
desc = e.get('description') or '(无描述)'
eid = e.get('id')
# 事件对应时间点的画面截图Oracle 带 token 接口;加载失败自动隐藏)
img_html = ''
if _oracle_url and eid:
img_html = (
f'<img src="{_oracle_url}/api/oracle/event/{eid}/thumb?token={_oracle_token}" '
f'style="width:100%;max-height:200px;object-fit:cover;border-radius:8px;'
f'margin-bottom:6px;" '
f'onerror="this.style.display=\'none\'"/>')
badges = ''.join(
f'<span class="bdg bdg-person">{esc(p)}</span>' for p in sorted(persons))
@@ -298,7 +308,7 @@ def render_event_list(events: list):
f'<div class="ev-item {"attention" if attention else ""}">'
f'<div class="ev-time">{esc(time_label)}'
f'{f"<span class=cam>{esc(camera)}</span>" if camera else ""}</div>'
f'<div class="ev-card">{badges}'
f'<div class="ev-card">{img_html}{badges}'
f'<div class="ev-desc">{esc(desc)}</div></div>'
f'</div>'
)
@@ -546,7 +556,7 @@ if page == "🕒 事件时间轴":
try:
cursor = conn.cursor()
cursor.execute(
"""SELECT e.ts, e.description, e.person_list_json,
"""SELECT e.id, e.ts, e.description, e.person_list_json,
e.is_attention_event, v.camera_name
FROM sync_events e
JOIN sync_videos v ON e.video_id = v.id