Files
universal-video-transcode/STATE.md
T
hoelee 4385724c5e gate: a re-do of an already-playable file gets a 0.975 mean bar (owner decision)
One pass measured 11 attempts rejected purely on the window mean (0.9655-0.9795)
while accepted encodes had worse frame minima (0.33-0.90): the bar was splitting a
continuum, not separating defects. 0718 马斯克原理 failed with min 0.887 and 0.00% of
frames below 0.85. Those files already play (HEVC hvc1 + AAC) and a re-do exists only
to reclaim an old setting's bloat; reaching a 0.98 mean costs more than the source's
own bitrate, which the size ceiling forbids - so the strict bar stranded them with
their bloat while burning an encode every pass.

SSIM_MEAN_MIN_REDO = 0.975 now applies only when the run is re-doing a file that is
genuinely playable (HEVC hvc1 AND aac) from the snapshot original. The frame-share
test (>1% of frames below 0.85) is unchanged and is what catches a real defect.

Verified on ONE file before the tiers were restarted: 0321 随他们去 (rejected last
pass at mean 0.9789) -> ok, mean 0.9786, min 0.5092 with 5 of 1500 frames below 0.85
(fades), 633 MB -> 418 MB installed, live byte count == the encoded output.
2026-10-08 20:07:26 +08:00

121 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# STATE — 樊登读书会媒体库转码(2026-10-08 10:50 更新)
给下一个会话的交接。**权威运行器:`scripts/library_run.py`**(不要再恢复旧的 `hevc_lib.py`)。
## 现在在跑什么
两个 HEVC 档在跑,各自独立的锁(`run-x265.lock` / `run-nvenc.lock`;x265 = E 核,nvenc = GPU ASIC,互不争抢)。
**它们不在 Hermes 的进程管理里** → `process_manage` 看不到,也没有退出通知:只能看日志、按 PID 杀。
```bash
# 断点续跑(幂等:已转好的自动跳过,失败项文件未动,下一轮自动重做),每档最多重试 8 次
bash /d/tmp/xcode/relaunch_tiers.sh
# 看进度
tail -f /d/tmp/xcode/run_x265.log /d/tmp/xcode/run_nvenc.log
```
### 为什么改成"脱管"启动 —— 10:37 那次全停的教训(第 9 个 bug)
上一轮的 x265 / nvenc 是 Hermes 后台进程。**用户停会话时它们被一起杀了**:两个都停在编码到一半
(stage 里 `*_out.mp4` 和 `.err` 停在 10:37,日志里没有 `PASS-DONE`),所以 `persist_on_release` 在这个
环境里**不可靠**。现在两档由 `powershell Start-Process` 拉起的独立 bash 启动,父进程立刻退出 →
进程树成为孤儿,**Hermes 的清理碰不到它们**。
代价与规矩:没有退出通知(看日志);**停/杀只能按 PID**,绝不用进程名批量杀。
## 进度(2026-10-08 10:50,库内共 589 个文件)
| 档 | 已转好 | 待转 |
|---|---|---|
| copy | 160 | 4(见下) |
| x265 | 13 | 169 |
| nvenc | 25 | 174 |
| 无需处理(已达播发标准) | 44 | — |
| **合计** | **242** | **347** |
- 预期:x265 ~3.5 天、nvenc ~3 天跑完各自那档(这一轮 10:43 才重新起来,10:37 被上面那次全停打断)。
- 台账:`C:\AI\transcode-run\ledger.jsonl`(每项一行:分类/结果/大小/SSIM)。
- 进度只认台账与 state,**不看 `.mp4` 扩展名**(TubeSync 重命名会把它改回 `.mkv`)。
## 2026-10-08 新增的 4 集"每周更新"(copy 档)
`1004 反内卷` `0912 感官觉醒` `0905 如何成为情绪稳定的父母` `0822 超赞的一代`(都在 `樊登读书2026年(更新中)`):
H.264 + **mp3** 音轨,其中 `0822 超赞的一代` 其实是 **MPEG-TS** 只是挂着 .mp4 名 → iPad 播不了,
需要 copy 档(视频逐位不变 + 音轨转 AAC)。
⚠ **不要跑整轮 `--tier copy`**:copy 档唯一的跳过判据是"已经是 HEVC",而 copy 的产物是 H.264 ——
整轮会把 193 个已转好的 copy 文件全部重做一遍。改用单文件通道:
```bash
bash /d/tmp/xcode/convert_new4.sh # 逐个 --tier copy --path <file> --keep-source,共用 run-copy.lock
```
- `1004 反内卷` 10:48:53 完成 ✓(535 MB → 535 MB,视频 100% 逐位不变,音频转 AAC,149 s,rc=0)
## 图片闸门:re-do 用 0.975(业主决定 2026-10-08)
第一轮实测:一趟里 11 次编码**只差在 mean**(0.9655–0.9795)就被拒,而被接受的那些帧最低分反而更差
(0.33–0.90)—— 阈值在切一条连续的分布,不是在分开缺陷(`0718 马斯克原理`:min 0.887、**0.00%** 帧
<0.85,照样被拒)。被拒的文件本来就已能播(HEVC hvc1 + AAC),re-do 的唯一目的是清掉旧设定的膨胀;
而要够到 mean 0.98 得花掉超过源片自身的码率,会被 size ceiling 拦住 —— 结果是文件连同膨胀被永久搁置,
而且每一趟还白烧一次编码。
新规则(`library_run.SSIM_MEAN_MIN_REDO = 0.975`):**只有**"重做一个已经在播的文件"才用 0.975,条件为
live = HEVC hvc1 **且**音轨是 AAC(真能播)**且**本次是从快照原档重做;首次转换仍用 0.98。
帧占比判据(>1% 帧 <0.85)两档都不变 —— 它才是抓真缺陷的那条:`失控`(0.9655)仍会被拒,
`0808 陌生人效应`(0.9739)因为 live 是 H.264、根本不是 re-do,也仍走 0.98。
先在一个文件上验证(`0321 随他们去`,上一轮 mean 0.9789 被拒)→ 见 `/d/tmp/xcode/run_pilot.log`。
## 目录与日志
| 用途 | 路径 |
|---|---|
| 运行日志 | `/d/tmp/xcode/run_x265.log`、`run_nvenc.log`、`run_copy.log`、`run_new4.log` |
| 脱管启动器 / 新集转换 | `/d/tmp/xcode/relaunch_tiers.sh`、`convert_new4.sh`(+ `relauncher.out`);**源在仓库 `run/`**(改仓库那份再拷出来) |
| 单文件日志 | `/d/tmp/xcode/run_single.log` |
| 暂存目录(编码/闸门 raw) | `C:\AI\transcode-run\stage`(C: 盘,要留 ≥8 GB) |
| 台账(每项一行 JSON) | `C:\AI\transcode-run\ledger.jsonl` |
| 锁(每档一个 + 心跳) | `C:\AI\transcode-run\run-<tier>.lock` |
## 本轮修掉的 bug(按时间顺序,全部已提交推送)
1. **闸门判据太粗糙** → 改"缺陷形状"判:`mean < 0.98` 或 `>1% 帧 <0.85` 才判错,并**剔除近平坦帧**(SSIM 在黑场/淡入淡出上无意义;实测:好编码 0/1500、误判文件 0.33%、真缺陷 2.9%)。
2. **闸门用输入 seek 解码** → 改**两侧顺序解码**(open GOP 源从中间 seek 会解出错误画面:同一文件与自身比对 min 0.25)。
3. **闸门 raw 文件固定名** → 三个档并行时互踩(实测报出"100% 帧不符"的假缺陷)→ 改 **PID + tag** 命名。
4. **安装只用 ffprobe 元数据复核** → RaiDrive 返回**缓存属性**,rename 没落地也说成功(实测"ok 1085→478 MB"而线上仍是原档)→ 改**安装后回读哈希**。
5. **源拷贝只校验字节数** → 加 **SHA-256 比对共享盘副本**(长度对内容错是真风险)。
6. **probe 单次失败即判文件失败** → 加**重试 3 次**。
7. **看门狗用 stderr 管道**(本轮最贵的 bug)→ ffmpeg `-stats` 每 0.5 s 一行,64 KB 管道几分钟塞满 → ffmpeg 阻塞在 write() → 输出不增长 → 看门狗**误杀好编码**(整夜 ~270 杀、只转成 24 个、GPU 0%)。修:**stderr 写文件**,阈值 5→15 分钟。自检脚本 `D:\dev\hoelee-tubesync-management\cache\watchdog_selfcheck.py`。
8. 看门狗**保留**(它要防的是真实场景:用户更新 NVIDIA 驱动会把在跑的 NVENC 冻死 1.5 小时且不报错)。
9. **Hermes 后台进程会随会话一起被杀** —— 两个档在 10:37 同时死在编码中,日志里没有 `PASS-DONE`;改脱管启动(见上)。
## 未完成 / 待办
- [ ] 两档跑完 → **全库落地审计**:`D:\dev\hoelee-tubesync-management\cache\install_audit.py`(核对线上文件真实大小 + 编码器;曾一次抓到"报告成功没落地")+ `copy_land_check.py`(copy 档用音轨 aac/mp3 判定)。
- [ ] 失败项:无需清单,新一轮自动重做(失败时文件原样)。
- [ ] `2022年/0723 《走出强迫症》/走出强迫症.mp4` 用新下载(`D:\Download\0723走出强迫症.mp4`,618,696,954 B)已转好装好(450,502,893 B,HEVC+AAC,SSIM min 0.997,时长 3399.81 s)✓。**快照里那份仍是坏的**(618,697,011 B,moov 缺失)→ 待定:是否用干净副本替换快照里的坏档,以免将来"从原档重转"踩坑。
- [ ] 目标文件夹里曾出现一个 0 字节的 `0723走出强迫症.mp4`(现已不在)—— 若是用户自建请告知命名约定。
- [ ] 全库唯一真损坏:`走出强迫症.mp4` 的原档(上面已处理);其余 573 个可读文件截断审计 0 可疑。
## 用法速查
```bash
# 单文件(任意位置)转好并装回库,走同一套分档/闸门/回读
python scripts/library_run.py --path "D:/Download/x.mp4" --dest "Z:/.../x.mp4" --keep-source
# 只审计不落地(本地编码+闸门,输出丢弃)
python scripts/library_run.py --tier x265 --limit 3 --keep-local
# 分档预览
python scripts/library_run.py --dry-run --limit 20
```
## 红线(用户明确要求过)
- **绝不删除/覆盖快照原档**(`#snapshot` 是唯一的干净档案)。
- 失败时**不动 live 文件**;只有"结构 + 全解码 + 图片闸门 + 上传回读 + 安装回读"全过才替换。
- 杀进程**只按 PID**(绝不用进程名批量杀,`taskkill /IM ffmpeg.exe` 会连带杀掉别人的编码);一档一个锁;同一档不要跑两个实例。
- 动 GPU(更新驱动/跑 ComfyUI/加载大模型)前先暂停 nvenc 档。