edit | blame | history | raw

本地媒体主机响应保护编码方案 V002

创建人员: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 前继续冻结产品代码与真实媒体。

1. 修订依据与不回退合同

  • 前序方案:CODE-DESIGN-PROJECT-INFO-MEDIA-HOST-RESPONSIVENESS-V001.md13606 bytes / 7F0F5505EF1D92C73FBE6EDFF382F6E25D95A0ABE6D28A7A366353B88CA80273
  • 前序审核:DEV-AUDIT-PROJECT-INFO-MEDIA-HOST-RESPONSIVENESS-V001-DESIGN-20260804-001=HOLD/3,审计报告当时为 171737 bytes / C9857D954230147A316DD72E2EAC0798C13865859125C566FCC14196AABB6D28
  • 本版只修订 F1“回退归因边界”、F2“H.264/H.265 业务等价合成门禁”和 F3“资源采样非空与时间口径”。V001 第 2、3、4.1、4.2、5、7.1 和 8 节中与三项修订不冲突的内容继续有效。
  • 产品文件仍仅允许修改 dev/project-dev/transcribe_media.pydev/project-dev/extract_ppt_slides.py 及其既有测试;另允许一个测试侧只读 PowerShell 采样器、两份既有用法说明、目录导读和开发账本。不新增产品模块、依赖、参数、服务、数据库、API、GUI、批处理或调度器。
  • 两 CLI 继续共用非阻塞 Windows named mutex;根 Python 和产品默认 FFprobe/FFmpeg 全生命周期使用 BelowNormal;固定解码线程 4、滤镜线程 2。公开 CLI、页面/转写算法、PNG/PDF、FLAC/TXT/SRT/JSON、源保护、原子提交和失败清理合同不变。
  • 实现审核 PASS 前仍不得读取或运行真实源、不得生成真实片段。实现审核 PASS 后最多只读生成一个 <=600 s 独立片段并运行一次 PPT 提取;不得重跑、调参、并发转写或改跑长媒体。

2. F1:硬件可归因失败与单次回退边界

2.1 类型边界

扫描内部只新增一个私有、不可跨 CLI 暴露的类型 HardwareDecodePathError(SlideExtractionError)。它只表示“本次硬件 decoder/硬件帧下载管道没有形成可供现有页面算法完整消费的 rawvideo 帧流”,不得用来包装任何页面业务错误。

硬件 _scan_once 分为两个严格区域:

  1. 外部解码/传输区域:组装和启动 FFmpeg、读取固定大小 rawvideo 帧、等待 FFmpeg、解释返回码和 stderr。只有本区域下表列出的失败可转换为 HardwareDecodePathError
  2. 页面业务区域:把已经读满的单帧交给既有稳定段 detector、页面 classifier、动画/去重和主课件选择。这里的异常保留原类型、原消息和原 traceback;不得被硬件错误捕获器包围,也不得触发 CPU。
事件 对外类型/语义 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 次
KeyboardInterruptSystemExit 原对象原样传播 0 次
受限 CPU 第二次扫描失败 CPU 路径的原失败作为最终失败;告警中仍保留首个硬件失败摘要 不再尝试

硬件帧读取循环不得以“其他普通扫描失败”作为兜底转换条件。关闭 pipe、wait、收集 stderr 或回收子进程时出现的清理异常,不得冒充 decoder 不可用;若已有业务异常正在传播,清理异常只作为诊断附注,不覆盖业务根因。BaseException 只用于 finally 清理,不用于转换或回退判断。

2.2 唯一回退控制流

外层扫描协调器只捕获 HardwareDecodePathError:打印一次带 NVDEC、实际 decoder 和根因的 stderr 告警,然后创建全新的 detector/classifier,执行一次固定 4/2 线程的 CPU _scan_once。CPU _scan_once 不会抛 HardwareDecodePathError,其任何失败直接结束任务;代码中不存在第三个 scan 调用点或循环重试。

不支持的 codec 不是运行时 NVDEC 失败:它在探测后直接打印“不支持硬件映射,使用受限 CPU”的明确告警并只运行一次 CPU。H.264/H.265 才进入上述硬件尝试。

2.3 F1 离线桩门禁

必须记录每次 scan 的路径和调用序号,并覆盖:

  1. 硬件启动失败、非零退出、零帧、半帧各自只触发一次 CPU;CPU 成功时总尝试数严格为 2。
  2. detector 异常、classifier 异常、无稳定页面、文件/清理异常的 CPU 调用数严格为 0,异常类型、消息和因果链不被改写为 NVDEC 错误。
  3. 硬件阶段 KeyboardInterruptSystemExit 使用对象身份或退出码断言原样传播,CPU 调用数为 0。
  4. CPU 第二次失败时总尝试数严格为 2,没有第三次;最终错误是 CPU 根因,stderr 告警仍含首个硬件根因,二者不互相覆盖。

3. F2:H.264/H.265 双路径业务等价合成门禁

3.1 固定合成序列

测试只使用测试临时目录中的程序生成 RGB PNG,不读取业务视频。生成 320x1801 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 的 libx264libx265 编成短小 H.264/H.265 媒体。编码命令自身固定线程上限,仅用于合成测试。缺少任一 encoder、h264_cuvidhevc_cuvid 时,对应集成测试必须明确 SKIP 并保存能力缺口;不得伪造 PASS。当前目标验收主机具备这些入口,提交实现审核时两种 codec 都必须实际 PASS。

3.2 四组实际扫描

对 H.264、H.265 各运行两条真实扫描路径:

  • NVDEC:分别固定 h264_cuvidhevc_cuvid,CUDA 硬件帧经 hwdownload 转为产品现有 RGB rawvideo;
  • forced CPU:同一媒体、同一采样/缩放/业务函数,但禁用 -hwaccel 和 cuvid,使用固定 4/2 线程。

每次运行保存实际 codec、decoder、完整 argv、FFmpeg 返回码、stderr 尾部和产品扫描/选择摘要。硬件证据以 argv 中的 -hwaccel cuda、实际 cuvid decoder 和成功返回为主;显存变化不能代替该证据。

3.3 等价断言

对每种 codec 的 NVDEC 与 forced CPU 结果逐项断言:

  1. 输入采样数相同;稳定候选数和动画更新数相同。
  2. 去重后的逻辑页数相同;主序列选中页的逻辑标识及顺序相同。
  3. 每个选中页的相对时间戳相同;允许的唯一浮点误差为 <=0.001 s,不得用整页误差掩盖漂移。
  4. 完整产品提取生成的 PNG 数、连续编号、顺序、RGB 模式和尺寸相同;PDF 页数、顺序、每页 RGB 图像尺寸相同。
  5. 不要求 NVDEC/CPU PNG 或 PDF 压缩字节逐字节相同;但是任一业务页、时间、数量、顺序、模式或尺寸漂移即阻断。

命令结构测试必须对 H.264/H.265 各自断言 -hwaccel-hwaccel_output_format-c:v <decoder> 和输入 -threads 4 全部位于目标输入 -i 之前;-filter_threads 2-filter_complex_threads 2 明确存在。CPU 命令不得含硬件参数,但同样含 4/2 上限。

4. F3:非空、连续且按真实时间判定的资源采样

4.1 采样阶段与有效行

测试侧 monitor_media_host_responsiveness.ps1 目标周期仍为 500 ms。采样器以首次发现本次任务树中的扫描 FFmpeg 为 scan_start,持续到该 FFmpeg 退出后的同一采样周期为 scan_end;该区间必须连续覆盖,不能用根 Python 的非扫描阶段替代。

性能计数器第一次读数标为 counter_warmup=truecpu_valid=false,只保留原始值,不进入任何窗口或高 CPU 段。其后每一行保存:

  • timestamp_utcprevious_valid_timestamp_utcinterval_secondscpu_valid
  • 整机 CPU、任务 PID 集、任务树 CPU/RAM、根/FFmpeg PriorityClass;
  • GPU utilization、decoder utilization、全局显存、PID 专用显存及原始查询状态;
  • scan_ffmpeg_present、实际命令和 decoder 字段。

任一有效行代表区间 (previous_valid_timestamp, timestamp]。实际相邻有效间隔必须 0 < interval_seconds <=1.5;超过 1.5 s、时间戳非递增、计数器读取失败、扫描起止无法归属或必填字段缺失,均令 sampling_valid=false

4.2 五秒尾窗公式与非空性

只评估完整落在 [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、最差窗口及成员。

4.3 连续高 CPU 的真实时间公式

高 CPU 段不用固定 20 行近似。对连续有效且整机 CPU >=85.0 的样本区间,按真实 interval_seconds 累计;遇到 <85.0、无效行、缺口或扫描阶段边界即结束一段。逐段保存 start_timestamp_utcend_timestamp_utcduration_seconds、成员行号和终止原因。

任一高 CPU 段 duration_seconds >=10.000 即 CPU FAIL;等于 10 秒必须失败。密度/覆盖无效和阈值超标是不同字段:前者使 sampling_valid=false,后者使 cpu_gate_pass=false,不得混为成功。

4.4 F3 合成 CSV 门禁

不启动媒体,使用固定时间戳的合成 CSV 直接测试 parser/汇总器:

  1. 密集 84.9%:窗口非空、全部 <85%、无 10 秒高段,PASS。
  2. 密集 85.0%:所有相关 5 秒窗口以严格 <85% 门禁 FAIL。
  3. 连续高 CPU 恰好 10.000 s:高段门禁 FAIL;9.999 s 反例不因该项失败。
  4. 稀疏 0.8—1.5 s:即使单行看似正常,只要任一完整尾窗成员少于 10 或覆盖不足,sampling_valid=false
  5. 扫描不足 5 秒或没有合格窗口:window_count=0sampling_valid=false,证明不能空通过。
  6. warm-up 行不进入窗口;首/末覆盖、时间戳倒退和 >1.5 s 缺口分别触发无效。

真实短片验收的 summary 还必须固定扫描开始/结束、有效样本数、最大间隔、窗口数/最差成员、高 CPU 最长段起止/时长、整机 CPU 两项门禁,并同时保留 V001 规定的任务树 CPU/RAM、GPU/decoder/显存和命令/日志证据。

5. 实现与审核门禁

  1. V002 限定方案复审只检查本文件第 2—4 节及第 1 节不回退合同;PASS 前产品代码、产品测试和真实媒体继续冻结。
  2. PASS 后仅按 V001+V002 实现;先运行 F1 桩、F2 H.264/H.265 合成媒体、F3 合成 CSV,再运行两个目标测试和 project 全回归。合成媒体只在测试临时目录生成和清理。
  3. 实现审核材料必须包含代码/测试/用法/采样器 bytes 与 SHA-256、完整测试结果、两种 codec 的四组 decoder argv 与等价摘要、F1 调用序列、F3 反例汇总、产品边界未回退证明,以及真实业务媒体动作仍为 0。
  4. 只有独立实现审核 PASS 后,才执行 V001 第 7.1 节的一次 <=600 s 片段和一次 PPT 运行。采样无效、CPU 门禁失败、NVDEC 主证据缺失或业务回归失败时只报告单一具体阻断,不重试、不调参、不改跑长视频。
  5. 最终向 case_analysis.media_processor 回传代码变更、测试、互斥/优先级/回退行为、CPU/GPU/decoder 采样、独立审核结论和源保护;不扩展产品范围。

6. V001 阻断逐项映射

前序 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 秒、稀疏、零窗口合成反例