v0.3.0 — 第三阶段:文件导入 + 字幕探测 + 融合体验
状态 : 代码已交付(2026-08-18 构建完成:M1/M2/M3/M4 + REQ-035 实时活动面板;真机验收待执行;REQ-019/020 闪卡顺延)
目标 : 打通"视频文件导入 → 字幕优先(文件级 100% 准确)→ 无字幕 fallback ASR"的第二入口;优化实时链路停止体验(融合停止异步化);同步修复采集链路三缺陷并并入三项头脑风暴优化;新增采集期间实时活动面板。
关联 : 需求池 v0.3.0 · ADR-006 · ADR-008 · 采集链路技术审查([ ] 已归档) · 头脑风暴 P6/T2/P3/P4
视频文件导入可用 :ffmpeg 提取音轨 + 关键帧,文件路径作为实时捕获之后的第二入口
字幕优先转写可用 :外挂字幕文件(.srt/.ass/.vtt)探测与内嵌字幕轨解析(L1/L2),命中则零成本 100% 准确,免 ASR
融合停止体验优化 :停止按钮秒回(REQ-031:融合异步化 + 无字幕短路)
采集链路质量优化 (REQ-034):时间戳统一、句起时间戳、引擎池并行、分窗转写、多帧投票、OCR 输入缩小、语音/画面互斥调度
实时活动面板 (REQ-035):采集期间右侧简要转写流/画面要点流/状态机
本阶段不做 :闪卡(REQ-019/020,用户决策顺延至 v0.4.0);会话段派生视图(REQ-032,V1.0);AI 问答与精修(REQ-024/025,V1.0)。
REQ
内容
验收要点
规划状态
REQ-015
视频文件导入:ffmpeg 提取音轨 + 关键帧
选择视频文件 → 提取 16kHz 音轨 + 关键帧序列入会话管线
已实现(代码已交付 2026-08-18,真机验收待执行)
REQ-016
字幕探测 L1:外挂字幕文件(同名 .srt/.ass/.vtt)
命中则免 ASR,字幕直出转写(100% 准确)
已实现(代码已交付 2026-08-18,真机验收待执行)
REQ-017
字幕解析 L2:容器内嵌字幕轨(ffprobe + 解码)
mov_text/subrip/ass/webvtt 解码为字幕段
已实现(代码已交付 2026-08-18,真机验收待执行)
REQ-018
字幕优先策略:有字幕→直出转写;无字幕→fallback ASR
按 REQ-016/017 命中结果自动选择转写路径
已实现(代码已交付 2026-08-18,真机验收待执行)
REQ-031
融合停止异步化 + 无字幕短路
停止秒回;融合后台执行;无字幕段跳过融合;完成事件刷新详情页
已实现(代码已交付 2026-08-18,真机验收待执行)
REQ-034
采集链路质量优化:时间戳统一/句起时间戳/引擎池并行/分窗转写/多帧投票/OCR 缩小/互斥调度
见 ADR-008 合规性验证
已实现(代码已交付 2026-08-18,真机验收待执行)
REQ-035
实时活动面板:采集期间右侧简要转写流/画面要点流/状态机
采集期间右侧显示最近 6 条转写/4 条画面要点;状态机徽标;停止/融合期面板保持
已实现(代码已交付 2026-08-18,真机验收待执行)
REQ-033
采集持续不间断运行:关闭保护 + 音频重连 + 屏幕自愈
采集中关闭弹确认框;插拔设备会话不死亡、时间戳连续;锁屏/远程桌面自动恢复 DXGI;全局采集徽标
已实现(ADR-007 )
REQ-019/020
闪卡 SM-2 + 笔记→闪卡一键生成
—
顺延 v0.4.0(用户决策 2026-08-18)
ffmpeg 解析 :ENTROPY_FFMPEG_DIR(测试注入)→ 捆绑 src-tauri/ffmpeg/(scripts/download-ffmpeg.ps1 下载,gitignore)→ PATH;全缺失返回可操作错误
管线 (import_video command,spawn_blocking + 进度事件):
建会话(title=文件名,source_window=None)
ffmpeg 提取 16kHz 单声道 WAV → data_dir/import/<id>/
字幕决策(M2):L1 命中 → 字幕直出(免 ASR);否则 L2;再否则分窗 ASR
分窗转写(无字幕路径):WAV 按 30s 窗切分 → transcribe_pcm 逐窗 → 真实时间戳段
关键帧:fps=1/10 封顶 60 帧 → 逐帧 OCR 落 OCR 块(单帧失败跳过不阻断)
finish 会话 + 清理中间文件
安全 :Command 参数数组(防注入)、子进程有界等待(超时 kill)、路径限定数据目录
M2 字幕探测与优先(REQ-016/017/018)
L1 外挂 (subtitle.rs 纯文本解析,零新依赖):同名探测 .srt/.ass/.vtt;编码探测 UTF-8 严格 → GBK(CP936,windows crate Win32_Globalization);SRT/VTT/ASS 三格式解析为 SubtitleSegment
L2 内嵌 :ffprobe -select_streams s → ffmpeg -map 0:s:0 -f srt - 解出 → 复用 L1 解析器;ffmpeg 缺失报可操作错误
策略 :L1 → L2 → ASR 三级降级;关键帧 OCR 始终执行(独立于转写路径)
M3 融合停止异步化 + 无字幕短路(REQ-031)
用户点停止
├─ 1. finish_session(毫秒级)
├─ 2. emit "live:stopped"(秒回)
└─ 3. 后台线程(std::thread::spawn):
├─ 无字幕段 → 直接 return(短路:融合=ASR 原样拷贝)
├─ 否则 → merge_transcript + replace_segments(沿用 ADR-005 原子事务)
└─ 完成 → emit "session:fused"(失败 "session:fusion-failed",原段保留)
状态标记 :内存方案——LiveSessionManager 持 fusing: HashSet<i64>(不迁移表,ADR-006 派生表 V1.0 取代)
细节 :融合线程持有 Db/AppHandle 克隆与字幕/ASR 段所有权;详情页融合完成前显示原始轴,session:fused 到达后刷新
项
内容
涉及文件
A1 时间戳统一
会话纪元 epoch 注入音频/屏幕/flush 三处
audio_loopback.rs / live_session.rs / live_session_frame.rs
A2 句起时间戳
Final 后首个非静音块时间戳为句起(替代 end-2000ms)
live_session.rs
A3 引擎池并行
ASR/OCR 双 worker 线程(API 不变)
engine.rs
A4 分窗转写
导入 WAV 30s 窗逐窗转写 + 进度
import.rs
B1 多帧投票(T2)
字幕样本累积 + 字符多数投票输出校正文本
subtitle_ocr.rs / live_session_frame.rs
B2 OCR 输入缩小(P4)
字幕裁剪区 >960px 最近邻缩小
frame_diff.rs / live_session_frame.rs
B3 互斥调度(P3)
静音期全帧提频(每 2 tick),语音期字幕区为主
frame_diff.rs / live_session.rs
B4 导入区域裁剪(TD-037)
关键帧中部(full)+ 底部(subtitle)两路裁剪缩 960px + 帧间去重
import_frame.rs / import.rs
B5 强制 OCR 兜底
diff 采样漏检防御:距上次识别超 15s 强制识别 + 全帧文本去重
live_session_frame.rs
事件 :live:asr-final(语音定稿,含停止 flush 尾句)、live:ocr(画面要点落库即推)——载荷携带后端会话纪元时间戳 (TD-043);live:subtitle 同步扩展
面板 (LiveActivityPanel.tsx,用户要求"简要"):转写流仅显示最近 6 条 、画面要点最近 4 条 ,总数在状态行计数,超出显示省略提示;状态机一行(采集中/已停止/融合中/完成/异常);停止过渡与融合期面板保持显示
工程修复 :live:status 区分 payload(录制态不再被 recording 事件错误重置);stopping 10s 超时兜底(TD-042);左栏移除重复实时文本(统一由面板展示)
步骤
内容
产出
M1
文件导入(REQ-015)
文件会话入口 + 提取管线
M2
字幕探测 L1/L2(REQ-016/017/018)
字幕解析模块 + 优先策略
M3
融合停止异步化(REQ-031)
停止秒回 + 无字幕短路 + 单测
M4
采集质量优化(REQ-034)
七项优化 + 单测
M5
端到端验收
文件会话/实时会话全链路