创建人员:dev.developer.project
文件职责:在 V001 已冻结合同上,补齐正式输出提交的中断回滚,以及 4 小时验收的外部资源采样和正确性证据合同。
管理规范/模板:../../../dev-doc/编码规范.md;../../../dev-doc/开发审计规范.md;../../../../common/dev-doc/编码规范.md。
引用文件:CODE-DESIGN-PROJECT-INFO-LOCAL-MEDIA-TRANSCRIBE-LONG-VIDEO-OPT-V001.md;../../../dev-doc/开发审计报告.md;../../../ai-media-processor/draft/本地视频语音转写_4小时长视频性能与资源优化需求_v0.1.md;../../../dev/project-dev/transcribe_media.py;../../../dev/project-dev/test/test_transcribe_media.py。
记录方式:V001 的后继方案;只闭环审核 F1/F2,V001 已通过合同保持冻结,复审通过前不实现。
DEV-PROJECT-INFO-LOCAL-MEDIA-TRANSCRIBE-LONG-VIDEO-OPT-20260801-001。DEV-AUDIT-PROJECT-INFO-LOCAL-MEDIA-TRANSCRIBE-LONG-VIDEO-OPT-DESIGN-20260801-001=HOLD/2。F1 的 BaseException 提交回滚合同与注入测试;F2 的外部只读资源采样器和完整验收证据清单。duration <= 1200 s 走原路径;长视频使用 1200 s 核心块、两侧 5 s 重叠、首尾裁边和中点唯一归属;模型一次加载、首块语言检测后复用;完整 FLAC 加最多一个临时块;不扩展 CPU/模型降级、GUI、API、数据库、批处理或断点续跑。_commit_outputs 仍按 FLAC、TXT、SRT、JSON 的既有顺序逐项 Path.replace,外部签名和无覆盖检查不变,但提交区的捕获边界从 Exception 扩大为 BaseException:
BaseException 后,对已移动文件逐项执行无覆盖目标的删除;只有本次调用创建且已为空的正式目录才删除。回滚本身采用尽力但不遮蔽原异常的清理分支,并保留回滚失败详情供普通异常错误消息使用。KeyboardInterrupt、SystemExit 或其他非 Exception 的 BaseException,回滚结束后以裸 raise 原样重抛;main 继续按现有合同把 KeyboardInterrupt 转为退出码 130,不会伪装成普通转写错误。Exception,回滚后继续包装为现有 MediaTranscriptionError("提交输出文件失败,已回滚已写结果……");不改变 CLI 退出码或用户可见合同。transcribe_video(...): finally 继续删除相邻暂存目录;提交函数不删除原视频、不覆盖既有正式文件,也不删除调用前已经存在的输出目录。如果某个正式文件无法回滚,错误信息必须明确列出残留路径;不得打印“未提交输出文件”或将该运行判为成功。该情况不改变本需求的正常验收路径,但防止回滚失败被静默掩盖。
在系统临时目录使用四个合成暂存文件,参数化注入 KeyboardInterrupt:分别在第 1、2、3 个文件成功移动后、下一个提交动作开始前中断。每个用例必须断言:
KeyboardInterrupt,不是 MediaTranscriptionError;transcribe_video 的集成清理用例中,相邻暂存目录不存在;另保留一个普通 OSError 注入用例,证明仍被包装为 MediaTranscriptionError 且已移动正式文件回滚。现有 6 项测试必须全部回归。
新增仅供真实验收使用的 dev/project-dev/test/monitor_transcribe_resources.ps1;它不进入生产 CLI,不修改被测脚本,也不读取或写入模型、源视频或正式输出内容。采样器负责启动隔离环境中的 Python 命令并把该 Python PID 冻结为 root_python_pid。
500 ms,从根 Python 创建后开始,到根进程退出且最后一次样本落盘后结束;周期和实际采样时间均写证据。ParentProcessId 递归构造根 Python 的后代集合;仅名称为 ffmpeg.exe 的后代计入 FFmpeg 工作集。每条样本保存根 PID、后代 PID/父 PID/进程名;不把系统中其他 Python 或 FFmpeg 进程计入。WorkingSet64、全部归属 FFmpeg 子进程 WorkingSet64 之和,以及同一采样时点的两者合计;任务和逐块 RAM 峰值均取“同一时点合计”的最大值,不把两个不同时点的独立峰值相加。nvidia-smi --query-compute-apps=pid,used_gpu_memory --format=csv,noheader,nounits,只汇总根 Python 和其后代 PID;另记录 GPU 型号。系统全局显存可作诊断列,但不得用于替代本任务 PID 归属值。正在转写分块 i/n 宣告当前块;采样器解析 stdout 并把最后一次已宣告的 block_index/block_total 绑定到样本。完整 FLAC 提取和模型加载阶段块号为空,仍计入任务全局峰值。*.flac,记录完整 FLAC、分块 FLAC的路径类别、数量和字节;临时块指标单独排除正式候选完整 FLAC,只允许同时最多 1 个分块文件且单块峰值 <500 MB。若根 PID、进程树、GPU 查询、块号关联或必填样本字段缺失,采样器必须把 sampling_valid=false 和具体原因写入汇总;该次运行不得宣告资源验收 PASS。采样器只在下述任务临时根写证据,不触碰原视频及其目录。
真实 19:54 回归与 4 小时运行分别使用独立子目录,并至少保存:
command.json:原样参数数组、环境 Python 绝对路径、开始/结束时间、退出码、墙钟耗时、采样周期和根 PID;stdout.log、stderr.log:完整且按产生顺序写入;resource_samples.csv:timestamp_utc,elapsed_seconds,root_python_pid,descendant_processes,block_index,block_total,python_working_set_bytes,ffmpeg_working_set_bytes,combined_working_set_bytes,task_gpu_memory_mib,temp_chunk_count,temp_chunk_bytes;resource_block_peaks.csv:每块的首末采样时间、样本数、Python/FFmpeg/合计 RAM 峰值、任务 GPU 峰值、临时块数量和字节峰值;resource_summary.json:采样有效性、GPU 型号、全局峰值、逐块峰值、门禁值和逐项 PASS/FAIL;acceptance_evidence.json:源文件前后指纹、媒体/四文件属性、时间轴与边界核验结果。resource_summary.json 必须直接计算并保存:
ram_growth_bytes = max(last_3_block_ram_peaks) - max(first_3_block_ram_peaks)
其中 block_ram_peak 是该块内 combined_working_set_bytes 的最大样本;4 小时 12 块运行的门禁为 ram_growth_bytes <= 2 * 1024^3。同时要求任务全局 combined_working_set_bytes <= 12 * 1024^3、任务 GPU 峰值 < 10 * 1024 MiB、临时分块数量 <=1、临时分块峰值 <500 * 1024^2。不得用平均值、进程全局值或前三/后三块以外窗口替代。
acceptance_evidence.json 的自动核验不得省略以下项目:
G:\熊猫财经\20260731-155802.mp4 在任何生成/回归动作前、全部动作结束后分别记录 size_bytes、CreationTimeUtc、LastWriteTimeUtc、SHA-256,四项逐一相等;原视频不移动、重命名、覆盖或删除。duration <= 1200 s、未出现分块进度、四文件完整、FLAC 为 16000 Hz/1 ch,并核对既有 705 段基线及 TXT/SRT/JSON 对应。0、墙钟 <=100 min,四文件均存在且没有额外正式输出。flac/16000/1,且其时长与测试媒体音轨在明确的 FFmpeg 封装容差内。large-v3/cuda/float16/vad_filter=true;每段满足 0 <= start <= end <= flac_duration。最终段按 (start,end,text) 非递减排序;SRT 序号严格为 1..N,时间合法且与对应 JSON 段一致;TXT 非空行、SRT 块、JSON 段的数量和文本逐项一致。1200,2400,...,13200 s 自动导出 [boundary-15,boundary+15] 内的 JSON/SRT/TXT 对照行;逐边界记录无重复段、无逆序、无非法时间,并人工抽查可读性后记录 reviewer/time/result。不得只抽首、中、末三个位置。1..12 且只出现一次开始宣告;全局输出段保持连续 SRT 序号。开始前三块与最后三块必须各有样本和峰值,否则 RAM 增长结论无效。PASS 后才修改代码与测试。case_analysis.media_processor 完成只读复核;不在本事项中扩展修复范围。| 审核项 | V002 闭环位置 | 验收门禁 |
|---|---|---|
F1 用户中断可留下部分正式输出 |
第 2 节 | 捕获 BaseException、先回滚、非普通异常原样重抛;第 1/2/3 次成功移动后注入中断,四正式文件和暂存均不存在 |
F2 资源采样不可复核 |
第 3 节 | 外部采样器、500 ms、根 PID/FFmpeg 后代归属、逐样本/逐块/汇总证据、固定 RAM 增长公式 |
F2 正确性和源不变证据不完整 |
第 4 节 | 全部边界 ±15 s、合法范围、排序/连续序号、四文件一致、源大小/创建与修改时间/SHA-256 前后对照 |
PENDING_INDEPENDENT_DESIGN_REREVIEW