# Validate SRT cue overlap, duration and media boundaries

Reject ambiguous cue order, zero-length captions, overlap and past-end timing before rendering. This recipe only covers the declared simple SRT subset and a supplied two-second media boundary.

This complete kit uses Node standard-library modules only. No media tool installation is required.

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: 9 checks passed, including 6 expected rejections. Node v24.18.0. No FFmpeg subprocess.

Preparation

- Use Node.js without any third-party package or FFmpeg. The duration.json fixture explicitly supplies a 2,000-millisecond media boundary.
- Read valid.srt: cue 1 spans 0–700 ms, cue 2 spans 700–1,400 ms and cue 3 spans 1,500–2,000 ms. Adjacent cues and a final end equal to media duration are allowed.
- Keep the strict format HH:MM:SS,mmm --> HH:MM:SS,mmm, sequential cue indices and nonempty text. The fixture is plain text and makes no font or burn-in claim.

## 01. Define the timing policy before parsing

The fixture uses integer milliseconds, sequential indices starting at one, no overlap and end > start. The media boundary is an explicit input; the script does not discover a video’s real duration. The one-hundred-millisecond gap before cue 3 is intentional.

## 02. Parse the accepted cues

Run the command and inspect cue-table.json. It contains the three actual parsed start/end values. A cue starting exactly at the previous cue’s end is accepted, and the last cue may end exactly at 2,000 ms.

## 03. Replay six invalid subtitle files

The runner writes and tests overlapping, zero-duration, past-boundary, wrong-index, malformed-millisecond and invalid-minute variants. Each expected rejection records its concrete validation error. A correctly shaped timestamp with a minute component of 60 is still invalid.

## 04. Hand off validated timing for a separate render

Check all nine assertions and retain the cue table beside the original SRT. Font coverage, line layout, reading speed, HTML extensions and rendered appearance remain separate tasks. This download contains no CJK font inventory or burned subtitle video.

Acceptance

- The supplied valid.srt parses into exactly three cue rows with integer milliseconds.
- Cue 2 starting at cue 1’s 700-ms end is accepted.
- The final cue ending exactly at the 2,000-ms media boundary is accepted.
- Overlap and zero-length cue variants are rejected with different recorded reasons.
- A cue ending at 2,001 ms and nonsequential numbering are rejected.
- Malformed milliseconds and a minute component of 60 are rejected; all nine checks pass.

Troubleshooting

Adjacent captions are incorrectly flagged as overlap. Use start >= previousEnd for the no-overlap rule and rerun the 700-ms boundary case.

The last cue is rejected at the video end. Verify the supplied durationMilliseconds first. If it is correct, allow end equal to that boundary while still rejecting 2,001 ms.

A well-formatted cue has no visible time. Change only end so it is strictly later than start, then recheck overlap against the next cue. Do not delete the zero-duration rule.

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. 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.

Validated timings are a handoff input for a render stage. They do not prove a particular font displays, captions fit the frame or viewers can comfortably read the text.

Sources read on 2026-10-14

- Node.js filesystem API: local file inspection: https://nodejs.org/api/fs.html
- Node.js crypto API: SHA-256 hashing: https://nodejs.org/api/crypto.html
