Skip to main content

hyperframes.interpolate

Take a project_artifact_key from hyperframes.scaffold, run LLM passes over each compositions/*.html file to rewrite the visible text content so it fits the user's topic, and re-upload the modified project as a new project_artifact_key.

Second link in the four-pack scaffold-video chain:

hyperframes.scaffold → scaffolded project (upstream's generic placeholder content)

hyperframes.interpolate → THIS PACK: visible text now matches the user's topic

hyperframes.attach_asset → A-roll image / video spliced into #short_mag_cut_frame

hyperframes.render → MP4

How content is detected

Each compositions/*.html file is classified by content pattern (one LLM pass per file):

Detected patternStrategyExample slots rewritten
<h1>, <h2>, <h3>, <div class="stat-value">, <div class="stat-label">html_text_slots — extract each slot's inner text, ask the LLM to rewrite each on-topic in a numbered format, splice back.intro.html title + subtitle. graphics.html stat values + labels.
const TRANSCRIPT = [{text, start, end}, ...];js_transcript — ask the LLM to generate a fresh word-level transcript timed against duration_seconds, replace the array literal wholesale.captions.html caption word array.
neither pattern presentunknown_shape — pass through unchanged. Reported in files_skipped.exotic upstream examples that use different content shapes.

If NO file in the scaffold matches a recognized shape, the pack rejects as invalid_input with the message "no files in the scaffold matched a recognized content shape — try a different upstream example."

Inputs

FieldTypeRequiredDefaultNotes
project_artifact_keystringyesKey from hyperframes.scaffold's output (or any project tarball satisfying the scaffold contract).
descriptionstringyesThe video topic. The LLM rewrites visible text to fit this.
modelstringyesProvider/model id. Tier C (gpt-oss-120b:free, gemma) gets a verbose constraint-heavy prompt; Tier A/B gets a lean one.
duration_secondsnumberno8.0Used to pace the caption transcript at ~150 wpm. Pair with podcast.generate's duration_s output for a narrated video. Capped at 720s.
audio_notestringno""Extra context for the LLM (e.g. "narration is calm and educational" — surfaces in both prompts).
max_tokensnumberno4096Per-LLM-call token budget. Clamped to [1024, 8192].

Outputs

FieldTypeNotes
project_artifact_keystringNEW key — the modified project tarball. Feeds hyperframes.attach_asset or hyperframes.render.
original_project_artifact_keystringEcho of the input key.
files_rewrittenarrayEach entry: {path, kind, original_size, new_size}. The interpolate manifest.
files_skippedarrayPaths the pack skipped, with reason (unknown_shape, rewrite error: ..., file cap).
model_usedstringEcho of the input model.

Behavior

Soft-degrade on per-file LLM failure

If the LLM fails on one file (returns no choices, dispatcher error, parse error), that file is added to files_skipped and processing continues on the next file. The pack only fails the whole call when ZERO files got rewritten.

Caption-transcript timing is heuristic, not whisper-aligned

The LLM generates a TRANSCRIPT array timed to duration_seconds at a ~150 wpm cadence. This produces caption text that's approximately aligned to the audio narration but is NOT word-by-word synced to actual speech. For broadcast-quality captioning, a separate whisper pass would be needed after the audio is finalized. The heuristic is fine for explainer/social videos where rough alignment is acceptable.

Token-budget per file

Each compositions/*.html file gets its own LLM call. For a typical 3-composition scaffold (intro + graphics + captions) that's three calls. The pack does NOT batch them into one prompt — the format requirements per file (numbered slots vs JSON transcript) are different enough that batched prompting confuses Tier C reliably.

Validation & errors

FailureCodeNotes
Missing project_artifact_key / description / modelinvalid_inputSpecific message per field.
project_artifact_key not in storeinvalid_inputSurfaces store error.
Empty artifact contentinvalid_inputCatches truncated upload.
Malformed tarball (not gzip / not tar)invalid_inputgzip decompress / tar reader errors are surfaced.
No files matched any recognized shapeinvalid_inputTry a different upstream example.
Single-file LLM failure(logged, not fatal)File appears in files_skipped; other files still rewrite.
All-files LLM failureinvalid_inputSame path as "no files matched" — rewritten is empty.
Artifact upload failureartifact_failedBackend issue.

Chaining example

Hand-chained:

# After hyperframes.scaffold returned KEY_SCAFFOLD.
KEY_INTERP=$(curl -X POST .../packs/hyperframes.interpolate/v1/execute \
-d "{
\"project_artifact_key\":\"$KEY_SCAFFOLD\",
\"description\":\"eBPF tracepoint observability for kernel rootkit detection\",
\"model\":\"openrouter/openai/gpt-oss-120b:free\",
\"duration_seconds\":15
}" | jq -r .output.project_artifact_key)

# Continue chain: hyperframes.attach_asset, then hyperframes.render.

Pipeline-orchestrated (recommended): the builtin.scaffolded-narrated-video pipeline (PR 7) wires this in automatically — operators pass description, model, and example, the pipeline handles the rest.

See also