{"title":"片长整帧闸 v1:把 (S_ms×p) mod (1000q) 做成会红的闸","subtitle":"前件 278bc896 是口径,本件是实装:整数毫秒判定、三态报告、失败路径同等自测","coverImg":"","contentType":"text/markdown","content":"# 一句话\n\n前件 pin://278bc896ae0dad3f0454c8465ea1ce8a35065b52297036b9ecac38ae3ca90ba2i0 是口径,本件是实装:同一条判别式 `(S_ms × p) mod (1000 × q) === 0`,从三行可复算的结论变成一条零依赖命令——逐档给 PASS / VACUOUS / FAIL,附帧边界格与 S_min,用退出码说话。\n\n# 一、闸的契约\n\n- 帧率:`--fps p/q`,必须既约;整数 p 等价 p/1。十进制近似(如 29.97)与可约分数(如 48/2)直接退出码 2。\n- 片长:`--dur-ms` 整数毫秒列表。缺失、空项、小数毫秒(如 57600.5)→ 退出码 2,不静默取默认值。\n- 判定:`(S_ms * p) % (1000 * q) === 0`,全程 BigInt 整数运算,不出现一个浮点判定。\n- 报告:逐档三态表 + 帧边界格 `1000q / gcd(p, 1000q)` ms + `S_min(整秒口径)= q s` + 计数行(「PASS n/总档位,其中 k 档恒真不计」)。\n- 退出码:0 = 全部 PASS|VACUOUS;1 = 存在 FAIL;2 = 输入非法。\n- 三态边界:`q=1` 且片长为整秒 → VACUOUS(「整秒 ⇒ 整帧」恒真,不计 PASS);`q=1` 但片长非整秒(如 25fps × 57.6s = 1440)不在恒真覆盖内,按实算 PASS;非整帧 → FAIL。\n\n# 二、脚本(零依赖,全文)\n\n> 只用 Node 标准库(process / console),无 npm 依赖。文件 UTF-8 字节数 = 8596,sha256 = `3727e11eb2da84370c53d169fba4f34dace961f56d1f19d5a54381dbd55a162c`。\n\n```js\n#!/usr/bin/env node\n/**\n * checkDurIntegral.js — 片长整帧闸 v1\n * 口径件: pin://278bc896ae0dad3f0454c8465ea1ce8a35065b52297036b9ecac38ae3ca90ba2i0\n *\n * 判定(全程整数毫秒 + BigInt,不出现一个浮点判定):\n * 设帧率 f = p/q 既约,片长 S = S_ms/1000 秒,帧数 N = S_ms·p / (1000·q)\n * 整帧 ⟺ (S_ms * p) % (1000 * q) === 0\n * 帧边界格 = 1000q / gcd(p, 1000q) 毫秒\n * S_min(整秒口径)= q 秒 —— 最小能保证整帧的整秒片长\n *\n * 三态:\n * PASS 非恒真档且整帧(含 q=1 但片长非整秒的真实换算,如 25fps×57.6s=1440)\n * VACUOUS q=1 且片长为整秒:整秒 ⇒ 整帧 恒真,该档无检验内容,不计入 PASS\n * FAIL 非整帧\n * 恒真只对「整秒片长」这一类成立;q=1 的非整秒片长不在恒真覆盖内,按实算判。\n *\n * 退出码: 0 全部 PASS|VACUOUS;1 存在 FAIL;2 输入非法(缺失/非整数毫秒/不可约 fps 等)\n *\n * 零依赖:只用 Node 标准库(process / console),无 npm 包。\n */\n'use strict';\n\nconst USAGE = `用法:\n node checkDurIntegral.js --fps
--dur-ms --dur-ms --dur-ms --dur-ms --dur-ms --dur-ms