# 把有序 PNG 序列组装为审片视频

用明确的每秒两帧时间安排，把已有静帧组装为审片。本任务是图片序列正向编码，没有生成中间帧，也不是从视频反向抽帧。

完整包只使用 Node 标准库。FFmpeg 需使用自己已有的安装，本包不分发二进制；不在 PATH 时将 FFMPEG_BIN 设为其绝对路径。

在本目录运行，并选择不存在的新输出目录，脚本拒绝覆盖。受内存管理的工作站可在 Node 命令前加本地串行执行包装器。不需要提供商密钥，夹具不会向设备外发请求。

```sh
node run-recipe.mjs --out ./my-run
```

实际记录：9项检查通过，包含4项预期拒绝，Node v24.18.0。ffmpeg version 6.0 Copyright (c) 2000-2023 the FFmpeg developers

准备

- 准备 Node.js 与 FFmpeg，必要时设置 FFMPEG_BIN。输入为三张原创 160×90 PNG，分别是红、绿、蓝色区并带白色边缘标记。
- 查看 sequence.json：索引1至3分别绑定 frame-0001.png 至 frame-0003.png 和 SHA-256，输入帧率明确为两 FPS。
- 选用新输出目录，并要求输入文件名集合完全一致。图像看起来合理，但顺序错误，仍必须判定清单失败。

## 01. 固定图片序列身份

脚本生成三张练习图与明确的有序清单，每行同时保存索引、准确 basename 和 SHA-256。不能用文件系统遍历顺序代替剪辑顺序。

## 02. 编码前拒绝断号、多图和错字节

分别实跑交换清单行、临时移除第二帧、增加第五帧及错误哈希。每例都应失败，finally 会恢复原始完整序列，然后才进入实际编码。

## 03. 按声明输入帧率编码

使用 -framerate 2 -start_number 1 与 frame-%04d.png，并明确最多输出三帧。实际 review.mp4 采用 yuv444p 且无音轨。每张 PNG 贡献一帧，目标时长为1.5秒。

## 04. 验收帧数和色彩顺序

完整解码 MP4，确认只有三帧 160×90 RGB。逐帧抽样中心色区，与预期红、绿、蓝比较，单通道容差四；本次最大差值为一，没有插帧。

验收

- 三行清单准确对应连续的 frame-0001.png 至 frame-0003.png。
- 交换清单行会在编码前被拒绝。
- 缺帧与额外的非连续编号帧分别被拒绝。
- 错误的预期 PNG SHA-256 会被拒绝。
- 审片文件实际解码为三帧 160×90，组装使用明确的两 FPS。
- 中心色区按红、绿、蓝排列，各通道误差不超过四，九项检查通过。

排错

图片都对，但审片顺序错了。只更正清单顺序与索引到文件名的绑定，重新预检后再编码。

编号序列缺图，编码提前停止。恢复准确 basename 与哈希对应的原始 PNG，不默默复制相邻帧补位。

审片播放太快。只修改声明的输入帧率并记录新预期时长，保留三份图像身份并重跑顺序检查。

公开回执副本仅归一化本地 checkout 路径，publicPathNormalization 保存原始回执 SHA-256；未改动原件保留在非公开资产之外。真实回执位于 executed/。failure-receipt.json 记录预期负向案例，不表示套件断言失败。原创新夹具会重新生成到指定新目录，包内保留实跑输入输出便于复核。子进程使用参数数组、禁用 shell，设15秒超时与8MB输出上限。临时原始数据和本机 HTTP 服务在 finally 清理。

checksums.json 覆盖自身与 ZIP 以外的全部分发文件，避免循环自引用；ZIP 内包含同份清单。下载后可重算，但比较前提是预期清单可信。execution-receipt.json 记录实际脚本运行前后哈希，ZIP 也会由发布目录的资产清单绑定。

把 sequence.json 与审片结果放在一起。本夹具证明选定顺序和帧数，不创造运动，也不额外延长帧停留或验收分发编码。

2026-10-14 实际读取的来源

- FFmpeg image2 format: image sequence inputs：https://ffmpeg.org/ffmpeg-formats.html#image2-1
- FFmpeg command-line documentation: maps, codecs and error exit：https://ffmpeg.org/ffmpeg.html
- Node.js crypto API: SHA-256 hashing：https://nodejs.org/api/crypto.html
