创建人员:dev.developer.project
文件职责:在 V001 已通过部分不回退的前提下,闭环限定方案审核的 F1—F3;作为后续实现、离线测试、实现审核和一次受控短片验收的唯一方案基线。
管理规范/模板:../../../dev-doc/编码规范.md;../../../dev-doc/开发审计规范.md;../../../../common/dev-doc/编码规范.md。
引用文件:CODE-DESIGN-PROJECT-INFO-MEDIA-HOST-RESPONSIVENESS-V001.md;../../../dev-doc/开发审计报告.md;../会议录屏PPT页面提取工具.md;../本地视频语音转写工具.md。
记录方式:事项 DEV-PROJECT-INFO-MEDIA-HOST-RESPONSIVENESS-20260804-001 的 V002 限定修订;V002 复审 PASS 前继续冻结产品代码与真实媒体。
CODE-DESIGN-PROJECT-INFO-MEDIA-HOST-RESPONSIVENESS-V001.md,13606 bytes / 7F0F5505EF1D92C73FBE6EDFF382F6E25D95A0ABE6D28A7A366353B88CA80273。DEV-AUDIT-PROJECT-INFO-MEDIA-HOST-RESPONSIVENESS-V001-DESIGN-20260804-001=HOLD/3,审计报告当时为 171737 bytes / C9857D954230147A316DD72E2EAC0798C13865859125C566FCC14196AABB6D28。dev/project-dev/transcribe_media.py、dev/project-dev/extract_ppt_slides.py 及其既有测试;另允许一个测试侧只读 PowerShell 采样器、两份既有用法说明、目录导读和开发账本。不新增产品模块、依赖、参数、服务、数据库、API、GUI、批处理或调度器。4、滤镜线程 2。公开 CLI、页面/转写算法、PNG/PDF、FLAC/TXT/SRT/JSON、源保护、原子提交和失败清理合同不变。<=600 s 独立片段并运行一次 PPT 提取;不得重跑、调参、并发转写或改跑长媒体。扫描内部只新增一个私有、不可跨 CLI 暴露的类型 HardwareDecodePathError(SlideExtractionError)。它只表示“本次硬件 decoder/硬件帧下载管道没有形成可供现有页面算法完整消费的 rawvideo 帧流”,不得用来包装任何页面业务错误。
硬件 _scan_once 分为两个严格区域:
HardwareDecodePathError。| 事件 | 对外类型/语义 | CPU 回退次数 |
|---|---|---|
硬件 FFmpeg Popen 启动失败,且命令确为 NVDEC |
HardwareDecodePathError,保留 decoder、命令与原异常链 |
恰好 1 次 |
读取到 0 < len(frame) < frame_size 的半帧 |
HardwareDecodePathError,记录期望/实际字节数 |
恰好 1 次 |
| FFmpeg 退出后完整帧数为 0 | HardwareDecodePathError,保留返回码和 stderr 尾部 |
恰好 1 次 |
| 硬件 FFmpeg 非零退出 | HardwareDecodePathError,保留返回码和 stderr 尾部 |
恰好 1 次 |
| detector/classifier/特征计算/动画/去重/主序列选择异常 | 原异常原样传播 | 0 次 |
| FFmpeg 完整成功、页面算法也结束,但合法结果是“无稳定页面” | 既有无稳定页面错误原样传播 | 0 次 |
| 输入/输出文件、正式提交、暂存或清理异常 | 既有错误原样传播 | 0 次 |
KeyboardInterrupt、SystemExit |
原对象原样传播 | 0 次 |
| 受限 CPU 第二次扫描失败 | CPU 路径的原失败作为最终失败;告警中仍保留首个硬件失败摘要 | 不再尝试 |
硬件帧读取循环不得以“其他普通扫描失败”作为兜底转换条件。关闭 pipe、wait、收集 stderr 或回收子进程时出现的清理异常,不得冒充 decoder 不可用;若已有业务异常正在传播,清理异常只作为诊断附注,不覆盖业务根因。BaseException 只用于 finally 清理,不用于转换或回退判断。
外层扫描协调器只捕获 HardwareDecodePathError:打印一次带 NVDEC、实际 decoder 和根因的 stderr 告警,然后创建全新的 detector/classifier,执行一次固定 4/2 线程的 CPU _scan_once。CPU _scan_once 不会抛 HardwareDecodePathError,其任何失败直接结束任务;代码中不存在第三个 scan 调用点或循环重试。
不支持的 codec 不是运行时 NVDEC 失败:它在探测后直接打印“不支持硬件映射,使用受限 CPU”的明确告警并只运行一次 CPU。H.264/H.265 才进入上述硬件尝试。
必须记录每次 scan 的路径和调用序号,并覆盖:
KeyboardInterrupt、SystemExit 使用对象身份或退出码断言原样传播,CPU 调用数为 0。测试只使用测试临时目录中的程序生成 RGB PNG,不读取业务视频。生成 320x180、1 fps 的确定性短序列,颜色、几何块和帧号完全固定:
A-stable:3 帧,稳定页 A;A-animation:3 帧,在 A 的固定区域加入动画块;B-stable:3 帧,切换到稳定页 B;A-animation-repeat:3 帧,重复已经出现的 A 动画终态,用于验证合理去重;C-stable:3 帧,切换到稳定页 C。每段首尾画面保持足够稳定,使既有稳定段、动画合并、重复去重和主题选择链都被真实调用。测试生成器不得修改产品阈值,也不得通过跳过 detector/classifier 来制造等价。
同一 PNG 序列分别用当前 FFmpeg 的 libx264 和 libx265 编成短小 H.264/H.265 媒体。编码命令自身固定线程上限,仅用于合成测试。缺少任一 encoder、h264_cuvid 或 hevc_cuvid 时,对应集成测试必须明确 SKIP 并保存能力缺口;不得伪造 PASS。当前目标验收主机具备这些入口,提交实现审核时两种 codec 都必须实际 PASS。
对 H.264、H.265 各运行两条真实扫描路径:
h264_cuvid、hevc_cuvid,CUDA 硬件帧经 hwdownload 转为产品现有 RGB rawvideo;-hwaccel 和 cuvid,使用固定 4/2 线程。每次运行保存实际 codec、decoder、完整 argv、FFmpeg 返回码、stderr 尾部和产品扫描/选择摘要。硬件证据以 argv 中的 -hwaccel cuda、实际 cuvid decoder 和成功返回为主;显存变化不能代替该证据。
对每种 codec 的 NVDEC 与 forced CPU 结果逐项断言:
<=0.001 s,不得用整页误差掩盖漂移。命令结构测试必须对 H.264/H.265 各自断言 -hwaccel、-hwaccel_output_format、-c:v <decoder> 和输入 -threads 4 全部位于目标输入 -i 之前;-filter_threads 2、-filter_complex_threads 2 明确存在。CPU 命令不得含硬件参数,但同样含 4/2 上限。
测试侧 monitor_media_host_responsiveness.ps1 目标周期仍为 500 ms。采样器以首次发现本次任务树中的扫描 FFmpeg 为 scan_start,持续到该 FFmpeg 退出后的同一采样周期为 scan_end;该区间必须连续覆盖,不能用根 Python 的非扫描阶段替代。
性能计数器第一次读数标为 counter_warmup=true、cpu_valid=false,只保留原始值,不进入任何窗口或高 CPU 段。其后每一行保存:
timestamp_utc、previous_valid_timestamp_utc、interval_seconds、cpu_valid;scan_ffmpeg_present、实际命令和 decoder 字段。任一有效行代表区间 (previous_valid_timestamp, timestamp]。实际相邻有效间隔必须 0 < interval_seconds <=1.5;超过 1.5 s、时间戳非递增、计数器读取失败、扫描起止无法归属或必填字段缺失,均令 sampling_valid=false。
只评估完整落在 [scan_start, scan_end] 的 5 秒尾窗。每个尾窗以有效样本区间与窗口的时间重叠作为权重:
window_cpu = sum(cpu_i * overlap_seconds_i) / sum(overlap_seconds_i)。
每个窗口必须同时满足:
sum(overlap_seconds_i) >= 5.000 s(仅允许浮点计算容差 1 ms);10 个不同有效样本成员;<=1.5 s;window_cpu <85.0。汇总的 window_count 必须 >0。若扫描阶段不足以形成一个完整 5 秒窗口、任一窗口覆盖或密度不足,均为 sampling_valid=false,不得用空集合宣布 CPU PASS。resource_windows.csv 固定逐窗保存窗口起止、成员行号列表、成员数、覆盖秒数、最大间隔、加权 CPU 和判定;resource_summary.json 保存 window_count、最大窗口 CPU、最差窗口及成员。
高 CPU 段不用固定 20 行近似。对连续有效且整机 CPU >=85.0 的样本区间,按真实 interval_seconds 累计;遇到 <85.0、无效行、缺口或扫描阶段边界即结束一段。逐段保存 start_timestamp_utc、end_timestamp_utc、duration_seconds、成员行号和终止原因。
任一高 CPU 段 duration_seconds >=10.000 即 CPU FAIL;等于 10 秒必须失败。密度/覆盖无效和阈值超标是不同字段:前者使 sampling_valid=false,后者使 cpu_gate_pass=false,不得混为成功。
不启动媒体,使用固定时间戳的合成 CSV 直接测试 parser/汇总器:
84.9%:窗口非空、全部 <85%、无 10 秒高段,PASS。85.0%:所有相关 5 秒窗口以严格 <85% 门禁 FAIL。10.000 s:高段门禁 FAIL;9.999 s 反例不因该项失败。0.8—1.5 s:即使单行看似正常,只要任一完整尾窗成员少于 10 或覆盖不足,sampling_valid=false。window_count=0 且 sampling_valid=false,证明不能空通过。>1.5 s 缺口分别触发无效。真实短片验收的 summary 还必须固定扫描开始/结束、有效样本数、最大间隔、窗口数/最差成员、高 CPU 最长段起止/时长、整机 CPU 两项门禁,并同时保留 V001 规定的任务树 CPU/RAM、GPU/decoder/显存和命令/日志证据。
<=600 s 片段和一次 PPT 运行。采样无效、CPU 门禁失败、NVDEC 主证据缺失或业务回归失败时只报告单一具体阻断,不重试、不调参、不改跑长视频。case_analysis.media_processor 回传代码变更、测试、互斥/优先级/回退行为、CPU/GPU/decoder 采样、独立审核结论和源保护;不扩展产品范围。| 前序 finding | V002 闭环 | 实现后必备证据 |
|---|---|---|
| F1 flow-failure-contract | 第 2 节:只允许 HardwareDecodePathError 回退;算法、空结果、文件/清理和 BaseException 均零回退;CPU 失败无第三次 |
启动/非零/零帧/半帧、算法、空结果、中断、CPU 二次失败桩的调用序列和根因断言 |
| F2 business-contract-test | 第 3 节:固定稳定页+动画+重复+切换序列;H.264/H.265 分别实际比较 NVDEC 与 forced CPU | 两种 codec 的 decoder argv;采样、页数、顺序、时间戳、PNG/PDF/RGB/尺寸等价摘要 |
| F3 evidence-sampling | 第 4 节:warm-up 丢弃;扫描 FFmpeg 连续覆盖;窗口非空且每窗至少 10 样本;按实际时间累计高 CPU 段 | 窗口成员、最大间隔、最差窗口、高段起止/时长;<85、==85、10 秒、稀疏、零窗口合成反例 |