chore: tidy project layout
This commit is contained in:
@@ -0,0 +1,699 @@
|
||||
# TG Video Damage Detector Implementation Plan
|
||||
|
||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||
|
||||
**Goal:** 构建一个专门面向 Telegram 导出场景的批量视频损坏检测工具,重点识别“点击跳过后文件未完整下载”的半截视频,并在机械硬盘上尽量减少无效寻道和全量深度解码带来的吞吐损失。
|
||||
|
||||
**Architecture:** 采用独立的 Python CLI 工具,使用 `uv` 管理环境,通过 `ffprobe` 做第一轮容器级快速校验,通过 `ffmpeg` 做第二轮定向深度验证。执行模型采用“分阶段、低并发、可恢复”的流水线:目录枚举与阶段一尽量顺序化,阶段二只处理阶段一失败或可疑的子集,并将所有中间状态持久化到 SQLite 以支持断点续跑和大规模批处理。
|
||||
|
||||
**Tech Stack:** Python 3.12+, `uv`, `ffprobe`, `ffmpeg`, `sqlite3`, `typer`, `orjson`, `pytest`, `pytest-xdist`(仅测试时可选)
|
||||
|
||||
---
|
||||
|
||||
## 1. 问题背景与核心判断
|
||||
|
||||
目标场景不是通用“坏视频”检测,而是高度特化的 TG 导出异常场景:
|
||||
|
||||
- 用户在 Telegram 导出期间点击“跳过”。
|
||||
- 目标目录中留下了扩展名正确、文件名正常、但内容不完整的视频文件。
|
||||
- 损坏主因通常是文件截断,而不是编码器随机写坏数据。
|
||||
- 数据位于机械硬盘,文件量较大,若对所有文件做完整解码,I/O 寻道与进程启动开销会迅速失控。
|
||||
|
||||
因此本项目的优化目标必须明确:
|
||||
|
||||
- 优先提升“单位时间筛出坏文件的数量”,而不是追求通用媒体法医级完整性验证。
|
||||
- 优先减少不必要的全量 `ffmpeg` 深度扫描。
|
||||
- 优先保证长时间批处理过程可恢复、可中断、可复跑,而不是一次性跑完后丢失上下文。
|
||||
|
||||
## 2. 方案比较与推荐
|
||||
|
||||
### 方案 A: 全量 `ffmpeg` 深度验证
|
||||
|
||||
思路:
|
||||
|
||||
- 对所有视频直接执行类似 `ffmpeg -v error -xerror -i <file> -f null -` 的验证。
|
||||
|
||||
优点:
|
||||
|
||||
- 结果直观。
|
||||
- 发现中后段流损坏的能力最强。
|
||||
|
||||
缺点:
|
||||
|
||||
- 对机械硬盘最不友好。
|
||||
- 对大量正常视频的成本极高。
|
||||
- 进程启动和全量读取会成为主要瓶颈。
|
||||
|
||||
结论:
|
||||
|
||||
- 不作为默认方案。
|
||||
|
||||
### 方案 B: 两轮检测,第一轮 `ffprobe`,第二轮定向 `ffmpeg`
|
||||
|
||||
思路:
|
||||
|
||||
- 第一轮对所有视频做容器级快速校验。
|
||||
- 第二轮只处理第一轮失败或被标记为可疑的文件。
|
||||
- 第二轮不默认全量解码,而是优先做“定向采样验证”,必要时再升级为完整验证。
|
||||
|
||||
优点:
|
||||
|
||||
- 与实际损坏模式匹配。
|
||||
- 能以较低成本抓住大量截断文件。
|
||||
- 适合机械硬盘和大批量数据。
|
||||
|
||||
缺点:
|
||||
|
||||
- 需要认真设计“可疑”判定规则。
|
||||
- 结果分类比单轮方案复杂。
|
||||
|
||||
结论:
|
||||
|
||||
- **推荐方案,也是本计划采用的方案。**
|
||||
|
||||
|
||||
|
||||
## 3. 范围与非目标
|
||||
|
||||
### 范围
|
||||
|
||||
- 选择一个或多个目录作为输入。
|
||||
- 递归扫描常见视频扩展名。
|
||||
- 第一轮对所有候选视频执行容器级快速校验。
|
||||
- 第二轮只对剩余可疑文件做更重验证。
|
||||
- 针对机械硬盘提供保守并发与顺序调度策略。
|
||||
- 面向大量文件提供断点续跑、结果落盘、批量输出。
|
||||
|
||||
### 非目标
|
||||
|
||||
- 不做 GUI,首版只做 CLI。
|
||||
- 不尝试修复视频。
|
||||
- 不尝试恢复 Telegram 元数据。
|
||||
- 不做跨机器分布式扫描。
|
||||
- 不做全媒体库去重、转码、预览图生成。
|
||||
|
||||
## 4. 推荐系统架构
|
||||
|
||||
首版采用单机、单进程协调、多子进程调用 `ffprobe`/`ffmpeg` 的结构。
|
||||
|
||||
组件划分:
|
||||
|
||||
1. `cli`
|
||||
- 解析参数。
|
||||
- 加载 profile。
|
||||
- 启动阶段流程。
|
||||
|
||||
2. `discovery`
|
||||
- 递归枚举目录。
|
||||
- 过滤扩展名。
|
||||
- 产出基础元数据:路径、大小、修改时间、扩展名。
|
||||
|
||||
3. `store`
|
||||
- 将扫描记录持久化到 SQLite。
|
||||
- 记录阶段状态,支持恢复。
|
||||
- 记录错误原因、命令返回码、耗时。
|
||||
|
||||
4. `stage1_probe`
|
||||
- 调用 `ffprobe`。
|
||||
- 生成容器级结果和可疑标记。
|
||||
|
||||
5. `stage2_verify`
|
||||
- 调用 `ffmpeg` 做更重验证。
|
||||
- 优先执行定向采样验证,而非对所有可疑文件完整解码。
|
||||
|
||||
6. `scheduler`
|
||||
- 负责 HDD 友好的阶段切换与低并发调度。
|
||||
- 控制 worker 数、队列长度、重试与中断。
|
||||
|
||||
7. `reporting`
|
||||
- 输出 SQLite、JSONL、CSV 摘要。
|
||||
- 提供按状态和原因分类的报告。
|
||||
|
||||
## 5. 数据模型与状态机
|
||||
|
||||
建议使用 SQLite 单文件数据库,例如 `scan_state.db`。
|
||||
|
||||
核心表:
|
||||
|
||||
- `scan_runs`
|
||||
- `id`
|
||||
- `created_at`
|
||||
- `profile`
|
||||
- `root_paths_json`
|
||||
- `status`
|
||||
|
||||
- `files`
|
||||
- `id`
|
||||
- `run_id`
|
||||
- `path`
|
||||
- `size`
|
||||
- `mtime_ns`
|
||||
- `extension`
|
||||
- `discovery_order`
|
||||
- `stage1_status`
|
||||
- `stage2_status`
|
||||
- `final_status`
|
||||
|
||||
- `stage1_results`
|
||||
- `file_id`
|
||||
- `exit_code`
|
||||
- `stderr_text`
|
||||
- `format_name`
|
||||
- `duration`
|
||||
- `has_video_stream`
|
||||
- `warning_flags_json`
|
||||
- `elapsed_ms`
|
||||
|
||||
- `stage2_results`
|
||||
- `file_id`
|
||||
- `mode`
|
||||
- `sample_points_json`
|
||||
- `exit_code`
|
||||
- `stderr_text`
|
||||
- `reason_code`
|
||||
- `elapsed_ms`
|
||||
|
||||
最终状态建议统一为:
|
||||
|
||||
- `confirmed_broken`
|
||||
- `suspicious`
|
||||
- `passed_stage1`
|
||||
- `passed_stage2`
|
||||
- `skipped`
|
||||
- `command_error`
|
||||
|
||||
状态流转建议:
|
||||
|
||||
- 发现文件后进入 `pending_stage1`
|
||||
- 第一轮失败直接进入 `confirmed_broken`
|
||||
- 第一轮通过但命中可疑规则,进入 `pending_stage2`
|
||||
- 第二轮通过进入 `passed_stage2`
|
||||
- 第二轮失败进入 `confirmed_broken`
|
||||
- 第二轮无法判定则保留 `suspicious`
|
||||
|
||||
## 6. 第一轮: 容器级快速校验设计
|
||||
|
||||
### 目标
|
||||
|
||||
- 用尽量低的 I/O 成本筛掉绝大多数明显坏文件。
|
||||
- 尽量不做深度解码。
|
||||
|
||||
### 推荐命令
|
||||
|
||||
建议首版基于如下 `ffprobe` 级别的信息:
|
||||
|
||||
```bash
|
||||
ffprobe -v error -show_entries format=format_name,duration,size:stream=index,codec_type,codec_name,width,height -of json <file>
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- `-v error` 只保留错误输出。
|
||||
- `show_entries` 只拿最小必要字段,避免无意义输出。
|
||||
- 不启用 `-count_frames`、`-show_packets` 这类重操作。
|
||||
|
||||
### 第一轮判定规则
|
||||
|
||||
直接判定 `confirmed_broken`:
|
||||
|
||||
- `ffprobe` 非零退出。
|
||||
- 无法识别容器格式。
|
||||
- 没有视频流。
|
||||
- 错误信息命中高置信度关键词,例如:
|
||||
- `moov atom not found`
|
||||
- `error reading header`
|
||||
- `EBML header parsing failed`
|
||||
- `Invalid data found when processing input`
|
||||
|
||||
判定 `pending_stage2`:
|
||||
|
||||
- `ffprobe` 成功,但 `stderr` 非空且命中软告警关键词。
|
||||
- `duration` 缺失、为 `N/A`、非数字或 `<= 0`。
|
||||
- 容器属于 TG 场景高风险集合,且启用了 `tg-hdd` profile。
|
||||
|
||||
建议首版高风险集合:
|
||||
|
||||
- `mp4`
|
||||
- `mov`
|
||||
- `m4v`
|
||||
- `mkv`
|
||||
- `webm`
|
||||
|
||||
判定 `passed_stage1`:
|
||||
|
||||
- `ffprobe` 成功。
|
||||
- 存在视频流。
|
||||
- 关键字段齐全。
|
||||
- 未命中可疑规则。
|
||||
|
||||
### 为什么第一轮只做容器级校验
|
||||
|
||||
因为你的场景里,大量半截文件会在这一层就暴露:
|
||||
|
||||
- MP4/MOV 缺尾时常直接在 `moov`/header 层失败。
|
||||
- MKV/WebM 容器不完整时常直接在 EBML 层失败。
|
||||
|
||||
这一步的价值是先把“最便宜能抓到的大头”清掉。
|
||||
|
||||
## 7. 第二轮: 更重验证设计
|
||||
|
||||
### 目标
|
||||
|
||||
- 不对所有文件做完整解码。
|
||||
- 只对第一轮失败边界附近的文件做更重验证。
|
||||
- 重点针对“头部还能读,但内容后段已截断”的视频。
|
||||
|
||||
### 推荐验证策略
|
||||
|
||||
第二轮默认不做全量解码,采用“定向采样 + 必要时升级”的两级策略。
|
||||
|
||||
#### 模式 1: 定向采样验证
|
||||
|
||||
推荐用 `ffmpeg` 在少数时间点解码短窗口,例如:
|
||||
|
||||
- 片头附近
|
||||
- 中段
|
||||
- 尾段附近
|
||||
|
||||
示例思路:
|
||||
|
||||
```bash
|
||||
ffmpeg -v error -xerror -ss <offset> -i <file> -t 3 -map 0:v:0 -f null -
|
||||
```
|
||||
|
||||
采样点建议:
|
||||
|
||||
- 时长 <= 60s: `10%`, `85%`
|
||||
- 60s < 时长 <= 10min: `10%`, `50%`, `90%`
|
||||
- 时长 > 10min: `10%`, `60%`, `92%`
|
||||
|
||||
尾段点位最关键,因为 TG 半截文件最常见的问题就是尾部缺失。
|
||||
|
||||
#### 模式 2: 完整解码确认
|
||||
|
||||
只对以下文件升级:
|
||||
|
||||
- 定向采样失败但错误原因不够稳定。
|
||||
- 用户手动指定 `--full-decode-confirm`。
|
||||
- 需要给出更高置信度结论的少量边界样本。
|
||||
|
||||
示例命令:
|
||||
|
||||
```bash
|
||||
ffmpeg -v error -xerror -i <file> -f null -
|
||||
```
|
||||
|
||||
### 第二轮判定规则
|
||||
|
||||
直接判定 `confirmed_broken`:
|
||||
|
||||
- 任一采样窗口退出非零。
|
||||
- 错误信息命中以下关键词:
|
||||
- `Truncating packet`
|
||||
- `Invalid NAL unit size`
|
||||
- `decode_slice_header error`
|
||||
- `corrupt input packet in stream`
|
||||
|
||||
保留为 `suspicious`:
|
||||
|
||||
- 第二轮命令执行异常,但不是明确媒体损坏。
|
||||
- 不同采样窗口结果相互矛盾。
|
||||
|
||||
判定 `passed_stage2`:
|
||||
|
||||
- 所有采样窗口通过。
|
||||
|
||||
## 8. 机械硬盘优化策略
|
||||
|
||||
这是本项目最重要的工程约束之一,不能事后再补。
|
||||
|
||||
### 调度原则
|
||||
|
||||
- 不让第一轮和第二轮并发运行。
|
||||
- 默认采用阶段式执行:
|
||||
- 目录发现 + 第一轮
|
||||
- 第一轮结束后再跑第二轮
|
||||
|
||||
原因:
|
||||
|
||||
- 在同一块 HDD 上同时跑 `ffprobe` 和 `ffmpeg`,会把顺序读打碎成大量随机寻道。
|
||||
|
||||
### 默认并发策略
|
||||
|
||||
建议提供 `--storage-profile`:
|
||||
|
||||
- `hdd`
|
||||
- `ssd`
|
||||
- `auto`
|
||||
|
||||
首版默认建议:
|
||||
|
||||
- `hdd`: `stage1_workers=1`, `stage2_workers=1`
|
||||
- `ssd`: `stage1_workers=4`, `stage2_workers=2`
|
||||
- `auto`: Windows 下默认保守映射到 `hdd`
|
||||
|
||||
理由:
|
||||
|
||||
- HDD 上盲目开线程,经常只会让总吞吐下降。
|
||||
- 多线程对 CPU 友好,不代表对磁盘友好。
|
||||
|
||||
### 队列与背压
|
||||
|
||||
- 使用有界队列。
|
||||
- 不允许一次性把几十万条待处理任务全部压进内存。
|
||||
- 队列深度建议默认不超过 `64`。
|
||||
|
||||
### 文件顺序
|
||||
|
||||
- 发现顺序和处理顺序尽量保持一致。
|
||||
- 默认按目录遍历顺序写入 `discovery_order`。
|
||||
- 阶段一按 `discovery_order` 处理。
|
||||
- 阶段二按可疑文件的 `discovery_order` 再处理。
|
||||
|
||||
### 数据落盘
|
||||
|
||||
- SQLite 写入采用批量提交,例如每 `100` 或 `500` 条一次事务提交。
|
||||
- 结果边写边落盘,不等全流程结束。
|
||||
|
||||
## 9. 大量视频处理优化
|
||||
|
||||
### 必做优化
|
||||
|
||||
1. **断点续跑**
|
||||
- 再次运行时,若 `path + size + mtime` 未变化,直接复用上一轮结果。
|
||||
|
||||
2. **结果流式写入**
|
||||
- 不把全部结果留在内存。
|
||||
- 允许处理百万级文件清单。
|
||||
|
||||
3. **分阶段输出**
|
||||
- 第一轮结束后立即产出“明确损坏 + 待二轮复核”列表。
|
||||
|
||||
4. **最小日志**
|
||||
- 默认只输出阶段进度与统计摘要。
|
||||
- 不为每个文件打印一行日志。
|
||||
|
||||
5. **可中断**
|
||||
- 捕获 `Ctrl+C`,将状态安全落盘。
|
||||
|
||||
### 建议优化
|
||||
|
||||
1. **扩展名白名单**
|
||||
- 首版只扫常见视频扩展名。
|
||||
- 减少误把非视频文件交给 `ffprobe`。
|
||||
|
||||
2. **目录级切分**
|
||||
- 对超大目录,允许后续增加“按一级目录分批执行”的操作模式。
|
||||
|
||||
3. **结果摘要缓存**
|
||||
- 对重复查看的报告生成固定 JSONL/CSV,不每次重新聚合。
|
||||
|
||||
## 10. CLI 设计
|
||||
|
||||
建议提供如下命令:
|
||||
|
||||
```bash
|
||||
uv run tgvideo-check scan D:\Exports\ChatA D:\Exports\ChatB
|
||||
```
|
||||
|
||||
首版参数建议:
|
||||
|
||||
- `--profile tg-hdd`
|
||||
- `--recursive / --no-recursive`
|
||||
- `--extensions mp4,mov,mkv,webm,avi`
|
||||
- `--db .\scan_state.db`
|
||||
- `--resume`
|
||||
- `--stage1-workers 1`
|
||||
- `--stage2-workers 1`
|
||||
- `--sample-duration 3`
|
||||
- `--full-decode-confirm`
|
||||
- `--export-jsonl .\results.jsonl`
|
||||
- `--export-csv .\results.csv`
|
||||
|
||||
建议内置 profile:
|
||||
|
||||
- `tg-hdd`
|
||||
- 针对当前用户场景的默认推荐档。
|
||||
- 保守并发。
|
||||
- 高风险容器进入第二轮。
|
||||
|
||||
- `tg-fast`
|
||||
- 第一轮尽可能快。
|
||||
- 第二轮更严格地缩小范围。
|
||||
|
||||
- `deep-verify`
|
||||
- 面向人工复核的小样本。
|
||||
- 允许完整解码确认。
|
||||
|
||||
## 11. 项目结构建议
|
||||
|
||||
建议在 `plan-for-tgvideo` 下实现为独立 Python 工具:
|
||||
|
||||
```text
|
||||
plan-for-tgvideo/
|
||||
pyproject.toml
|
||||
uv.lock
|
||||
README.md
|
||||
src/
|
||||
tgvideo_check/
|
||||
__init__.py
|
||||
cli.py
|
||||
config.py
|
||||
discovery.py
|
||||
scheduler.py
|
||||
store.py
|
||||
models.py
|
||||
ffprobe_runner.py
|
||||
ffmpeg_runner.py
|
||||
classifiers.py
|
||||
reporting.py
|
||||
profiles.py
|
||||
tests/
|
||||
test_profiles.py
|
||||
test_stage1_classification.py
|
||||
test_stage2_classification.py
|
||||
test_resume_logic.py
|
||||
test_integration_truncated_mp4.py
|
||||
test_integration_truncated_mkv.py
|
||||
samples/
|
||||
valid/
|
||||
broken/
|
||||
```
|
||||
|
||||
## 12. 分任务实施计划
|
||||
|
||||
### Task 1: 初始化独立项目骨架
|
||||
|
||||
**Files:**
|
||||
- Create: `plan-for-tgvideo/pyproject.toml`
|
||||
- Create: `plan-for-tgvideo/README.md`
|
||||
- Create: `plan-for-tgvideo/src/tgvideo_check/__init__.py`
|
||||
- Create: `plan-for-tgvideo/src/tgvideo_check/cli.py`
|
||||
|
||||
**Steps:**
|
||||
1. 用 `uv init` 初始化项目。
|
||||
2. 设定 CLI 入口为 `tgvideo-check`。
|
||||
3. 增加最小依赖:`typer`、`orjson`。
|
||||
4. 跑 `uv run tgvideo-check --help`,确认骨架可执行。
|
||||
|
||||
### Task 2: 建立配置与 profile 系统
|
||||
|
||||
**Files:**
|
||||
- Create: `plan-for-tgvideo/src/tgvideo_check/config.py`
|
||||
- Create: `plan-for-tgvideo/src/tgvideo_check/profiles.py`
|
||||
- Test: `plan-for-tgvideo/tests/test_profiles.py`
|
||||
|
||||
**Steps:**
|
||||
1. 定义全局配置模型。
|
||||
2. 实现 `tg-hdd`、`tg-fast`、`deep-verify` 三个 profile。
|
||||
3. 明确 `hdd` 默认 worker 数与采样策略。
|
||||
4. 编写配置解析测试。
|
||||
|
||||
### Task 3: 实现目录发现与候选文件过滤
|
||||
|
||||
**Files:**
|
||||
- Create: `plan-for-tgvideo/src/tgvideo_check/discovery.py`
|
||||
- Create: `plan-for-tgvideo/src/tgvideo_check/models.py`
|
||||
- Test: `plan-for-tgvideo/tests/test_discovery.py`
|
||||
|
||||
**Steps:**
|
||||
1. 实现多目录递归枚举。
|
||||
2. 只保留目标扩展名。
|
||||
3. 记录 `path / size / mtime / extension / discovery_order`。
|
||||
4. 保证发现顺序稳定。
|
||||
|
||||
### Task 4: 实现 SQLite 状态存储与恢复
|
||||
|
||||
**Files:**
|
||||
- Create: `plan-for-tgvideo/src/tgvideo_check/store.py`
|
||||
- Test: `plan-for-tgvideo/tests/test_resume_logic.py`
|
||||
|
||||
**Steps:**
|
||||
1. 初始化数据库 schema。
|
||||
2. 支持批量 upsert 文件记录。
|
||||
3. 以 `path + size + mtime` 作为恢复依据。
|
||||
4. 确保中断后可恢复到上次阶段状态。
|
||||
|
||||
### Task 5: 实现第一轮 `ffprobe` 执行器
|
||||
|
||||
**Files:**
|
||||
- Create: `plan-for-tgvideo/src/tgvideo_check/ffprobe_runner.py`
|
||||
- Test: `plan-for-tgvideo/tests/test_stage1_runner.py`
|
||||
|
||||
**Steps:**
|
||||
1. 封装 `ffprobe` 命令构建。
|
||||
2. 限制输出字段。
|
||||
3. 捕获 `stdout`、`stderr`、退出码与耗时。
|
||||
4. 对超时和命令不存在给出明确错误状态。
|
||||
|
||||
### Task 6: 实现第一轮分类器
|
||||
|
||||
**Files:**
|
||||
- Create: `plan-for-tgvideo/src/tgvideo_check/classifiers.py`
|
||||
- Test: `plan-for-tgvideo/tests/test_stage1_classification.py`
|
||||
|
||||
**Steps:**
|
||||
1. 定义高置信度错误关键词。
|
||||
2. 定义软告警关键词和可疑规则。
|
||||
3. 加入 TG 高风险容器升级规则。
|
||||
4. 输出 `confirmed_broken / pending_stage2 / passed_stage1` 三种核心结果。
|
||||
|
||||
### Task 7: 实现第二轮 `ffmpeg` 定向验证
|
||||
|
||||
**Files:**
|
||||
- Create: `plan-for-tgvideo/src/tgvideo_check/ffmpeg_runner.py`
|
||||
- Test: `plan-for-tgvideo/tests/test_stage2_classification.py`
|
||||
|
||||
**Steps:**
|
||||
1. 根据时长生成采样点。
|
||||
2. 实现定向短窗口验证命令。
|
||||
3. 支持按需升级到完整解码确认。
|
||||
4. 归类典型流损坏错误。
|
||||
|
||||
### Task 8: 实现 HDD 友好的调度器
|
||||
|
||||
**Files:**
|
||||
- Create: `plan-for-tgvideo/src/tgvideo_check/scheduler.py`
|
||||
- Test: `plan-for-tgvideo/tests/test_scheduler_hdd.py`
|
||||
|
||||
**Steps:**
|
||||
1. 强制阶段一和阶段二不重叠运行。
|
||||
2. 用有界队列限制内存和并发。
|
||||
3. 默认 `hdd` profile 使用单 worker。
|
||||
4. 保证顺序处理和中断恢复。
|
||||
|
||||
### Task 9: 实现报告导出
|
||||
|
||||
**Files:**
|
||||
- Create: `plan-for-tgvideo/src/tgvideo_check/reporting.py`
|
||||
- Test: `plan-for-tgvideo/tests/test_reporting.py`
|
||||
|
||||
**Steps:**
|
||||
1. 输出 JSONL。
|
||||
2. 输出 CSV 摘要。
|
||||
3. 支持按原因统计。
|
||||
4. 支持导出“建议重新下载”清单。
|
||||
|
||||
### Task 10: 集成测试与样本验证
|
||||
|
||||
**Files:**
|
||||
- Create: `plan-for-tgvideo/tests/test_integration_truncated_mp4.py`
|
||||
- Create: `plan-for-tgvideo/tests/test_integration_truncated_mkv.py`
|
||||
- Create: `plan-for-tgvideo/tests/test_integration_resume.py`
|
||||
- Create: `plan-for-tgvideo/samples/README.md`
|
||||
|
||||
**Steps:**
|
||||
1. 准备有效视频样本。
|
||||
2. 人工截断生成坏样本。
|
||||
3. 验证第一轮能抓住明显容器损坏。
|
||||
4. 验证第二轮能抓住头部可读但中后段损坏的样本。
|
||||
|
||||
### Task 11: 性能基线与调优
|
||||
|
||||
**Files:**
|
||||
- Create: `plan-for-tgvideo/tests/test_perf_smoke.py`
|
||||
- Modify: `plan-for-tgvideo/README.md`
|
||||
|
||||
**Steps:**
|
||||
1. 在 HDD 场景下跑小规模基线测试。
|
||||
2. 比较 `stage1_workers=1` 与 `2` 的总耗时。
|
||||
3. 比较“定向采样”与“完整解码”的吞吐差异。
|
||||
4. 固化默认 profile 参数。
|
||||
|
||||
## 13. 测试策略
|
||||
|
||||
### 单元测试
|
||||
|
||||
- profile 解析
|
||||
- SQLite 恢复逻辑
|
||||
- 第一轮分类规则
|
||||
- 第二轮错误归类
|
||||
- 采样点计算
|
||||
|
||||
### 集成测试
|
||||
|
||||
- 正常 MP4
|
||||
- 截断 MP4
|
||||
- 正常 MKV
|
||||
- 截断 MKV
|
||||
- 命令缺失
|
||||
- 中断后恢复
|
||||
|
||||
### 手工验证
|
||||
|
||||
- 在真实 TG 导出目录上跑 `tg-hdd` profile
|
||||
- 抽样核对 `confirmed_broken`
|
||||
- 抽样核对 `passed_stage2`
|
||||
- 对边界文件再用播放器人工抽查
|
||||
|
||||
## 14. 风险与缓解
|
||||
|
||||
### 风险 1: 第二轮样本点过少,漏掉局部损坏
|
||||
|
||||
缓解:
|
||||
|
||||
- 保留 `--full-decode-confirm`。
|
||||
- 允许 profile 提高采样点数量。
|
||||
|
||||
### 风险 2: 对 HDD 开过多并发导致更慢
|
||||
|
||||
缓解:
|
||||
|
||||
- `tg-hdd` 默认单 worker。
|
||||
- 基线测试后再决定是否允许提高默认值。
|
||||
|
||||
### 风险 3: 结果解释不清,用户不知道哪些文件该重下
|
||||
|
||||
缓解:
|
||||
|
||||
- 报告中明确区分 `confirmed_broken` 和 `suspicious`。
|
||||
- 输出可读原因码与建议动作。
|
||||
|
||||
### 风险 4: 边界格式太多,首版支持面过宽
|
||||
|
||||
缓解:
|
||||
|
||||
- 首版只优先优化 `mp4/mov/m4v/mkv/webm/avi`。
|
||||
|
||||
## 15. 验收标准
|
||||
|
||||
满足以下条件即可认为首版达标:
|
||||
|
||||
- 能选择一个或多个目录运行。
|
||||
- 第一轮完成全量容器级快速校验。
|
||||
- 第二轮只处理第一轮失败或可疑文件。
|
||||
- 具备 `tg-hdd` profile,并默认采用 HDD 友好的保守并发。
|
||||
- 支持 SQLite 落盘与断点续跑。
|
||||
- 能输出明确的坏文件清单与原因分类。
|
||||
- 在真实机械硬盘数据集上,默认模式明显快于“对所有文件完整解码”的朴素方案。
|
||||
|
||||
## 16. 首版执行建议
|
||||
|
||||
建议严格按以下顺序推进:
|
||||
|
||||
1. 先把 SQLite 恢复和第一轮 `ffprobe` 跑通。
|
||||
2. 再实现分类器,确保“坏 / 可疑 / 通过”三分法稳定。
|
||||
3. 然后实现第二轮定向采样验证。
|
||||
4. 最后再做 HDD 调度细化和性能调优。
|
||||
|
||||
不要一开始就做“全量完整解码 + 高并发”,那是最容易把项目做成一个在真实机械硬盘上难用的慢工具的路线。
|
||||
Reference in New Issue
Block a user