P4 Theater

全量视频字幕与内容识别流水线

来源版本:2026-07-14 · 公开:2026-09-08 · 27,962 字符 · P4 剧场研究档案

下载完整公开版 Markdown段落与引用数据(JSON)引用本文回到影片资料
本篇目录 / Contents

全量视频字幕与内容识别流水线

[!summary] 一句话决策 “全量”不是给 6,154 个视频路径盲目生成 6,154 份 SRT,而是让每一个视频路径都有可审计的 resolved_outcome;在去重、可读性、音轨、语音与权利检查之后,让每一个独立、可读取、确有言语内容且获准进行本地 ASR 的资产得到一套可追溯的机器字幕包。

[!success] 当前已经进入执行态 READY-B 已与 READY-A 完成稳定性复核并封存为 READY_SEALED12TMAC02 目标根目录已经建立,《冰山》DJI_0016.MP4 的本地双引擎试点已成功,全量镜像也已启动。这里的“执行态”只表示批次封存和基础链路开始运行,不表示镜像已经完成,更不表示 6,154 个视频路径已经全部获得语音字幕

[!important] 批次级本地转写权限已落账 Owner指令已写入2026-07-13-ready-sealed-local-asr-authorization.json,仅对本批开放LOCAL_ASR_ALLOWED,同时锁定restricted / machine_unreviewed / public=no / cloud=false / source_write=false。它允许内部归档转写,不使公开、AI训练、声纹识别或项目确认获得默认授权。运行器必须校验该文件的批次、manifest SHA-256、许可字段和文件哈希;没有这道门时不得执行全量run --execute

上一卷:04-首批项目路由与三十天执行顺序-2026-07-13(馆内参考,未随本文公开)|返回P4素材盘项目式归档总入口(馆内参考,未随本文公开)|下一卷:暂无

一、封存后的权威分母:先把“有多少”说准确

2026-07-13 09:15 PDT 的 READY-B 与 08:45 的 READY-A,以 relative_path + bytes + mtime UTC 为比较键复核,结果为:

added   = 0
removed = 0
changed = 0
batch_status = READY_SEALED

因此,以下数字不再只是 READY 候选 A 的观察值,而是本批次封存清单的权威路径级分母:

指标 READY_SEALED 权威清单 相对旧基线 证据含义
文件路径 21,299 +116 尚未等同于独立数字资产
目录 529 目录结构计数,不进入资产分母
总字节数 4,419,913,652,206 B 约 +0.488 TB 十进制约 4.420 TB,以精确字节值为权威
视频路径 6,154 +114 依据扩展名识别,不代表均可解码、有音轨或有言语
新增 XML 2 +2 来自 子丑破月,应作为伴随元数据候选处理
新增 MP4 114 +114 来自 子丑破月,尚待哈希、探测、权利与项目关系确认

旧基线为 21,183 个文件、3.932 TB、6,040 个视频路径;本轮新增共 116 个文件,全部位于 子丑破月,由 114 个 MP4 与 2 个 XML 构成。这里必须保留三个边界:

  1. 本批次已经 READY_SEALED,但封存清单并不等于 21,299 个路径已经全部写入 Archive v2,也不等于镜像已经完成。
  2. 6,154 是视频路径数,不是独立视频资产数;只有 SHA-256 解析后才能知道 unique_video_assets
  3. 路径所暗示的项目归属仍是 candidate/probable,不能因为字幕内容“看起来像某个项目”就自动升级为确认关系。

因此,本工程同时维护两类分母:

二、什么叫“完成”:结果不是只有“转写成功”

全量工程的第一目标是闭合路径责任。每条视频路径最终必须落入一个明确、可复查的 resolved_outcome

resolved_outcome 含义 是否算路径已解决 是否进入 ASR 分母
transcribed 已生成并校验机器字幕包
existing_transcript_reused 已有合格字幕版本,完成关系复用
exact_duplicate_reused SHA-256 完全相同,复用同一资产与字幕
no_audio_stream 容器内无音频流
silence_only 有音轨但只有静音或近静音
non_speech_audio 只有音乐、环境声等非言语声音
rights_hold 权利判断不足,暂缓处理
sealed_no_asr 封存材料明确不允许自动转写
unsupported_codec 当前本地解码链不支持 是,但进修复队列
probe_failed 探测失败,需重试或人工诊断 是,但进修复队列
corrupt 文件损坏或有效数据不完整 是,但进隔离队列
withdrawn 权利人或档案责任人要求撤回

NO_AUDIONON_SPEECHEXACT_DUPLICATERIGHTS_HOLDUNSUPPORTED/CORRUPT 都是合法的完成状态,而不是“失败后留空”。尤其不能用空白 SRT 伪装无音轨材料已经完成。

三、状态机:一条视频路径怎样变成可追溯字幕

DISCOVERED
→ HASH_PENDING
→ ASSET_RESOLVED
  ├─ EXACT_DUPLICATE_REUSE
  └─ UNIQUE_ASSET
→ PROBE_PENDING
  ├─ PROBE_FAILED
  ├─ UNSUPPORTED_CODEC
  ├─ NO_AUDIO
  └─ AUDIO_PRESENT
→ SPEECH_TRIAGE
  ├─ SILENCE_ONLY
  ├─ NON_SPEECH_AUDIO
  └─ SPEECH_PRESENT
→ RIGHTS_PREFLIGHT
  ├─ RIGHTS_HOLD
  ├─ SEALED_LOCAL_ONLY
  └─ LOCAL_ASR_ALLOWED
→ AUDIO_EXTRACTED_TEMP
→ ASR_RUNNING
→ MACHINE_TRANSCRIPT_COMPLETE
→ TECHNICALLY_VALIDATED
→ HUMAN_REVIEW_QUEUE
  ├─ INTERNAL_MACHINE_ONLY
  ├─ TEXT_REVIEWED
  ├─ SPEAKER_REVIEWED
  └─ PUBLICATION_APPROVED
→ ARCHIVED
→ 可选:PUBLISHED / WITHDRAWN

不能把这条状态机压成一个“字幕状态”字段。至少要分别保存:

这样才能区分“技术上可做但尚无授权”“已有机器稿但未校对”“校对过但不可公开”等完全不同的事实。

四、九步流水线

1. 批次冻结与 READY 握手

本轮 READY 握手已经完成:READY-B 相对 READY-A 在 relative_path + bytes + mtime UTC 上为 0 added、0 removed、0 changed,批次状态为 READY_SEALED。批次运行期间不接受源目录继续变化;若创作者继续拷贝,新文件进入下一批,而不是悄悄混入正在运行的清单。每批保留只读 manifest、文件大小、mtime 与源路径;任何转写产物都不得写回 〔本地资料路径省略〕 源树。

2. 哈希与资产解析

为路径计算 SHA-256,先解析为 Archive v2 的 P4-A:

3. 全量 ffprobe 与音轨枚举

对每个独立、可支持的视频资产执行只读探测,记录容器、时长、视频编码、音频流数量、每一条音频流的 stream index、codec、sample rate、channel layout、语言标签、default 标记、时长与音频指纹。不得假设“第 0 条音轨就是应该转写的主混音”。

4. 本地语音初筛

在本地进行静音、非言语音频、语音段落和语言候选判断。初筛只决定队列,不确认人物身份、项目归属或公开价值。音乐、掌声、环境声可成为辅助标注,但不是默认 ASR 文本。

5. 权利预检

先检查授权状态、可见级别和敏感性,再抽音频。ai_transcription 是独立许可,不可由“可以保存”“可以内部观看”或“可以公开放映”自动推导,更不能与 ai_training、声音克隆、人物识别和生成式使用混为一谈。

6. 确定性音频提取

音频只提取到独立 scratch/derivative 盘:使用固定采样率、声道策略和工具版本,记录命令、源 SHA-256、音轨索引、时间基与处理配置。scratch 是可重建的工作区,不是永久保存副本;不得在空间不足时删除源盘文件换取容量。

7. 本地 ASR 与说话人分段

模型、推理、VAD、语言检测和可选 diarization 全部在本地完成,不上传云端或外部 API。ASR 的输入键必须包括源资产 SHA-256、音轨/声道、目标语言、模型与版本、配置和流水线版本,以便幂等复跑。

8. 产物校验与 Archive v2 导入

校验时间码递增、片段不越界、VTT/SRT 可解析、UTF-8、JSONL schema、产物 SHA-256 与 manifest 一致;随后进行幂等导入。所有失败都有显式错误码和重试次数,不能只留下日志中的一句报错。

9. 人工复核与发布分离

机器稿首先是内部工作资产。文本复核、说话人确认、权利复核、隐私处理、发布审批分别签名;公开发布必须经过既有 G5/H4 门槛。机器字幕完成不等于字幕真实、不等于人物已确认,更不等于获准公开。

五、Archive v2:源视频、转写文本与字幕文件不是同一个对象

正确的关系是:

源视频 digital_asset:P4-A-...
  ├─ transcript:P4-TX-...
  │    └─ transcript_segments:带时间码的文本片段
  └─ 字幕产物各自成为新的 digital_asset:P4-A-...
       ├─ manifest.json
       ├─ segments.jsonl
       ├─ words.jsonl(可选)
       ├─ transcript.txt
       ├─ captions.vtt
       ├─ captions.srt
       ├─ quality.json
       └─ review.tsv

实施规则:

  1. transcripts.asset_id 指向源视频资产,不是 VTT 或 SRT 文件。
  2. VTT、SRT、JSONL、TXT 是不同字节序列,分别拥有自己的 P4-A 与 SHA-256;它们不是源视频的多个 location。
  3. 字幕产物可通过同一 archive item 的 item_assetssubtitlefull_textattachment 等角色连接;更稳妥的未来增量迁移是增加 transcript_artifacts 连接表,明确 transcript_idartifact_asset_idartifact_roleversion。不另建第三套字幕数据库。
  4. 新转写使用 P4-TX-<16HEX> 一类数据库生成代码并保留既有 legacy code;不能从项目名、路径或日期拼稳定编号。
  5. 已入账版本不原位覆写。换模型、修正正文或人工校对均新增 version;同一源资产、语言、类型和版本保持唯一,并明确 primary。
  6. 转写所属项目通过源视频、archive item 与 item_projects 继承。源关系若是 candidate,字幕关系仍是 candidate;内容推断最多生成 machine candidate,不能自动确认。
  7. 每个 P4-TX 必须能落到一个项目关系,或显式进入 unmapped_hold,不得项目字段空白。
  8. 本机路径只进入受控 location/导入账,不序列化到 transcript 正文或公共数据库字段。

六、产物目录与文件格式

未经人工复核的机器稿先进入受限区;只有完成相应用途审核的版本才复制为工作或公开衍生件。项目包只保存 transcripts.csv 索引和关系,不复制全量字幕:

07_restricted/machine-transcripts/
  <P4-A-source>/
    <language>/
      <type>/
        <P4-TX>/
          manifest.json
          segments.jsonl
          words.jsonl
          transcript.txt
          captions.vtt
          captions.srt
          quality.json
          review.tsv

03_derivatives/publication-subtitles/
  <仅存已经通过相应用途审核的字幕版本>

所有文本采用 UTF-8 无 BOM、LF 换行;内部时间统一为整数毫秒;每个文件都写 SHA-256。各格式的责任不能混淆:

文件 责任
manifest.json 全局来源、权利、模型、配置、音轨、时间基、版本与哈希入口
segments.jsonl 无损的规范片段层,保存时间码、重叠、说话人候选、置信度与审核状态
words.jsonl 可选词级时间码,用于精细校准,不要求所有模型都生成
captions.vtt 首选显示与网页交换格式
captions.srt 面向剪辑软件和旧播放器的兼容衍生格式
transcript.txt 搜索和快速阅读,不作为时间码证据
quality.json 技术校验、低置信区间、时间漂移与错误统计
review.tsv 保留不可变机器候选列,另设人工修订、身份依据、审核者与时间列

manifest.json 至少记录:source_asset_code、源 SHA-256、transcript_code、语言、类型、版本、音轨索引、声道范围、源/代理关系、模型及版本、配置摘要、pipeline 版本、开始/结束时间、转写许可、可见级别、产物哈希和 resolved_outcome

segments.jsonl 至少记录:sequencestart_msend_msspeaker_labeltextlanguage_codeconfidencespeaker_attribution_sourcereview_status 与可选 metadata。语言使用 BCP 47:如 zh-Hanszh-Hantenundmul;源音轨语言与字幕文本语言分别保存,翻译必须另建 transcript_type: translation

置信度只保留模型原生含义:不同 provider 的数值不可直接横比,无数据时为 null;人工确认写入审核字段,不能把 confidence 粗暴改成 1。

七、说话人:先匿名分段,后证据确认

八、特殊格式与棘手材料的明确处置

BRAW

BRAW 单独成批,使用可验证的本地解码链,并完整保留 sidecar。若 ASR 实际来自代理文件,必须记录代理资产、原始 BRAW、timebase/offset 变换和至少三个锚点校验;不能把 BRAW 直接丢进通用 MP4 队列后假定时间码一致。

AVC 与 BDM

AVC、BDM 先探测再判断:它们可能是裸码流、设备元数据、无音轨文件或当前工具不支持的容器。no_audio_streamunsupported_codec 都是有效结果,不得靠改扩展名强行运行。

多音轨与多声道

完整枚举 stream index、codec、sample rate、channel layout、language、default、duration 和 fingerprint。默认只转写经确认的主混音,同时保存其他轨的机器检测信息。现有 transcript 唯一约束尚不足以安全表达“同一源资产、同一语言、同一类型但不同音轨”的并存版本;批量逐轨导入前应增补 audio_stream_indexchannel_scope 并调整唯一性。迁移完成前,每个源资产只导入一个经确认的主混音 transcript;其他逐轨结果仅作受控 artifact,不冒充主字幕。

重复、近重复与不同剪辑

无音轨、音乐、损坏

无音轨不生成 transcript row 或空 SRT。纯音乐/非言语音频写 non_speech_audio;如未来需要无障碍字幕,可人工审核后制作 [音乐][掌声] 等 captions 版本。损坏和探测失败进入隔离、重试与人工诊断队列,源文件保持原样。

九、权利、隐私与本地计算边界

新材料的保守默认值应为:

visibility: private
authorization_status: unknown
workflow_status: draft
ai_transcription_permission: pending
ai_training_permission: no

机器转写会把原本难以检索的声音变成可全文搜索的文本,因此字幕产物的权限不得低于源材料,原则上应与源相同或更严格。以下内容默认进入 sensitivesealed_local_onlyrights_hold:聊天室、监控画面、私人访谈、未成年人、身份证件、联系方式、健康和亲密信息,以及权利不明的第三方电影、音乐和歌词。

本流水线只授权本地转写:不上传云端,不调用外部识别服务,不进行人脸或声纹身份识别,不用于 AI 训练、声音克隆或生成式再利用。公开文本必须另做隐私、版权、署名和撤回机制审查;机器稿永远不能默认公开。

十、批次、幂等与算力排兵

批次操作标签采用:

p4-YYYYMMDD-transcript-<project-or-scope>-NN

按项目候选、权利等级、编码类型和语言分组,而不是把 6,154 个路径一次性投入同一个进程。建议:

幂等键应由下列字段计算:

source_sha256
+ audio_stream_index
+ channel_scope
+ target_language
+ model_provider/model_version
+ config_hash
+ pipeline_version

同一键重复运行只返回既有 job/产物,不重复创造字幕记录。最终不可变导入账可沿用已批准的 P4-DIALOGUE-* 批次账口径;日常 processing job 与最终归档账应区分。

十一、首轮试点:单件链路已经跑通,仍需完成分层试点

当前已有一项可核查的执行成果:《冰山》DJI_0016.MP4 已完成本地双引擎试点,最终资产 location 为 loc-ee88bbc8ebabdb0a518c。这证明“本地读取 → 双引擎识别 → 结果汇合 → location 落账”的最小链路可以运行;但一个成功样本不能代表 20 资产试点已经验收,也不能代表 BRAW、多音轨、重复、无音轨、敏感材料和既有字幕等分支已经覆盖。

随后已建立正式任务账p4-20260713-video-asr-01,并以p4_local_asr_pipeline.py 2026-07-13.2完成一个20路径技术canary。这20条按manifest顺序取样,不能冒充跨项目分层样本:单worker ffprobe在约30秒内完成,18条识别为单音轨可转写媒体,2条因moov atom not found进入PROBE_FAILED;在批次权限文件未应用前,18条全部保持RIGHTS_HOLD,证明权限门不会把“技术可转写”直接写成“已获准”。

Owner的本批LOCAL_ASR_ALLOWED决定经batch、snapshot、manifest SHA-256、源根、输出分级与文件哈希校验后,MLX正式队列又完成1条61.61秒素材:loc-212caca9544144ca1e5b,结果TRANSCRIBED。本次从源SHA-256、音频提取到冷启动推理的总耗时79.885秒,RTF 1.2966;5项规范字幕产物和done.json哈希一致,JSON/JSONL严格可解析,scratch清零,权限为0600,状态仍是restricted / machine_unreviewed / public=no。它与早期《冰山》试点合计构成2条真实ASR样本,但仍不足以外推全库准确率或总工期。当前canary任务账还保留17条READY_FOR_ASR与2条PROBE_FAILED,在全量镜像完成前不继续制造I/O竞争。

下一步仍须把首批扩展到 20 个独立资产,覆盖以下十种情况:

  1. 《冰山》当前目录中的 6 个视频样本,但必须先查询 Archive v2,避免重做既有字幕;
  2. 一个完全重复路径组;
  3. 一个视频编码不同、音频及时基相同的近重复组;
  4. 一个无音轨视频;
  5. 一个音乐或环境声为主的视频;
  6. 一个多人抢话和重叠明显的视频;
  7. 一个多音轨视频;
  8. 一个聊天室、监控或私密材料,只做封存/权利决策,不输出公开稿;
  9. 一个 BRAW 或其代理链样本;
  10. 一个已有 SRT/VTT 的视频,用于测试版本与来源关系。

从中抽取 60 至 90 分钟制作人工参考稿,用 CER、专名错误率、时间漂移、重叠语音、远场语音和处理成本比较本地模型。试点不发布。通过后按既有归档优先级推进:《冰山》→ 实像 →《致幻》→《影子对位法》,再进入《茧房》等后续项目;优先级可因权利状态调整,但必须留变更理由。

完整试点验收的最低条件:

十二、KPI:不拿“生成了多少 SRT”冒充完成度

分母

discovered_video_paths = 6154
unique_video_assets = 哈希后确定
audio_bearing_assets = probe 后确定
speech_bearing_assets = 本地语音初筛后确定
local_asr_allowed_assets = 权利预检后确定

覆盖率

质量

必须长期保持为零的指标

no_audio_streamsilence_onlynon_speech_audio、精确重复和权利暂缓都计入路径闭合率,但不进入 ASR 应完成分母。这样,“全量”才是一套对每条材料负责的档案制度,而不是一场以字幕数量为指标的算力表演。

十三、执行看板:四个硬门槛的当前完成度

硬门槛 当前状态 已验证事实 下一动作
封存可验证 manifest 已完成 READY-B 相对 READY-A 为 0 added、0 removed、0 changed;批次 READY_SEALED;权威清单为 21,299 文件、529 目录、4,419,913,652,206 B、6,154 视频路径 保持源盘只读;任何新增材料进入新批次
20路径技术canary 已完成 20条完成单worker probe:18条单音轨、2条moov atom not found;权限文件应用后1条正式MLX机器稿成功,产物严格解析与哈希通过,scratch为0 保留技术证据;不把顺序样本写成分层质量样本
20资产分层试点 执行中 现有2条真实ASR样本:《冰山》双引擎试点与正式队列1条MLX样本 镜像完成后补齐跨项目、重复、无音轨、非语音、多音轨、BRAW、敏感和既有字幕分支
多音轨 schema 部分完成 probe任务账已记录audio_stream_count/index并把多音轨阻断,不会盲选;Archive v2尚未导入 增加人工主音轨选择、channel_scope、多字幕关系与唯一性迁移
独立实体镜像 已恢复推进、未完成 既有10,245个final复核完成后,新复制阶段累计298件/256,734,203,383 B且零SHA冲突;09:16与09:31两次无进度后09:45安全封停。09:47只读诊断发现两个非本批全树宽扫造成明确I/O争用;只终止对应进程组并静置后,09:50完整重验恢复门并启动PID 30509/会话20260714T095042Z-2286a6abafee,已越过此前4.56 GB项并持续产生SHA一致事件 继续观察恢复吞吐;禁止同机箱额外媒体/全树扫描。仍须完成21,299件与terminal receipt,且不把宽扫写成唯一根因或硬件无故障证明

镜像未完成之前,不能宣称 12TMAC02 已经形成完整保护副本;单件 ASR 成功也不能把未处理路径标成 transcribed。当前规模化执行的正确顺序是:先让镜像和校验闭合,再按批次推进哈希、probe、语音判断、权利预检与本地 ASR,最终保证全部 6,154 个视频路径都有 resolved_outcome。其中无音轨、纯音乐、精确重复、权利暂缓、损坏或不支持的路径可以得到合法的非字幕结论;全路径闭合从来不等于每条路径都必须产生语音字幕。

当四个门槛全部闭合后,字幕工程才从已启动的执行链路升级为 P4 的长期档案基础设施:每一份机器文本知道自己从哪一段声音来、使用了什么模型、能被谁看到、属于哪个版本、与哪个项目有何种证据关系,并且在错误、争议与撤回发生时,可以沿着关系账精确纠正,而不伤害原件。

十四、自动接力器:镜像完成后先全量probe,不盲跑全量ASR

com.p4.archive.postmirrorprobe.ready01最初加载的v2026-07-14.2已经在2026-07-14约05:00 UTC由一次受控bootout/bootstrap替换;固定工具为p4_post_mirror_probe_runner.py 2026-07-14.4,SHA-256为58be4336b6766e676275fd1e1bdd11495793a66997740f6be8c855f7560b067f。现有plist传入--poll-seconds 300,部署effective config SHA-256为b22d3d8261191e1af1f8df9041d533d7509df27c182901affd515610c95cbda9。它在09:45 UTC故障保持时曾为避免误接力而unload;09:54Z镜像恢复稳定产生SHA一致事件后重新bootstrap为PID 34666,当前仍为waiting / wait_for_mirrorlast_error=null。只有镜像取得成功终态并同时满足以下条件才可接力:

  1. 最新镜像session以complete=true结束,launchd进程停止且镜像flock释放;
  2. 同一session的JSON/CSV receipt与21,299行、4,419,913,652,206 B和源—目标SHA全部一致;
  3. 两块卷UUID、manifest SHA、工具SHA、精确漂移许可与源树“probe前两遍+report后一遍”元数据门都未漂移;
  4. 目标盘仍保有1.5 TB以上可用空间。

过门后它依次生成final fixity五件套、把现有20条队列幂等扩展到6,154条、用4个worker做全量ffprobe、导出状态与CSV。运行器对ASR子命令的白名单只有init / probe / status / export-queue,代码和参数层均拒绝run--execute;因此它能自动把“这些文件究竟能不能读、有几条音轨”闭合,不会跳过重复复用、语音判断、20资产质量试点和人工抽审直接制造数千份低质量字幕。

对现有ASR脚本的二次审查确认:它已具备逐件恢复、单GPU工作、权限门和原子产物写入,但尚未实现精确SHA字幕复用、内嵌字幕复用和多音轨主轨选择;此外,断电恰好发生在稳定产物已写入而done.json未提交的窗口时,下次执行会以OUTPUT_CONFLICT停队。因此目前有意不挂载无人值守的全量run --execute:先用全量probe得到时长、音轨和异常分布,再生成确定性去重/例外计划,修复中断恢复窗口,完成20资产分层质量门后才分批运行。这不是缩小“全量”目标,而是避免把重复文件、空字幕、错音轨和不可恢复中断写成假的完成数。

为降低同一ACASIS外置机箱中源—目标双盘的Spotlight随机读竞争,12TMAC02索引仍为disabled,12TMAC01为enabled。09:45 UTC进入故障保持时,独立标签com.p4.archive.spotlightrestore.ready01曾先于post-mirror runner卸载;09:54Z已重新bootstrap为PID 34668,但只等待镜像成功终态,当前不会提前改变索引状态。这一临时状态不改写〔本地资料路径省略〕的任何文件,也不是硬盘健康判断。

2026-07-14另建立Codex心跳监督P4 素材归档监督(automation id p4-2),每15分钟复核launchd状态、卷UUID、progress/receipt/status/log与1.5 TB保留线。第一次持续无进度后曾在全部恢复门通过时使用既有--resume;第二次同型无进度复发后,09:45策略升级为incident hold。该hold仅在09:47发现并移除两个非本批宽扫、磁盘静置两分钟这一明确外部状态变化后解除,且09:50重新通过UUID、manifest、源边界、flock、partial归属与容量门。监督不得改写源盘、不得增加同机箱媒体扫描,也不得绕过去重、音轨、质量与中断恢复门盲跑bulk ASR。若再次异常停止,仍须fail-closed重新判断,不自动循环resume。

十五、19:12 UTC SHA-256冲突与安全暂停

2026-07-13 19:12:55 UTC,镜像脚本在3P/小视频/HF_2021_06_12_18_44_32.mp4的同名.p4mirror.partial发布前重读中发现源—目标SHA-256不一致。该件为742,315,576 B;脚本以safety_or_integrity_error和exit 2结束,未将partial原子改名为final,也未覆写既有final。当时session在冲突前报告481件/191,710,070,339 B新复制完成,全局append-only账中已有502件/196,799,232,165 B的copied事件。

因submitted launchd带keepalive,该job在19:12:57 UTC自动重启并从头重验已有final。监督器识别出校验冲突后于19:25 UTC移除com.p4.archive.mirror.ready01,防止在未诊断前循环截断partial和重读约200 GB既有镜像。被移除进程在内核U型I/O等待返回后已退出,mirror flock可非阻塞获取;两卷UUID、manifest SHA与1.5 TB保留线均再验通过。IORegistry报告源—目标物理盘的read/write error与retry计数均0;这只说明底层未报错,不能消解本次字节级不一致。

定向诊断对源文件和错误partial各做两遍哈希:源两遍均为95c5a7e8736a26358bf111853db9db7f2deaa0e5b2223f3b97288037969312d1,partial两遍均为46ad3300d244ef7b01403621e667be1ce1d96859aba9586dc28c102855ac66d5,两者fingerprint均稳定。字节比较将差异锁定在第73个1 MiB块,绝对偏移76,554,724至77,594,623,该块有1,035,486个不同字节;其余91 MiB块全部一致。随后执行一次受控诊断重拷贝,复制过程源哈希与目标连续两遍重读哈希均等于上述源哈希,表明错误可由安全重拷贝避免,但原因仍只能记为“一次局部传输/写入异常,底层未报错”而不是已确认硬件故障。

错误partial已从payload原子移到99_system/integrity-diagnostics/20260713T191255Z-HF_2021_06_12_18_44_32/mismatched-original.p4mirror.partial,诊断重拷贝、incident.jsondiagnostic-result.json同目录保存。镜像已改为KeepAlive=false的持久LaunchAgent,于19:41:01 UTC以session 20260713T194101Z-5dd835e4d1c4恢复,已开始重验既有final;若再发生任何integrity error,job会停留供诊断,不再自动循环。post-mirror probe和Spotlight恢复器也已重启为waiting;Spotlight恢复脚本同时加入了mdutil -s双卷结果复验,不再将“命令返回0但输出报错”记成completed。

19:41 UTC恢复会话完成了502件既有final的逐件SHA-256重验。21:13:07 UTC它重新复制原冲突文件,21:13:20 UTC以源—目标同为95c5a7e8736a26358bf111853db9db7f2deaa0e5b2223f3b97288037969312d1copied事件原子发布final,随后已继续越过该路径复制新文件。21:21 UTC全局进度为554件/226,907,299,817 B,本恢复会话在重验502件后新复制52件,run_stopping=0。因此可将“本次冲突的安全恢复”标记为已验证,但全批镜像和终态fixity仍未完成。

十六、02:52 UTC封存后增量与固定manifest恢复

2026-07-14 02:52:40 UTC,心跳监督发现〔本地资料路径省略〕根目录fingerprint从封存时的dev=16777254 / inode=135488 / mtime=ctime=1783957313变为mtime=ctime=1783997082。这构成源树封存边界漂移。监督器没有把“镜像仍能读”当成安全证明,而是立即向PID 5492发送SIGTERM;进程约2秒后退出,flock释放,既有final未被覆盖,正在复制的HF_2020_12_19_12_54_41.mp4只留下由既有copy_started事件证明归属的260,046,848 B partial。

为避免再次扫描整套媒体,只对根层、发生mtime变化的父目录与manifest做浅层集合比较。结果定位出两个封存后对象:

两者均不在21,299行权威manifest内;根层与王亚男 风车 TV/在对应浅层比较中均无manifest成员消失。根.DS_Store的mtime/ctime发生变化,但当前源文件、镜像中既有final与早先progress记录的SHA-256仍同为de593351c97a4ac9ee7404bc82e5ac338419974f7d7b82787de87886aec91a04,因此这是已核实的元数据时间变化,不是内容变化。上述新增对象不得暗中进入当前批次,必须在以后重新执行READY握手时进入新批次。

监督器随后复核两卷UUID、manifest SHA、JSONL零损坏、无活动flock、partial所有权与4.78 TB左右可用空间,确认均满足既有--resume前置条件。事故账保存于〔本地资料路径省略〕,SHA-256为8bc1e873dab2880979257a961712abaa9e7ad1b171fbe49c321f7b5e01fa6552。02:57 UTC以LaunchAgent启动新会话20260714T025724Z-fa8e148346ba;首两项.DS_Store3P/.DS_Store已获得源—目标SHA一致的resume_verified事件,说明固定manifest恢复链路已经重新工作。

本次处置只证明“两个新增对象被排除、已有.DS_Store内容未变、恢复前置条件通过”;它不把当前源根重新宣称为原始READY-B状态。新会话将继续逐件复验已有final,并在复制未完成manifest成员时做源—目标SHA-256校验。镜像后的source metadata gate还必须显式识别这份已登记的out-of-batch增量,不能静默忽略,也不能把它误并入当前6,154条视频路径分母。

镜像停止窗口内,post-mirror runner在02:56 UTC按设计把“launchd镜像未运行且progress未完成”记为blocked并退出;这不是新的媒体校验冲突。镜像恢复后已重新启动该runner,03:00 UTC进入verify_manifestlast_error=null,随后只会回到等待镜像终态的状态,不会触发bulk ASR。

十七、封存后漂移精确闸门:受控部署成功、等待镜像终态

02:52 UTC事故不能靠“忽略manifest以外对象”草率收口。当前批次新增了一份单独、SHA钉死且无通配符的许可账:

wiki/meta/ledgers/p4-12tmac01-snapshots/20260713T0915-0700-ready-b/
source-drift-allowance-20260714T025240Z.json
SHA-256 = c3f88b54576f2383b39eb6863243ffeb0de2ef1146669f05dbc8cd68cf588ebc
incident SHA-256 = 8bc1e873dab2880979257a961712abaa9e7ad1b171fbe49c321f7b5e01fa6552

它接受的不是“这个目录以后都可以变”,而是三个封闭事实:

  1. 当前精确的非许可目录路径集有528条,路径集摘要为daa7a167ae076dffaa326851d4ffe521410099e8725bfac5b3485c45d1b080ae;再加唯一获准且必须保持为空的幸福王国,当前总数仍为529。
  2. 唯一获准的非manifest文件是王亚男 风车 TV/DJI_0298.MP4,只按当次记录的路径、类型、字节、inode、mode、mtime、ctime与birth time逐项比对;本许可不打开、不哈希它,也不把它加入21,299文件或6,154视频分母。
  3. .DS_Store是唯一manifest元数据例外,只允许那一次mtime差异;每次过门仍须重算源文件与既有目标final,且两者都必须等于de593351c97a4ac9ee7404bc82e5ac338419974f7d7b82787de87886aec91a04以及terminal receipt中的同一路径SHA。

这里必须保留一条不能补造的证据边界:READY-B只保存了“含根共529个目录”的计数,没有保存当时529条目录路径身份。事故后可接受状态是“528条非许可目录+1条已登记空目录=529”,但现有证据不能证明READY-B时缺席空目录的名字和身份;“发生过移动或改名”只能作为一种可能推断,不能写成事实。以后任何新增、消失、路径集摘要变化、许可对象fingerprint变化或.DS_Store再次变化,都必须重新立事故账与新许可账,不能沿用本次例外。

v4实现的闭合范围

p4_post_mirror_probe_runner.py 2026-07-14.4的已部署SHA-256为58be4336b6766e676275fd1e1bdd11495793a66997740f6be8c855f7560b067f,状态文件改为post-mirror-probe-runner-status-v4.json。它在真正写入fixity或队列前后增加了以下fail-closed闭包:

regular file在被stat之后发生同inode原位写入,仍存在没有FSEvents journal seal便无法彻底消除的窄观察窗;READY manifest也没有源内容SHA可供本门逐件重算。v4因此把这一点明写进状态证据,不把元数据稳定冒充内容不可变。真正的内容权威仍来自镜像逐件源—目标SHA与terminal receipt。

离线验证结果与证据边界

本轮只运行了临时目录测试与manifest/许可账解析,没有再次扫描〔本地资料路径省略〕媒体树,也没有启动probe、fixity exporter、ASR或launchd重启:

PYTHONDONTWRITEBYTECODE=1 python3 -m unittest -v \
  inspool-wiki-zh/scripts/tests/test_p4_post_mirror_probe_runner.py

Ran 17 tests ... OK

17项回归全部使用TemporaryDirectory,覆盖未知文件/目录、许可空目录非空、许可文件fingerprint变化、.DS_Store同尺寸错内容、等数目录替换、同数伪造queue、ASR执行命令守卫、共享freeze、receipt session与full scope、resume fixity空event_target_bytes、duplicate完整元数据、完整fixity不自动quarantine、summary伪造、reporting发布后替换和receipt前后progress替换。另做AST解析以及只读manifest/许可账smoke:21,299行、4,419,913,652,206 B、6,154视频、528+1目录和上述SHA均通过;红队复核收口为P0=0 / P1=0这些测试只证明离线逻辑,不证明真实源树此刻已经通过v4门。真实三遍source gate只会在镜像成功终态后由已部署runner执行。

05:00 UTC受控部署结果

2026-07-14约05:00 UTC完成了最小范围的受控部署。操作只对com.p4.archive.postmirrorprobe.ready01执行一次bootout/bootstrap;没有停止、重启或重载镜像与Spotlight恢复作业,也没有因此读取媒体正文或启动任何后继处理。部署凭据如下:

  1. 旧post-mirror进程PID 96920已经退出;post-mirror-probe-runner.lock的inode为1778704,在重新bootstrap前确认可取得排他锁。新进程PID为89239。
  2. 镜像仍为PID 92483,Spotlight恢复器仍为PID 5886;这两个PID在部署前后均未改变,说明替换范围没有越过post-mirror单一job。
  3. runner版本为2026-07-14.4,SHA-256为58be4336b6766e676275fd1e1bdd11495793a66997740f6be8c855f7560b067f;被钉住的ASR pipeline SHA-256为c20a641f6ae91609f961fd476ef589201eecc2220c332181253cc31873364df5;漂移许可账SHA-256为c3f88b54576f2383b39eb6863243ffeb0de2ef1146669f05dbc8cd68cf588ebc
  4. 必须区分两种配置指纹:代码内默认配置使用poll_seconds=60,其SHA-256为04664044f0f4b8b3e8a4967c6a11d4d0cff134667c81e5cfd3f23442dec4d53b;现有plist实际传入--poll-seconds 300,所以本次部署的effective config SHA-256是b22d3d8261191e1af1f8df9041d533d7509df27c182901affd515610c95cbda9。二者不同是受允许的operator timing override,不是配置漂移。
  5. 新v4 status于2026-07-14T05:00:01Z开始,当时为state=waiting / phase=wait_for_mirrorlast_error=null;manifest、许可账和工具链的初始校验均已完成。它未取得镜像终态,因此没有提前运行final fixity、扩展6,154路径、执行全量ffprobe或触发bulk ASR;09:45曾因incident hold卸载,09:54Z已重新bootstrap为PID 34666并恢复waiting / last_error=null,后续状态见第二十节。

部署成功在当时的准确含义只是:正确版本、正确工具链和实际effective config已经在正确的单一launchd job中等待镜像成功终态。这份部署证据仍然有效,但job现已因故障保持而unloaded。部署不表示真实源树已经通过三遍source gate,不表示6,154条视频已经probe,更不表示READY-B时刻的位级原貌已被证明。READY manifest的逐行SHA字段原本为空;当前内容权威仍须由镜像逐件源—目标SHA、terminal receipt和后继闸门共同建立。

镜像成功结束后,应让v4自行取得terminal mirror lease,依序完成final fixity、6,154路径扩队、全量probe、报告与terminal seal;不要手工并行启动initprobe或任何run --execute。任一UUID、容量、progress、receipt、fixity、源树、queue或工具校验失败时保持fail-closed,保留status、日志和证据文件供复核,不得以删除canonical证据、放宽许可或绕过freeze来换取“完成”。

十八、08:14 UTC既有final复核完成并转入剩余对象复制

2026-07-14约08:14 UTC,恢复会话20260714T025724Z-fa8e148346ba完成了02:52 UTC停机前已有的10,245个final的逐件复核。每一件都重新计算当前源文件与目标final的SHA-256并取得一致结果,本轮复核为零冲突;append-only progress.jsonl的解析检查仍为malformed=0。这标志着会话从“重验既有final”转换到“复制尚未完成的manifest对象”,不是21,299件全批完成,也不是镜像terminal receipt已经生成。

停机时登记的owned partial为天台上的嚎叫者/3P 天台山的嚎叫者/HF_2020_12_19_12_54_41.mp4.p4mirror.partial,中断时有260,046,848 B。恢复会话在走到该路径时按既定断点安全语义写入partial_restart,没有把旧partial当作已验证前缀续接,而是从零重新复制;源流SHA与目标partial重读SHA一致后,脚本将其原子发布为592,220,006 B final,同名.p4mirror.partial随发布消失。随后镜像越过该路径继续复制未完成对象。

阶段转换后的短时观察显示:约08:14 UTC恢复会话已有至少15个新copied事件,稍后的同一轮观察增至18个;这些新发布件的源/目标SHA均一致。1518只记录当时恢复会话进入新复制阶段后的动态截面,不应写成长期总数或完成率。容量门同样按时点解释:这些progress事件记录的目标可用空间约4.77 TB,df只读观测也约4.77 TB,均高于1.5 TB硬保留线;随着后续复制继续,余量会变化,真正约束始终是“不得跌破1.5 TB”,而不是维持某个小数。

证据措辞继续限定为固定manifest下的 current-source verified mirror:READY-B manifest的逐行SHA字段原本为空,所以本轮10,245件复核与随后新复制证明的是“复核/复制时当前源字节与目标字节一致”,不能倒推出每一件仍等于READY-B时刻的位级原貌。post-mirror v4 runner在这一阶段仍保持waiting / wait_for_mirror;尚未运行final fixity、扩展6,154路径、全量probe或bulk ASR,也不得因既有final复核完成而提前启动这些后继步骤。

十九、09:16—09:31 UTC持续无进度与受控恢复

2026-07-14 09:16:31Z之后,镜像会话20260714T025724Z-fa8e148346ba的append-only progress停在一个copy_started事件,至09:30:57Z约14分钟没有新增进度。对应目标partial为天台上的嚎叫者/嚎叫者/2020 12.26/DJI_0045.MP4.p4mirror.partial,当时大小2,065,296,234 B,同名final不存在。只读进程观察显示PID 92483处于U态、CPU约0.1%;lsof只显示它以5r打开该目标partial,连续12秒两次stat所见大小和时间均未变化。两卷仍然挂载,现有日志未发现明确的磁盘I/O错误。因此本次只登记为持续无进度/疑似阻塞,不把进程状态或短时静止外推为硬盘故障。

依据连续无进度停止线,09:30:57Z向旧镜像进程发送SIGTERM;进程在2秒内退出,没有强杀、拔盘或改写源树。恢复前逐项重新确认:

  1. 源卷与目标卷仍以既定UUID挂载;
  2. 权威manifest SHA-256仍为2342c8514dd298da4a4302d4c188789c08ec7e0bcdee4f1006729ef6482592cd
  3. 已登记的源树边界未再漂移;
  4. 旧进程已退出且无活动mirror flock;
  5. 2,065,296,234 B partial可由既有progress.jsonlcopy_started事件证明归属,具备--resume恢复条件,同名final仍缺失;
  6. 目标卷可用空间约4.53 TB,高于1.5 TB硬保留线。

全部前置条件通过后,09:31:49Z使用既有launchd配置和同一批次--resume机制恢复,没有另造目标树。新镜像PID为93130,新会话为20260714T093151Z-cb8561fc6e46。恢复会话先对两个.DS_Store final完成当前源/目标SHA一致的事件,随后进入第三个约4.56 GB对象复核。这个当时截面只证明恢复会话已经启动且出现两个成功事件,不足以声称持续吞吐已经完全恢复;其后的无进度复发与封停见第二十节。

镜像短暂消失时,post-mirror runner按设计fail-closed退出;镜像恢复后仅对该runner做受控重启,新PID为93199。v4 status保持waiting / wait_for_mirrorlast_error=null。Spotlight恢复器PID 5886在全过程未被停止或重载,目标卷Spotlight索引仍为disabled。本事件没有启动final fixity、6,154路径扩队、全量probe或bulk ASR,证据边界继续限定为固定manifest下的current-source verified mirror,READY-B逐行内容SHA缺失这一限制也没有改变。

二十、09:31—09:45 UTC持续无进度复发与故障保持

第一次受控恢复并没有形成可持续吞吐。launchd在09:31:49Z启动恢复动作后,新会话20260714T093151Z-cb8561fc6e46于09:31:52Z写入会话起点;它只完成了根.DS_Store3P/.DS_Store两个既有final的当前源/目标SHA一致复核。09:31:53Z开始校验manifest第三项3P/20200919_145015.mp4,该文件为4,562,092,032 B。直到09:44:34Z,append-only progress再无任何新增事件;PID 93130持续处于U态、CPU约0,进程当时已运行约12分45秒。

这与前一轮“持续无进度/疑似阻塞”同型,因而记为复发的持续无进度,但仍不外推为硬盘故障:本次证据只表明同一恢复链在第三个manifest对象校验期间没有产生可观察进展,不能仅凭U态、零CPU或progress静止确定故障层级。09:45:06Z向PID 93130发送SIGTERM,进程约3秒后退出;没有强杀、拔盘、改写源树、删除partial或重写append-only进度账。

第二次事件后的处置不再是自动恢复,而是incident hold/故障保持。为避免镜像进程消失后自动触发Spotlight恢复,或让post-mirror runner误把停机窗口当作可接力终态,先卸载com.p4.archive.spotlightrestore.ready01,再卸载com.p4.archive.postmirrorprobe.ready01。最终状态为:

  1. com.p4.archive.mirror.ready01的job定义仍loaded,但没有运行中的mirror进程;
  2. com.p4.archive.postmirrorprobe.ready01com.p4.archive.spotlightrestore.ready01均unloaded;
  3. 源卷Spotlight索引为enabled,目标卷仍为disabled;
  4. v4没有取得成功镜像终态,也没有运行final fixity、扩展6,154路径、全量probe或bulk ASR。

故障保持没有抹除已完成证据。前一复制阶段在会话20260714T025724Z-fa8e148346ba中累计发布298个新对象/256,734,203,383 B,全部记录为源/目标SHA一致,零SHA冲突;这些事件继续封存在既有progress.jsonl。目标卷当时约有4.53 TB可用空间,高于1.5 TB硬保留线。天台上的嚎叫者/嚎叫者/2020 12.26/DJI_0045.MP4.p4mirror.partial仍为2,065,296,234 B,具有先前copy_started事件所证明的owned partial身份,同名final缺失,因而在未来满足全部恢复门时仍可按既有语义处理;当前保持不动。

09:45Z当时的下一动作不是再次kickstart--resume,而是等待外部状态变化或完成人工诊断;只有随后重新验证两卷UUID、manifest SHA-256、源树登记边界、无活动flock、partial可恢复性与同名final关系,以及目标空间高于1.5 TB保留线,才可重新评估同一批次恢复。该历史hold后来因09:47发现并移除非本批宽扫、磁盘静置这一明确外部状态变化而进入一次新的恢复评估;这不把复发省略为普通断点,也不授权在镜像终态之前启动全量probe或任何bulk ASR。

20.1 09:47—09:54 UTC:外部宽扫争用移除、重验恢复门与观察性恢复

09:47Z的只读lsof/ps检查发现,同一ChatGPT/Codex父进程PID 36967之下有两个不属于本批次的宽范围扫描已经运行约27—28分钟:PGID 77545的find/tmp〔本地资料路径省略〕〔本地资料路径省略〕全树寻找海报;PGID 78468的rg扫描〔本地资料路径省略〕〔本地资料路径省略〕寻找YouTube链接。同期disk9约为164—174 tps、2.3—2.4 MB/s随机读。现有证据不能证明这两个宽扫是两次停滞的唯一根因,但它们明确违反“避免对同一ACASIS机箱增加额外媒体扫描”的执行边界,并形成可观测的I/O争用。

09:47:44Z只终止上述两个进程组,没有触碰、移动、改名或删除任何数据,也没有操作镜像数据结构。随后disk8/disk9连续样本均为0 MB/s;QuickLook进程仍持有静态文件描述符,但观察窗口未见对应磁盘吞吐。两分钟静置构成相对于09:45 hold的明确外部状态变化,但这只说明争用条件被移除,不能由此证明硬件无故障或把全部停滞归因于宽扫。

09:50:39Z再次严格核对两卷UUID、manifest SHA-256、无活动flock、owned partial及同名final关系、目标约4.53 TB可用空间高于1.5 TB保留线、已登记源边界未再漂移,并确认没有残留宽扫。全部门通过后,09:50:40Z沿既有launchd与--resume语义恢复;当前镜像PID为30509,会话为20260714T095042Z-2286a6abafee。该会话很快越过此前停在的第三项4,562,092,032 B对象,并至少继续复核到7,218,953,892 B文件;观察期间持续写入源/目标SHA一致事件且CPU活跃。因此可记录为“在外部争用移除后恢复了可观察吞吐”,但仍须继续监督,不宣称故障根因已经唯一确定。

09:54Z重新bootstrap post-mirror v4 runner为PID 34666、Spotlight waiter为PID 34668。v4当前为waiting / wait_for_mirrorlast_error=null;源卷索引仍为enabled、目标卷仍为disabled。两项后继任务只等待镜像成功终态,没有运行final fixity、扩展6,154路径、全量probe或bulk ASR。若镜像再次连续无进度、出现I/O错误、校验冲突、卷掉线、容量跌破保留线或源树再漂移,必须再次fail-closed停止破坏性动作并保留证据,不得将本次恢复变成自动重试循环。

引用与版本

P4 剧场研究档案:《全量视频字幕与内容识别流水线》,来源版本 2026-07-14,公开研究版 2026-09-08

https://a.p4theater.top/research/hs-1e923859c8605e9b

馆内参考标记指尚未在本次文库公开的资料,不能视为读者已可访问的独立证据。不同版本、译文与同一材料的转述,不计作相互独立的证据。