# Trim a bounded reference-video time window and verify the kept frames

Create a one-second reference excerpt using explicit start-inclusive/end-exclusive boundaries. This recipe trims a continuous video segment; it does not choose a still frame by time base.

This complete kit uses Node standard-library modules only. Install/use your own FFmpeg; the binary is not redistributed. Set FFMPEG_BIN to its absolute path if it is not on PATH.

Run from this directory and select a NEW output directory. Existing output directories are refused. On a memory-managed workstation, put its local serialization wrapper before the Node command. No provider credentials or off-device fixture requests are used.

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

Recorded execution: 11 checks passed, including 5 expected rejections. Node v24.18.0. ffmpeg version 6.0 Copyright (c) 2000-2023 the FFmpeg developers

Preparation

- Use Node.js plus FFmpeg and set FFMPEG_BIN if needed. The fixture builds a small 320×180, ten-FPS, three-second original reference clip.
- Read window.json: source duration is measured as 30 decoded frames at the fixture’s declared constant rate; selected start is 0.5 and end is 1.5 seconds.
- Choose a new output directory. Use the provided CFR fixture first; deriving the usable end of an arbitrary VFR or nonzero-start reference requires its own timestamp inventory.

## 01. Establish the available source interval

Fully decode the original fixture and confirm thirty frames at ten FPS, establishing its three-second controlled interval. The raw construction buffer is temporary and removed in finally. Do not use this controlled CFR duration rule as an unqualified VFR duration estimator.

## 02. Reject invalid boundaries before encoding

The local window validator requires finite numbers, start ≥ 0, end > start and end ≤ measured source duration. It executes separate negative cases for a negative start, equal boundaries, reversed boundaries, a past-end request and NaN.

## 03. Trim and reset the output time origin

Apply trim=start=0.5:end=1.5,setpts=PTS-STARTPTS and re-encode the video. The trim filter keeps the continuous source interval, while setpts makes the excerpt start at zero. The end boundary excludes the source frame beginning at 1.5 seconds.

## 04. Compare both endpoints and every output timestamp

Decode the result to ten frames and compare its first/last RGB frames against source indices 5 and 14. Parse actual showinfo output to verify PTS 0.0 through 0.9 in 0.1-second steps. The executed fixture measured zero endpoint channel difference.

Acceptance

- The source actually decodes to thirty 320×180 frames at the controlled ten-FPS rate.
- The 0.5–1.5-second window passes the finite-number and interval rules.
- The excerpt decodes to exactly ten frames, corresponding to one second at ten FPS.
- First and last output frames match source indices 5 and 14 within four channel values; the recorded differences are zero.
- The observed output timestamps begin at zero and finish at 0.9 seconds.
- All five invalid-window cases are rejected and the eleven-check receipt retains actual showinfo evidence.

Troubleshooting

The first timestamp is still 0.5 seconds. Add or restore only setpts=PTS-STARTPTS after trim and reread the output showinfo timestamps.

The excerpt includes a frame from 1.5 seconds. Use the documented exclusive end boundary and check source index 14 as the final fixture frame; avoid increasing the requested end to compensate.

The requested end lies beyond the reference. Reduce only endSeconds to an established source boundary, or obtain the intended longer reference. Do not silently clamp an invalid request.

Public receipt copies normalize only local checkout paths and include publicPathNormalization with the original receipt SHA-256; raw originals are retained outside public assets. The actual receipts are under executed/. failure-receipt.json lists expected negative cases, not failed-suite assertions. Original tiny fixtures are generated again into your new output directory; shipped executed inputs and outputs let you inspect the recorded run. Subprocesses have a 15-second timeout, an 8-MB output cap, argument arrays and no shell. Temporary raw buffers and local HTTP servers are cleaned in finally.

checksums.json records every distributed file except itself and the archive, avoiding self-reference. The ZIP includes that same checksum list. Recompute hashes after download; comparison requires trusting the expected list. execution-receipt.json records executed script hashes before and after the run. The complete kit archive is also bound by the publishing catalog asset inventory.

Keep the requested window, measured source interval and decoded endpoint checks together. The small CFR fixture proves this trim operation and does not establish every real reference clip’s timestamp behaviour.

Sources read on 2026-10-14

- FFmpeg filters: scale, pad, trim, setpts and showinfo: https://ffmpeg.org/ffmpeg-filters.html
- FFmpeg command-line documentation: maps, codecs and error exit: https://ffmpeg.org/ffmpeg.html
- Node.js child process API: bounded argument-array execution: https://nodejs.org/api/child_process.html
