aivee 0.1.0-alpha.0 → 0.1.0-dev.d34a6ba
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +120 -118
- package/docs/architecture.md +401 -401
- package/docs/aspect-ratio-presets.md +72 -72
- package/docs/releasing.md +19 -19
- package/docs/usage.md +1193 -1193
- package/package.json +52 -52
- package/requirements-otio.txt +1 -1
- package/src/capabilities.mjs +307 -307
- package/src/cli.mjs +646 -646
- package/src/doctor.mjs +133 -133
- package/src/edits/analysis-to-edl.mjs +43 -43
- package/src/edits/detect-silence.mjs +51 -51
- package/src/edits/find-mistake-candidates.mjs +42 -42
- package/src/edits/plan-shot-placements.mjs +105 -105
- package/src/edits/plan-silence-cuts.mjs +49 -49
- package/src/edits/retime-transcript.mjs +105 -105
- package/src/files.mjs +80 -80
- package/src/index.mjs +44 -44
- package/src/interchange/otio.mjs +204 -204
- package/src/interchange/otio_bridge.py +521 -521
- package/src/media/analysis-provider.mjs +75 -75
- package/src/media/compatibility.mjs +45 -45
- package/src/media/ffmpeg-capabilities.mjs +129 -129
- package/src/media/frame-rate.mjs +58 -58
- package/src/media/frame-time.mjs +22 -22
- package/src/media/preview-assets.mjs +350 -350
- package/src/media/probe.mjs +149 -149
- package/src/media/render-cuts.mjs +90 -90
- package/src/media/scene-detection.mjs +107 -107
- package/src/media/scene-review.mjs +205 -205
- package/src/project/assets.mjs +1194 -1194
- package/src/project/create.mjs +100 -100
- package/src/project/presets.mjs +44 -44
- package/src/render/checkpoints.mjs +192 -192
- package/src/render/formats.mjs +163 -163
- package/src/render/hyperframes.mjs +590 -590
- package/src/render/process.mjs +111 -111
- package/src/render/progress.mjs +46 -46
- package/src/render/timeline-control.mjs +53 -53
- package/src/timeline/assemble.mjs +119 -119
- package/src/timeline/audio-effects.mjs +75 -75
- package/src/timeline/audio-mastering.mjs +236 -236
- package/src/timeline/audio-mix.mjs +105 -105
- package/src/timeline/audio-track-effects.mjs +139 -139
- package/src/timeline/audio-volume.mjs +63 -63
- package/src/timeline/background.mjs +8 -8
- package/src/timeline/blend-mode.mjs +34 -34
- package/src/timeline/caption-layouts.mjs +62 -61
- package/src/timeline/captions.mjs +80 -80
- package/src/timeline/edit.mjs +965 -965
- package/src/timeline/fingerprint.mjs +6 -6
- package/src/timeline/from-edl.mjs +31 -31
- package/src/timeline/history-store.mjs +281 -281
- package/src/timeline/history.mjs +69 -69
- package/src/timeline/inspect.mjs +117 -117
- package/src/timeline/keyframes.mjs +158 -158
- package/src/timeline/layers.mjs +18 -18
- package/src/timeline/mask.mjs +53 -53
- package/src/timeline/project.mjs +52 -52
- package/src/timeline/render.mjs +759 -759
- package/src/timeline/sidechain-render.mjs +209 -209
- package/src/timeline/source-fit.mjs +15 -15
- package/src/timeline/speech-bubble.mjs +26 -26
- package/src/timeline/speed-ramp.mjs +188 -188
- package/src/timeline/track-state.mjs +22 -22
- package/src/timeline/transition.mjs +34 -34
- package/src/timeline/validate.mjs +322 -322
- package/src/transcript/corrections.mjs +21 -21
- package/src/transcript/normalize.mjs +17 -17
- package/src/transcript/provider.mjs +42 -42
- package/src/transcript/subtitles.mjs +57 -57
- package/src/transcript/validate.mjs +39 -39
package/docs/architecture.md
CHANGED
|
@@ -1,401 +1,401 @@
|
|
|
1
|
-
# Architecture
|
|
2
|
-
|
|
3
|
-
## What to carry forward
|
|
4
|
-
|
|
5
|
-
Herk Edit Kit demonstrates a useful editing sequence: preserve source media,
|
|
6
|
-
transcribe into word-level timestamps, propose cuts, review decisions, retime
|
|
7
|
-
the transcript, compose visuals, then lint, preview, and inspect a draft before
|
|
8
|
-
rendering the final output. Its local HyperFrames and GSAP workflow also gives
|
|
9
|
-
this project a concrete renderer to build around.
|
|
10
|
-
|
|
11
|
-
We will implement the workflow independently. No source files, skills, card
|
|
12
|
-
library, brand assets, footage, or examples are copied into this repository.
|
|
13
|
-
If a future change ports or adapts upstream material, review its license and
|
|
14
|
-
third-party notices first and preserve the required attribution.
|
|
15
|
-
|
|
16
|
-
## Improvement targets
|
|
17
|
-
|
|
18
|
-
1. **Provider-neutral transcription:** one normalized transcript contract, with
|
|
19
|
-
provider-specific adapters and a local option.
|
|
20
|
-
2. **Traceable edits:** every cut keeps original source times and a reason; all
|
|
21
|
-
derived media and transcript timings identify the EDL used to produce them.
|
|
22
|
-
3. **Safer defaults:** never overwrite source media; require an explicit review
|
|
23
|
-
artifact before applying proposed content cuts; keep credentials and personal
|
|
24
|
-
media out of version control.
|
|
25
|
-
4. **Smaller reusable core:** separate media operations and validation from
|
|
26
|
-
assistant instructions, creative styles, and project examples.
|
|
27
|
-
5. **Verifiable output:** make machine checks catch structural and timing errors,
|
|
28
|
-
while keeping rendered audio and visual review as a human step.
|
|
29
|
-
6. **Agent-readable state:** expose a deterministic read-only summary of the
|
|
30
|
-
project, media, tracks, and clip timing before an editing agent proposes
|
|
31
|
-
changes.
|
|
32
|
-
|
|
33
|
-
These targets define this repository's engine scope. Consumer products, plugins,
|
|
34
|
-
image editing, asset-generation marketplaces, and large bundled style libraries
|
|
35
|
-
belong elsewhere.
|
|
36
|
-
|
|
37
|
-
New projects include a validated empty timeline initialized from project
|
|
38
|
-
dimensions, frame rate, duration, source-fit policy, and registered asset
|
|
39
|
-
metadata. Existing projects can create the same timeline through the CLI or
|
|
40
|
-
`createProjectTimeline` API. The default track scaffold contains video, audio,
|
|
41
|
-
and overlay tracks; consumers can add or remove tracks through normal edit
|
|
42
|
-
operations.
|
|
43
|
-
|
|
44
|
-
## OpenTimelineIO interchange boundary
|
|
45
|
-
|
|
46
|
-
The optional `src/interchange/otio.mjs` module invokes a small Python bridge
|
|
47
|
-
that uses the maintained OpenTimelineIO library and its native `otio_json`
|
|
48
|
-
adapter. This keeps OTIO parsing and serialization out of hand-written Node
|
|
49
|
-
code and keeps Python/OpenTimelineIO optional for consumers that do not use
|
|
50
|
-
interchange. The pinned optional dependency is in `requirements-otio.txt`.
|
|
51
|
-
|
|
52
|
-
The interchange profile maps external media references, video/audio tracks,
|
|
53
|
-
nested track stacks and nested compositions inside tracks (flattened into
|
|
54
|
-
ordered Engine tracks), clips, gaps, root-stack review markers, track enabled
|
|
55
|
-
state, clip enabled state, and project duration including trailing gaps. Import
|
|
56
|
-
expands standard `SMPTE_Dissolve` transitions into overlapping
|
|
57
|
-
Engine clips with video opacity fades or audio crossfades. It supports
|
|
58
|
-
constant-rate `LinearTimeWarp` retiming and trimmed track/stack ranges when
|
|
59
|
-
their boundaries preserve complete transitions. It rejects variable speed
|
|
60
|
-
ramps, retimed crossfades, nested or combined stack trims, custom transition
|
|
61
|
-
types, other overlaps, effects, nested-composition trims combined with parent
|
|
62
|
-
track trims, non-file remote references, and missing media instead of silently
|
|
63
|
-
changing their meaning. Export converts explicitly faded two-clip overlaps to
|
|
64
|
-
standard `SMPTE_Dissolve` transitions. Unmarked or
|
|
65
|
-
chained overlaps, standalone fades, clip-edge transitions, and variable speed
|
|
66
|
-
ramps are rejected instead of silently changing their meaning. Track-level
|
|
67
|
-
audio effects and volume automation are also refused on export because the profile does not
|
|
68
|
-
map them to standard OTIO effects. The full Engine timeline is carried in
|
|
69
|
-
namespaced OTIO metadata so Engine-specific overlays and settings can survive
|
|
70
|
-
an Engine-to-OTIO-to-Engine round trip. Other editors may discard unknown
|
|
71
|
-
metadata, so this is not a cross-editor preservation guarantee. OTIO references
|
|
72
|
-
media paths and does not package the media files.
|
|
73
|
-
|
|
74
|
-
## Phase 1 capability audit (2026-11-05)
|
|
75
|
-
|
|
76
|
-
The table separates what the local checkout implements from what reference
|
|
77
|
-
project documentation says it does. Reference claims are not local verification.
|
|
78
|
-
|
|
79
|
-
| Capability | Engine local checkout | Herk Edit Kit reference | Free247Editor reference |
|
|
80
|
-
| --- | --- | --- | --- |
|
|
81
|
-
| Media inspection | Implemented with ffprobe | Uses FFmpeg-based workflow | Requires FFmpeg; setup checks tools |
|
|
82
|
-
| Transcript timing | Normalize/import and HyperFrames transcription wrapper | Word timing and transcript-driven workflow | Groq or faster-whisper routes advertised |
|
|
83
|
-
| Edit decisions | Silence-gap proposals, repeated-word candidates, validated EDL and retiming | Silence/mistake cutting and reviewed EDL workflow | Describes dead air, breaths, false starts, and retake cuts |
|
|
84
|
-
| Cut/render pipeline | FFmpeg cut helper plus EDL-to-timeline MP4 orchestration | Integrated agent workflow | README says it installs a pinned Herk Edit Kit under `kit/` |
|
|
85
|
-
| Composition/motion | HyperFrames project render wrapper; GSAP starter | HyperFrames, GSAP, reusable motion cards/templates | Attributes motion graphics to HyperFrames + GSAP through Herk |
|
|
86
|
-
| Captions/B-roll/audio design | EDL-to-MP4, timed text, still/video layers, gain/fades/clip-timing ducking; no automatic B-roll selection | Workflow includes captions, B-roll, music/SFX, review | README advertises word-level captions, B-roll, SFX/music, camera reframing |
|
|
87
|
-
| Consumer interface | Local Node ESM API and private CLI binary | Agent skills orchestrate kit tools | Agent skill orchestrates bundled/pinned Herk kit |
|
|
88
|
-
| Avatar speech | Consumer-owned; studios can generate avatar layers as timed image clips on generic video tracks | Talking Explainer is a separate reference, not a Herk core requirement | Not a core editor capability |
|
|
89
|
-
| Platform evidence | Windows checkout only; do not infer universal support | README documents Windows/macOS/Linux requirements; not independently tested here | README reports Windows 11 test; macOS/Linux are stated but untested |
|
|
90
|
-
|
|
91
|
-
**Audit conclusion:** The Engine now provides a shared timeline schema,
|
|
92
|
-
validation, CLI/API, media registration, EDL conversion, transcript-to-caption
|
|
93
|
-
assembly, a HyperFrames renderer, and basic audio mix automation. Visual
|
|
94
|
-
effects breadth, cross-platform coverage, and full audiovisual quality review
|
|
95
|
-
remain open. Skills, personal style/rules,
|
|
96
|
-
explainer storyboards, and owned avatar art remain consumer concerns. Studio
|
|
97
|
-
can call reusable Engine operations while retaining its chat approvals and
|
|
98
|
-
creative direction.
|
|
99
|
-
|
|
100
|
-
**License/provenance note:** the Herk repository identifies its project
|
|
101
|
-
license as MIT and lists separate third-party notices; each included
|
|
102
|
-
dependency/asset retains its own terms. Free247Editor identifies itself as MIT
|
|
103
|
-
and describes downloading a pinned Herk kit rather than copying it into its
|
|
104
|
-
own engine source. This Engine will implement its own contracts and code; do
|
|
105
|
-
not copy either project's skills, assets, templates, or code during the audit
|
|
106
|
-
or implementation without a provenance and license review.
|
|
107
|
-
|
|
108
|
-
## Proposed generic project and timeline contract
|
|
109
|
-
|
|
110
|
-
The first contract is intentionally small and renderer-neutral. JSON examples
|
|
111
|
-
will be checked into docs only after the validator and CLI/API land.
|
|
112
|
-
|
|
113
|
-
- `schemaVersion`: integer for explicit compatibility and migrations.
|
|
114
|
-
- `project`: stable id, width, height, frame rate, duration in seconds, and an
|
|
115
|
-
optional validated background color. New projects default to `#10141c`,
|
|
116
|
-
while legacy timelines without a color retain the renderer's black
|
|
117
|
-
background; `null` means transparent for overlay workflows.
|
|
118
|
-
- `assets`: stable ids and project-relative media paths; probe metadata is
|
|
119
|
-
derived and records streams, duration, dimensions, average and nominal frame
|
|
120
|
-
rates, per-stream timing, and codecs. A/V records preserve container aliases,
|
|
121
|
-
metadata for every video stream, and metadata for every audio stream. When
|
|
122
|
-
the container duration is absent, probing falls back to the longest valid
|
|
123
|
-
stream duration, deriving seconds from `duration_ts × time_base` when needed;
|
|
124
|
-
media with no usable duration remains invalid. Asset verification compares SHA-256
|
|
125
|
-
identities, while relinking replaces media under the same stable id/path and
|
|
126
|
-
refreshes its probe record without modifying the replacement source.
|
|
127
|
-
Optional video-only H.264 proxies retain their own dimensions, stream timing,
|
|
128
|
-
settings, and source/output SHA-256 identities. Draft renders can explicitly
|
|
129
|
-
select those variants; audio and default final renders continue using source
|
|
130
|
-
assets.
|
|
131
|
-
- `tracks`: ordered tracks with stable ids and kinds (`video`, `audio`,
|
|
132
|
-
`overlay`), plus explicit z-order, optional video/overlay visibility, audio
|
|
133
|
-
mute/solo state, and a lock that prevents edits to track contents/settings.
|
|
134
|
-
- `clips`: stable id, asset reference, source in/out, timeline start, and
|
|
135
|
-
optional placement/fit, constant `playbackRate`, source-relative `speedRamp`,
|
|
136
|
-
or reverse playback on video and audio clips,
|
|
137
|
-
volume, and composition reference. A speed ramp has linear or named eased
|
|
138
|
-
`playbackRate` interpolation between `{ sourceOffset, playbackRate, ease? }`
|
|
139
|
-
points covering the full clip source span; the optional ease controls the
|
|
140
|
-
outgoing segment. Its timeline duration is the integral of source time
|
|
141
|
-
divided by playback rate. Eased curves are sampled into bounded linear
|
|
142
|
-
segments for rendering. Constant-rate clips use source span = clip duration
|
|
143
|
-
× playback rate. All times are seconds; renderers quantize to project frames
|
|
144
|
-
in one documented step.
|
|
145
|
-
- `keyframes`: optional clip-local visual states on video and overlay clips.
|
|
146
|
-
Normalized x/y/width/height, opacity, rotation, brightness, contrast,
|
|
147
|
-
object-position, 1×–4× video zoom, saturation, blur, and hue interpolate
|
|
148
|
-
through GSAP. Zoom scales media inside its fixed, clipped viewport;
|
|
149
|
-
allowlisted easing controls each segment. Per-property easing ranges preserve
|
|
150
|
-
the curve when a clip is trimmed or split inside a tween. The first key must
|
|
151
|
-
be at time zero, geometry must remain within the canvas, and opacity keyframes
|
|
152
|
-
cannot overlap the separate clip-fade controls.
|
|
153
|
-
- `mask`: optional clip-path mask on video and overlay clips. Version 1 supports
|
|
154
|
-
normalized `circle`, `ellipse`, and `rect` shapes; `maskProgress` keyframes
|
|
155
|
-
animate the configured shape between closed and full bounds. Shape fields are
|
|
156
|
-
validated and compiled to CSS; raw CSS strings are not accepted.
|
|
157
|
-
- `blendMode`: optional allowlisted CSS compositing mode on video and overlay
|
|
158
|
-
clips. Modes blend the clip against lower visual layers within an isolated
|
|
159
|
-
project canvas; arbitrary CSS and audio-track use are rejected.
|
|
160
|
-
- `transitionIn` and `transitionOut`: optional version-1 `fade` or directional
|
|
161
|
-
`wipe` transitions on video and overlay clips. Their durations cannot overlap;
|
|
162
|
-
wipes cannot share a static mask, and fades cannot share opacity animation.
|
|
163
|
-
- `audioMix`: optional clip-timing ducking and signal-aware sidechain rules
|
|
164
|
-
between audio tracks. Timing ducking combines with track/clip gain and fades
|
|
165
|
-
in one volume envelope. Signal-aware rules build temporary detector stems
|
|
166
|
-
from source track clips and create temporary compressed target audio clips;
|
|
167
|
-
all generated media is removed after render.
|
|
168
|
-
- `audioEffects`: optional ordered per-clip equalizer, high-pass, low-pass,
|
|
169
|
-
compressor, stereo-balance, and noise-reduction effects on audio tracks.
|
|
170
|
-
Audio tracks can also define an ordered track-level chain. Clip effects run
|
|
171
|
-
first; track clips are then mixed to a temporary stem and the track effects
|
|
172
|
-
run across the full stem. Required FFmpeg filters for clip/track effects,
|
|
173
|
-
sidechain, and mastering are included in capability discovery and checked
|
|
174
|
-
before rendering.
|
|
175
|
-
- `volumeKeyframes`: optional, clip-relative audio gain automation with linear
|
|
176
|
-
interpolation and a held final value. Time 0 is required; trim, split, and
|
|
177
|
-
synchronized timeline operations rebase and preserve the curve.
|
|
178
|
-
- Audio tracks can also define `volumeKeyframes` in project time. The curve is
|
|
179
|
-
multiplied with static track/clip gain and clip automation; gap insertion and
|
|
180
|
-
ripple deletion preserve its shape relative to edited timeline content.
|
|
181
|
-
- `audioMastering`: optional final-mix integrated loudness, true-peak ceiling,
|
|
182
|
-
and loudness-range targets. FFmpeg `loudnorm` uses measured two-pass mode
|
|
183
|
-
when possible, dynamic single-pass mode for unmeasurable non-silent input,
|
|
184
|
-
and preserves valid silent tracks without a loudness filter. Optional
|
|
185
|
-
parametric equalizer bands run before analysis/normalization, and an optional
|
|
186
|
-
sample-peak limiter runs at the end of the final mix chain. Consumers can
|
|
187
|
-
request mono or stereo output and the encoded channel count is verified.
|
|
188
|
-
- `overlays`: timed composition references with validated duration and layer
|
|
189
|
-
order. Text/caption semantics live in composition data, not in a Studio-only
|
|
190
|
-
field.
|
|
191
|
-
- `markers`: optional project-time review/chapter points with stable ids,
|
|
192
|
-
labels, and optional display colors. Markers are non-rendering and are retimed
|
|
193
|
-
by synchronized gap insertion and ripple deletion. OpenTimelineIO interchange
|
|
194
|
-
maps them to root-stack markers; other formats may drop them.
|
|
195
|
-
- `lineage`: optional transcript/EDL references and source identities so
|
|
196
|
-
transcript edits can compile into the same timeline.
|
|
197
|
-
|
|
198
|
-
Validation rejects missing assets, paths escaping the project when assets are
|
|
199
|
-
project-managed, non-finite or negative times, invalid source ranges, timeline
|
|
200
|
-
clips beyond project duration, source ranges beyond known registered media
|
|
201
|
-
duration, mismatches between source span and constant-rate or integrated
|
|
202
|
-
speed-ramp duration,
|
|
203
|
-
unknown track kinds, and duplicate ids. A non-default media playback rate is
|
|
204
|
-
rendered through a temporary FFmpeg proxy that is removed after render; video
|
|
205
|
-
proxy encoding and pitch-preserving audio `atempo` are explicit costs. Eased
|
|
206
|
-
audio speed ramps use FFmpeg's optional `rubberband` filter to preserve pitch;
|
|
207
|
-
rendering such a ramp fails with an actionable error when the filter is absent.
|
|
208
|
-
Reverse video and audio playback use an FFmpeg temporary proxy for the selected
|
|
209
|
-
source range. They can combine with a constant playback rate, but not a speed
|
|
210
|
-
ramp; image assets cannot be reversed. FFmpeg's reverse filters buffer the
|
|
211
|
-
selected clip, so memory use grows with clip duration and resolution. Trim and
|
|
212
|
-
split operations preserve the reverse source direction. Detaching audio from a
|
|
213
|
-
reversed video clip copies the reverse setting to the audio clip. OTIO export
|
|
214
|
-
rejects reverse playback rather than silently dropping it.
|
|
215
|
-
Capability discovery reports the `reverse` and `areverse` filters, and render
|
|
216
|
-
preflight checks the specific filter required by a reversed track before the
|
|
217
|
-
renderer creates temporary media.
|
|
218
|
-
If a linked video's audio stream has a material start or
|
|
219
|
-
duration offset, the renderer creates a temporary FFmpeg-normalized audio file
|
|
220
|
-
for the composition and removes it afterward; source media stays unchanged. Overlap
|
|
221
|
-
is allowed within a track only when explicitly represented; tracks define
|
|
222
|
-
compositing order. Existing schemaVersion 1 transcript and EDL contracts stay
|
|
223
|
-
supported and can be compiled into the timeline model.
|
|
224
|
-
|
|
225
|
-
Consumers use the same operations through CLI and JavaScript exports. Timeline
|
|
226
|
-
operations include validation, EDL assembly, track/clip add and remove, track
|
|
227
|
-
locks, trim, slip, split, move, synchronized gap insertion and clip/range ripple
|
|
228
|
-
deletion, crossfade, registered-asset replacement, reviewable speed changes,
|
|
229
|
-
versioned fade/wipe transitions, reviewable visual framing and keyframe changes,
|
|
230
|
-
track visibility/mute/solo/lock/volume changes, caption generation, and rendering.
|
|
231
|
-
Reviewable audio clip gain/fade/stream selection, video stream selection, and
|
|
232
|
-
overlay content/style changes join this operation surface. Video stream
|
|
233
|
-
selection uses a zero-based video ordinal and compiles to a temporary clip
|
|
234
|
-
proxy, preserving the original asset. `set-audio-mix` and
|
|
235
|
-
`set-audio-mastering` expose validated reviewable changes for timeline-level
|
|
236
|
-
mix rules and final-mix settings. `set-project-state` can change timeline
|
|
237
|
-
duration and project-wide source fitting while keeping width, height, and frame
|
|
238
|
-
rate consistent with Engine project metadata.
|
|
239
|
-
Consumers can wrap immutable edits in bounded in-memory undo/redo history that returns
|
|
240
|
-
isolated snapshots and drops redo entries after a new branch of edits. CLI agents
|
|
241
|
-
can also use persistent timeline-file history across process invocations. It
|
|
242
|
-
stores bounded snapshots in an atomic sidecar journal, recovers an interrupted
|
|
243
|
-
timeline write, and refuses to overwrite a timeline modified outside the
|
|
244
|
-
history session until the user resets that session. A lock serializes history
|
|
245
|
-
updates and stale locks from exited processes are cleared. Crossfades configure GSAP opacity or
|
|
246
|
-
audio-volume fades on a validated, caller-positioned clip overlap. Video and
|
|
247
|
-
overlay clips can animate normalized placement, size, opacity, rotation, and
|
|
248
|
-
CSS visual filters with clip-local keyframes. Rendering compiles video clips, audio
|
|
249
|
-
tracks, text overlays, and timed compositions into a HyperFrames project before
|
|
250
|
-
draft/standard/high rendering. MP4, WebM, MOV, and GIF file exports are accepted
|
|
251
|
-
by extension; PNG sequences are requested explicitly. GIF and PNG sequences are
|
|
252
|
-
rejected for timelines with audio. PNG sequences are written as validated
|
|
253
|
-
full-resolution RGBA frame directories.
|
|
254
|
-
|
|
255
|
-
Injected transcription and media-analysis providers are generic JavaScript
|
|
256
|
-
adapters. Transcript output is normalized to the source duration. Media
|
|
257
|
-
findings are returned as time-validated suggestions for review and are not
|
|
258
|
-
automatically converted into timeline edits. Provider credentials remain in
|
|
259
|
-
consumer code and are not stored in project metadata.
|
|
260
|
-
Rational project frame rates are passed to
|
|
261
|
-
the renderer and checked in the output. MP4, MOV, and WebM renders can override
|
|
262
|
-
the quality preset with validated codec, CRF, or target video bitrate options.
|
|
263
|
-
Explicit codec overrides are applied by a final FFmpeg encode and the output
|
|
264
|
-
codec is checked before publishing the file. Render options can bound capture
|
|
265
|
-
workers from 1 to 64, select HyperFrames low-memory mode, and set a bounded
|
|
266
|
-
render timeout that also applies to the explicit-codec FFmpeg stage. The async
|
|
267
|
-
render APIs accept an `AbortSignal`; the CLI maps Ctrl+C to process-tree
|
|
268
|
-
cancellation. `renderTimelineAsync` applies one deadline to FFmpeg/ffprobe
|
|
269
|
-
preprocessing, HyperFrames, final encoding, output probing, and audio mastering.
|
|
270
|
-
Timeout and cancellation remove Engine and HyperFrames temporary outputs and
|
|
271
|
-
roll back timeline metadata. The async timeline renderer uses cancellable
|
|
272
|
-
FFmpeg/ffprobe child processes for media preparation and mastering, so timeout
|
|
273
|
-
and external abort signals terminate the active process tree.
|
|
274
|
-
Color profiles can request Rec.709, Rec.2020 SDR, or HDR10. HDR10 export is an
|
|
275
|
-
SDR-to-HDR conversion for MP4/MOV: it maps the Rec.709 render to 10-bit
|
|
276
|
-
BT.2020/PQ at a 203-nit reference white and requires FFmpeg `zscale` plus
|
|
277
|
-
`libx265` Main 10. This changes the transfer function and encoding precision;
|
|
278
|
-
it cannot recreate highlight information absent from the SDR render.
|
|
279
|
-
The async renderer can preserve a completed HyperFrames capture for retrying
|
|
280
|
-
the final stage. Checkpoints are content-fingerprinted, SHA-256 verified,
|
|
281
|
-
bounded by per-capture size and expiration, and removed after success. An
|
|
282
|
-
interrupted browser capture starts over; this is stage-level recovery, not
|
|
283
|
-
frame-level continuation. PNG sequences and synchronous rendering are excluded.
|
|
284
|
-
The core validator does not require FFmpeg or a
|
|
285
|
-
browser. Schema changes require a version increment or an explicit
|
|
286
|
-
backward-compatible migration.
|
|
287
|
-
|
|
288
|
-
## Current implementation
|
|
289
|
-
|
|
290
|
-
```text
|
|
291
|
-
src/
|
|
292
|
-
transcript/ normalized word timing and validation
|
|
293
|
-
edits/ silence proposals, mistake candidates, EDL retiming
|
|
294
|
-
media/ FFmpeg/ffprobe process helpers
|
|
295
|
-
project/ isolated project generation
|
|
296
|
-
render/ HyperFrames lint, preview, transcription, and render
|
|
297
|
-
cli.mjs command-line interface
|
|
298
|
-
video-projects/ generated per-video workspaces
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
The engine creates projects at caller-selected dimensions, registers and
|
|
302
|
-
fingerprints media, imports or generates transcripts, proposes editable cuts,
|
|
303
|
-
applies approved EDLs, retimes transcripts, generates captions, and
|
|
304
|
-
lints/previews/renders HyperFrames compositions. The generated starter
|
|
305
|
-
composition is intentionally small; editing intelligence and user approval
|
|
306
|
-
stay outside the renderer.
|
|
307
|
-
|
|
308
|
-
Named social-video canvas presets are 9:16, 4:5, 1:1, and 16:9, with arbitrary
|
|
309
|
-
dimensions remaining supported. The registry is exposed through the JavaScript
|
|
310
|
-
API and CLI; project metadata records the selected preset id and resolved canvas
|
|
311
|
-
dimensions. Their platform mapping and default pixel dimensions are documented
|
|
312
|
-
in [`aspect-ratio-presets.md`](aspect-ratio-presets.md). A preset selects canvas
|
|
313
|
-
dimensions only; source fit/crop behavior stays an explicit rendering choice.
|
|
314
|
-
Source-fit modes are `contain`, `cover` (center crop), and `fill` (stretch),
|
|
315
|
-
with `contain` as the non-cropping default. Project policy may be overridden by
|
|
316
|
-
a video clip's `fit` value.
|
|
317
|
-
|
|
318
|
-
## Version 1 data contracts
|
|
319
|
-
|
|
320
|
-
Transcript JSON uses `schemaVersion: 1`, `durationSeconds`, and `words` with
|
|
321
|
-
`text`, `start`, and `end` fields. Times are seconds on the original media
|
|
322
|
-
timeline. Words must be ordered by start time and stay within the media duration.
|
|
323
|
-
Provider word intervals may overlap; the engine preserves those source timings
|
|
324
|
-
and their overlap when retiming. It does not infer which provider timestamp is
|
|
325
|
-
more accurate or force neighboring words apart.
|
|
326
|
-
Registered assets retain FFprobe container and per-stream start times and time
|
|
327
|
-
bases for diagnostics and downstream timing decisions. Use `secondsToFrame`,
|
|
328
|
-
`frameToSeconds`, or `snapTimeToFrame` for explicit output-frame rounding.
|
|
329
|
-
Variable-frame-rate source timestamps remain seconds-based and must not be
|
|
330
|
-
snapped to the project frame rate; broader VFR seek/render behavior remains a
|
|
331
|
-
validation item. When linked video/audio start times differ, or a standalone
|
|
332
|
-
audio stream starts after zero, the renderer creates and removes a temporary
|
|
333
|
-
timestamp-aligned audio proxy. Original assets remain untouched.
|
|
334
|
-
|
|
335
|
-
An approved EDL uses `schemaVersion: 1`, the same `sourceDurationSeconds`, and a
|
|
336
|
-
`cuts` array. Each cut has `sourceStart`, `sourceEnd`, and a non-empty `reason`.
|
|
337
|
-
Cuts must be ordered, non-overlapping, positive-duration intervals within the
|
|
338
|
-
source. A cut may fully contain a transcript word, removing it. It may not split
|
|
339
|
-
a word; cuts that touch only the beginning or end of a word are also rejected.
|
|
340
|
-
With overlapping word intervals, a cut that fully contains one word but only
|
|
341
|
-
partly intersects another is rejected because it would clip the latter word.
|
|
342
|
-
These checks prevent the retimed transcript from claiming that clipped speech
|
|
343
|
-
is intact.
|
|
344
|
-
|
|
345
|
-
The retimer verifies both contracts and matching source durations before writing
|
|
346
|
-
anything. It drops fully cut words and shifts retained timestamps by the removed
|
|
347
|
-
duration preceding each word. Source transcript and EDL files are never modified.
|
|
348
|
-
|
|
349
|
-
## Tool boundary
|
|
350
|
-
|
|
351
|
-
- Node.js owns the CLI, validation, orchestration, and file handling.
|
|
352
|
-
- FFmpeg and ffprobe handle media probing, cuts, and encoding.
|
|
353
|
-
- HyperFrames renders HTML compositions; its supported browser runtime is part
|
|
354
|
-
of the render environment.
|
|
355
|
-
- GSAP adds timeline animation to compositions; static compositions do not need it.
|
|
356
|
-
- Playwright is for browser automation and smoke checks, not required by the
|
|
357
|
-
transcript/EDL core or every render.
|
|
358
|
-
- Transcription providers are optional adapters; credentials never enter project
|
|
359
|
-
metadata, generated HTML, logs, or committed files.
|
|
360
|
-
|
|
361
|
-
## Runtime requirements by capability
|
|
362
|
-
|
|
363
|
-
| Capability | Requirements |
|
|
364
|
-
| --- | --- |
|
|
365
|
-
| Transcript and EDL validation/retiming | Node.js 22+; current code uses built-ins only |
|
|
366
|
-
| Probe, cut, and encode media | FFmpeg and ffprobe |
|
|
367
|
-
| Render HTML compositions | HyperFrames, FFmpeg, and the browser runtime supported by the pinned HyperFrames version |
|
|
368
|
-
| Animate compositions | GSAP, when the composition uses animation |
|
|
369
|
-
| Automated browser smoke checks | Playwright, when those checks are enabled |
|
|
370
|
-
| Generate a transcript | Optional cloud provider key, or a separately installed local transcription runtime and model |
|
|
371
|
-
| Reproducible container rendering | Docker, if selected for the render workflow |
|
|
372
|
-
|
|
373
|
-
The engine checks the tools needed by the requested operation. For example,
|
|
374
|
-
transcript retiming does not require FFmpeg, a browser, or API keys. `npm run
|
|
375
|
-
doctor` checks Node.js, FFmpeg, ffprobe, HyperFrames, and GSAP, then runs
|
|
376
|
-
HyperFrames' environment doctor for browser/render setup and optional local AI
|
|
377
|
-
runtimes. Consumers can query the versioned `getEngineCapabilities()` API or
|
|
378
|
-
`aivee capabilities` CLI command to discover required tools, common
|
|
379
|
-
FFmpeg demuxers and decoders for common input media, encoders, output formats,
|
|
380
|
-
detected codec/per-format color-profile support, predefined canvas presets,
|
|
381
|
-
canvas background support and its accepted values, and optional render filters
|
|
382
|
-
without relying on doctor output parsing. Input
|
|
383
|
-
`available` reports whether FFmpeg and ffprobe are installed; `inventoryChecked`
|
|
384
|
-
reports whether the decoder and demuxer lists could be read. Container and
|
|
385
|
-
decoder fields are independent checks; having both does not prove that every
|
|
386
|
-
media stream combination will decode. Format availability reflects the relevant local FFmpeg,
|
|
387
|
-
ffprobe, HyperFrames, encoder, and filter inventory. The browser runtime is
|
|
388
|
-
reported as unchecked and must be verified with `npm run doctor`. The report
|
|
389
|
-
marks a format available when its render runtime and at least one compatible
|
|
390
|
-
encoder are present; `defaultCodecAvailable` indicates whether the default
|
|
391
|
-
encoder is installed. It does not guarantee that every input codec or
|
|
392
|
-
media-specific render operation is supported.
|
|
393
|
-
For operation-specific input checks, the JavaScript API exposes
|
|
394
|
-
`listFfmpegDecoders()`, `listFfmpegDemuxers()`, their boolean `has` helpers, and
|
|
395
|
-
their throwing `assert` helpers. `inspectMediaCompatibility(path)` probes a
|
|
396
|
-
source and checks its container plus every reported audio/video stream against
|
|
397
|
-
the local FFmpeg inventory before ingest; it does not decode the full file.
|
|
398
|
-
|
|
399
|
-
Pinned package versions are an initial baseline from the installed Herk Edit Kit
|
|
400
|
-
setup, not a promise of compatibility with future releases. Recheck versions and
|
|
401
|
-
licenses before upgrades or distributing a build.
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
## What to carry forward
|
|
4
|
+
|
|
5
|
+
Herk Edit Kit demonstrates a useful editing sequence: preserve source media,
|
|
6
|
+
transcribe into word-level timestamps, propose cuts, review decisions, retime
|
|
7
|
+
the transcript, compose visuals, then lint, preview, and inspect a draft before
|
|
8
|
+
rendering the final output. Its local HyperFrames and GSAP workflow also gives
|
|
9
|
+
this project a concrete renderer to build around.
|
|
10
|
+
|
|
11
|
+
We will implement the workflow independently. No source files, skills, card
|
|
12
|
+
library, brand assets, footage, or examples are copied into this repository.
|
|
13
|
+
If a future change ports or adapts upstream material, review its license and
|
|
14
|
+
third-party notices first and preserve the required attribution.
|
|
15
|
+
|
|
16
|
+
## Improvement targets
|
|
17
|
+
|
|
18
|
+
1. **Provider-neutral transcription:** one normalized transcript contract, with
|
|
19
|
+
provider-specific adapters and a local option.
|
|
20
|
+
2. **Traceable edits:** every cut keeps original source times and a reason; all
|
|
21
|
+
derived media and transcript timings identify the EDL used to produce them.
|
|
22
|
+
3. **Safer defaults:** never overwrite source media; require an explicit review
|
|
23
|
+
artifact before applying proposed content cuts; keep credentials and personal
|
|
24
|
+
media out of version control.
|
|
25
|
+
4. **Smaller reusable core:** separate media operations and validation from
|
|
26
|
+
assistant instructions, creative styles, and project examples.
|
|
27
|
+
5. **Verifiable output:** make machine checks catch structural and timing errors,
|
|
28
|
+
while keeping rendered audio and visual review as a human step.
|
|
29
|
+
6. **Agent-readable state:** expose a deterministic read-only summary of the
|
|
30
|
+
project, media, tracks, and clip timing before an editing agent proposes
|
|
31
|
+
changes.
|
|
32
|
+
|
|
33
|
+
These targets define this repository's engine scope. Consumer products, plugins,
|
|
34
|
+
image editing, asset-generation marketplaces, and large bundled style libraries
|
|
35
|
+
belong elsewhere.
|
|
36
|
+
|
|
37
|
+
New projects include a validated empty timeline initialized from project
|
|
38
|
+
dimensions, frame rate, duration, source-fit policy, and registered asset
|
|
39
|
+
metadata. Existing projects can create the same timeline through the CLI or
|
|
40
|
+
`createProjectTimeline` API. The default track scaffold contains video, audio,
|
|
41
|
+
and overlay tracks; consumers can add or remove tracks through normal edit
|
|
42
|
+
operations.
|
|
43
|
+
|
|
44
|
+
## OpenTimelineIO interchange boundary
|
|
45
|
+
|
|
46
|
+
The optional `src/interchange/otio.mjs` module invokes a small Python bridge
|
|
47
|
+
that uses the maintained OpenTimelineIO library and its native `otio_json`
|
|
48
|
+
adapter. This keeps OTIO parsing and serialization out of hand-written Node
|
|
49
|
+
code and keeps Python/OpenTimelineIO optional for consumers that do not use
|
|
50
|
+
interchange. The pinned optional dependency is in `requirements-otio.txt`.
|
|
51
|
+
|
|
52
|
+
The interchange profile maps external media references, video/audio tracks,
|
|
53
|
+
nested track stacks and nested compositions inside tracks (flattened into
|
|
54
|
+
ordered Engine tracks), clips, gaps, root-stack review markers, track enabled
|
|
55
|
+
state, clip enabled state, and project duration including trailing gaps. Import
|
|
56
|
+
expands standard `SMPTE_Dissolve` transitions into overlapping
|
|
57
|
+
Engine clips with video opacity fades or audio crossfades. It supports
|
|
58
|
+
constant-rate `LinearTimeWarp` retiming and trimmed track/stack ranges when
|
|
59
|
+
their boundaries preserve complete transitions. It rejects variable speed
|
|
60
|
+
ramps, retimed crossfades, nested or combined stack trims, custom transition
|
|
61
|
+
types, other overlaps, effects, nested-composition trims combined with parent
|
|
62
|
+
track trims, non-file remote references, and missing media instead of silently
|
|
63
|
+
changing their meaning. Export converts explicitly faded two-clip overlaps to
|
|
64
|
+
standard `SMPTE_Dissolve` transitions. Unmarked or
|
|
65
|
+
chained overlaps, standalone fades, clip-edge transitions, and variable speed
|
|
66
|
+
ramps are rejected instead of silently changing their meaning. Track-level
|
|
67
|
+
audio effects and volume automation are also refused on export because the profile does not
|
|
68
|
+
map them to standard OTIO effects. The full Engine timeline is carried in
|
|
69
|
+
namespaced OTIO metadata so Engine-specific overlays and settings can survive
|
|
70
|
+
an Engine-to-OTIO-to-Engine round trip. Other editors may discard unknown
|
|
71
|
+
metadata, so this is not a cross-editor preservation guarantee. OTIO references
|
|
72
|
+
media paths and does not package the media files.
|
|
73
|
+
|
|
74
|
+
## Phase 1 capability audit (2026-11-05)
|
|
75
|
+
|
|
76
|
+
The table separates what the local checkout implements from what reference
|
|
77
|
+
project documentation says it does. Reference claims are not local verification.
|
|
78
|
+
|
|
79
|
+
| Capability | Engine local checkout | Herk Edit Kit reference | Free247Editor reference |
|
|
80
|
+
| --- | --- | --- | --- |
|
|
81
|
+
| Media inspection | Implemented with ffprobe | Uses FFmpeg-based workflow | Requires FFmpeg; setup checks tools |
|
|
82
|
+
| Transcript timing | Normalize/import and HyperFrames transcription wrapper | Word timing and transcript-driven workflow | Groq or faster-whisper routes advertised |
|
|
83
|
+
| Edit decisions | Silence-gap proposals, repeated-word candidates, validated EDL and retiming | Silence/mistake cutting and reviewed EDL workflow | Describes dead air, breaths, false starts, and retake cuts |
|
|
84
|
+
| Cut/render pipeline | FFmpeg cut helper plus EDL-to-timeline MP4 orchestration | Integrated agent workflow | README says it installs a pinned Herk Edit Kit under `kit/` |
|
|
85
|
+
| Composition/motion | HyperFrames project render wrapper; GSAP starter | HyperFrames, GSAP, reusable motion cards/templates | Attributes motion graphics to HyperFrames + GSAP through Herk |
|
|
86
|
+
| Captions/B-roll/audio design | EDL-to-MP4, timed text, still/video layers, gain/fades/clip-timing ducking; no automatic B-roll selection | Workflow includes captions, B-roll, music/SFX, review | README advertises word-level captions, B-roll, SFX/music, camera reframing |
|
|
87
|
+
| Consumer interface | Local Node ESM API and private CLI binary | Agent skills orchestrate kit tools | Agent skill orchestrates bundled/pinned Herk kit |
|
|
88
|
+
| Avatar speech | Consumer-owned; studios can generate avatar layers as timed image clips on generic video tracks | Talking Explainer is a separate reference, not a Herk core requirement | Not a core editor capability |
|
|
89
|
+
| Platform evidence | Windows checkout only; do not infer universal support | README documents Windows/macOS/Linux requirements; not independently tested here | README reports Windows 11 test; macOS/Linux are stated but untested |
|
|
90
|
+
|
|
91
|
+
**Audit conclusion:** The Engine now provides a shared timeline schema,
|
|
92
|
+
validation, CLI/API, media registration, EDL conversion, transcript-to-caption
|
|
93
|
+
assembly, a HyperFrames renderer, and basic audio mix automation. Visual
|
|
94
|
+
effects breadth, cross-platform coverage, and full audiovisual quality review
|
|
95
|
+
remain open. Skills, personal style/rules,
|
|
96
|
+
explainer storyboards, and owned avatar art remain consumer concerns. Studio
|
|
97
|
+
can call reusable Engine operations while retaining its chat approvals and
|
|
98
|
+
creative direction.
|
|
99
|
+
|
|
100
|
+
**License/provenance note:** the Herk repository identifies its project
|
|
101
|
+
license as MIT and lists separate third-party notices; each included
|
|
102
|
+
dependency/asset retains its own terms. Free247Editor identifies itself as MIT
|
|
103
|
+
and describes downloading a pinned Herk kit rather than copying it into its
|
|
104
|
+
own engine source. This Engine will implement its own contracts and code; do
|
|
105
|
+
not copy either project's skills, assets, templates, or code during the audit
|
|
106
|
+
or implementation without a provenance and license review.
|
|
107
|
+
|
|
108
|
+
## Proposed generic project and timeline contract
|
|
109
|
+
|
|
110
|
+
The first contract is intentionally small and renderer-neutral. JSON examples
|
|
111
|
+
will be checked into docs only after the validator and CLI/API land.
|
|
112
|
+
|
|
113
|
+
- `schemaVersion`: integer for explicit compatibility and migrations.
|
|
114
|
+
- `project`: stable id, width, height, frame rate, duration in seconds, and an
|
|
115
|
+
optional validated background color. New projects default to `#10141c`,
|
|
116
|
+
while legacy timelines without a color retain the renderer's black
|
|
117
|
+
background; `null` means transparent for overlay workflows.
|
|
118
|
+
- `assets`: stable ids and project-relative media paths; probe metadata is
|
|
119
|
+
derived and records streams, duration, dimensions, average and nominal frame
|
|
120
|
+
rates, per-stream timing, and codecs. A/V records preserve container aliases,
|
|
121
|
+
metadata for every video stream, and metadata for every audio stream. When
|
|
122
|
+
the container duration is absent, probing falls back to the longest valid
|
|
123
|
+
stream duration, deriving seconds from `duration_ts × time_base` when needed;
|
|
124
|
+
media with no usable duration remains invalid. Asset verification compares SHA-256
|
|
125
|
+
identities, while relinking replaces media under the same stable id/path and
|
|
126
|
+
refreshes its probe record without modifying the replacement source.
|
|
127
|
+
Optional video-only H.264 proxies retain their own dimensions, stream timing,
|
|
128
|
+
settings, and source/output SHA-256 identities. Draft renders can explicitly
|
|
129
|
+
select those variants; audio and default final renders continue using source
|
|
130
|
+
assets.
|
|
131
|
+
- `tracks`: ordered tracks with stable ids and kinds (`video`, `audio`,
|
|
132
|
+
`overlay`), plus explicit z-order, optional video/overlay visibility, audio
|
|
133
|
+
mute/solo state, and a lock that prevents edits to track contents/settings.
|
|
134
|
+
- `clips`: stable id, asset reference, source in/out, timeline start, and
|
|
135
|
+
optional placement/fit, constant `playbackRate`, source-relative `speedRamp`,
|
|
136
|
+
or reverse playback on video and audio clips,
|
|
137
|
+
volume, and composition reference. A speed ramp has linear or named eased
|
|
138
|
+
`playbackRate` interpolation between `{ sourceOffset, playbackRate, ease? }`
|
|
139
|
+
points covering the full clip source span; the optional ease controls the
|
|
140
|
+
outgoing segment. Its timeline duration is the integral of source time
|
|
141
|
+
divided by playback rate. Eased curves are sampled into bounded linear
|
|
142
|
+
segments for rendering. Constant-rate clips use source span = clip duration
|
|
143
|
+
× playback rate. All times are seconds; renderers quantize to project frames
|
|
144
|
+
in one documented step.
|
|
145
|
+
- `keyframes`: optional clip-local visual states on video and overlay clips.
|
|
146
|
+
Normalized x/y/width/height, opacity, rotation, brightness, contrast,
|
|
147
|
+
object-position, 1×–4× video zoom, saturation, blur, and hue interpolate
|
|
148
|
+
through GSAP. Zoom scales media inside its fixed, clipped viewport;
|
|
149
|
+
allowlisted easing controls each segment. Per-property easing ranges preserve
|
|
150
|
+
the curve when a clip is trimmed or split inside a tween. The first key must
|
|
151
|
+
be at time zero, geometry must remain within the canvas, and opacity keyframes
|
|
152
|
+
cannot overlap the separate clip-fade controls.
|
|
153
|
+
- `mask`: optional clip-path mask on video and overlay clips. Version 1 supports
|
|
154
|
+
normalized `circle`, `ellipse`, and `rect` shapes; `maskProgress` keyframes
|
|
155
|
+
animate the configured shape between closed and full bounds. Shape fields are
|
|
156
|
+
validated and compiled to CSS; raw CSS strings are not accepted.
|
|
157
|
+
- `blendMode`: optional allowlisted CSS compositing mode on video and overlay
|
|
158
|
+
clips. Modes blend the clip against lower visual layers within an isolated
|
|
159
|
+
project canvas; arbitrary CSS and audio-track use are rejected.
|
|
160
|
+
- `transitionIn` and `transitionOut`: optional version-1 `fade` or directional
|
|
161
|
+
`wipe` transitions on video and overlay clips. Their durations cannot overlap;
|
|
162
|
+
wipes cannot share a static mask, and fades cannot share opacity animation.
|
|
163
|
+
- `audioMix`: optional clip-timing ducking and signal-aware sidechain rules
|
|
164
|
+
between audio tracks. Timing ducking combines with track/clip gain and fades
|
|
165
|
+
in one volume envelope. Signal-aware rules build temporary detector stems
|
|
166
|
+
from source track clips and create temporary compressed target audio clips;
|
|
167
|
+
all generated media is removed after render.
|
|
168
|
+
- `audioEffects`: optional ordered per-clip equalizer, high-pass, low-pass,
|
|
169
|
+
compressor, stereo-balance, and noise-reduction effects on audio tracks.
|
|
170
|
+
Audio tracks can also define an ordered track-level chain. Clip effects run
|
|
171
|
+
first; track clips are then mixed to a temporary stem and the track effects
|
|
172
|
+
run across the full stem. Required FFmpeg filters for clip/track effects,
|
|
173
|
+
sidechain, and mastering are included in capability discovery and checked
|
|
174
|
+
before rendering.
|
|
175
|
+
- `volumeKeyframes`: optional, clip-relative audio gain automation with linear
|
|
176
|
+
interpolation and a held final value. Time 0 is required; trim, split, and
|
|
177
|
+
synchronized timeline operations rebase and preserve the curve.
|
|
178
|
+
- Audio tracks can also define `volumeKeyframes` in project time. The curve is
|
|
179
|
+
multiplied with static track/clip gain and clip automation; gap insertion and
|
|
180
|
+
ripple deletion preserve its shape relative to edited timeline content.
|
|
181
|
+
- `audioMastering`: optional final-mix integrated loudness, true-peak ceiling,
|
|
182
|
+
and loudness-range targets. FFmpeg `loudnorm` uses measured two-pass mode
|
|
183
|
+
when possible, dynamic single-pass mode for unmeasurable non-silent input,
|
|
184
|
+
and preserves valid silent tracks without a loudness filter. Optional
|
|
185
|
+
parametric equalizer bands run before analysis/normalization, and an optional
|
|
186
|
+
sample-peak limiter runs at the end of the final mix chain. Consumers can
|
|
187
|
+
request mono or stereo output and the encoded channel count is verified.
|
|
188
|
+
- `overlays`: timed composition references with validated duration and layer
|
|
189
|
+
order. Text/caption semantics live in composition data, not in a Studio-only
|
|
190
|
+
field.
|
|
191
|
+
- `markers`: optional project-time review/chapter points with stable ids,
|
|
192
|
+
labels, and optional display colors. Markers are non-rendering and are retimed
|
|
193
|
+
by synchronized gap insertion and ripple deletion. OpenTimelineIO interchange
|
|
194
|
+
maps them to root-stack markers; other formats may drop them.
|
|
195
|
+
- `lineage`: optional transcript/EDL references and source identities so
|
|
196
|
+
transcript edits can compile into the same timeline.
|
|
197
|
+
|
|
198
|
+
Validation rejects missing assets, paths escaping the project when assets are
|
|
199
|
+
project-managed, non-finite or negative times, invalid source ranges, timeline
|
|
200
|
+
clips beyond project duration, source ranges beyond known registered media
|
|
201
|
+
duration, mismatches between source span and constant-rate or integrated
|
|
202
|
+
speed-ramp duration,
|
|
203
|
+
unknown track kinds, and duplicate ids. A non-default media playback rate is
|
|
204
|
+
rendered through a temporary FFmpeg proxy that is removed after render; video
|
|
205
|
+
proxy encoding and pitch-preserving audio `atempo` are explicit costs. Eased
|
|
206
|
+
audio speed ramps use FFmpeg's optional `rubberband` filter to preserve pitch;
|
|
207
|
+
rendering such a ramp fails with an actionable error when the filter is absent.
|
|
208
|
+
Reverse video and audio playback use an FFmpeg temporary proxy for the selected
|
|
209
|
+
source range. They can combine with a constant playback rate, but not a speed
|
|
210
|
+
ramp; image assets cannot be reversed. FFmpeg's reverse filters buffer the
|
|
211
|
+
selected clip, so memory use grows with clip duration and resolution. Trim and
|
|
212
|
+
split operations preserve the reverse source direction. Detaching audio from a
|
|
213
|
+
reversed video clip copies the reverse setting to the audio clip. OTIO export
|
|
214
|
+
rejects reverse playback rather than silently dropping it.
|
|
215
|
+
Capability discovery reports the `reverse` and `areverse` filters, and render
|
|
216
|
+
preflight checks the specific filter required by a reversed track before the
|
|
217
|
+
renderer creates temporary media.
|
|
218
|
+
If a linked video's audio stream has a material start or
|
|
219
|
+
duration offset, the renderer creates a temporary FFmpeg-normalized audio file
|
|
220
|
+
for the composition and removes it afterward; source media stays unchanged. Overlap
|
|
221
|
+
is allowed within a track only when explicitly represented; tracks define
|
|
222
|
+
compositing order. Existing schemaVersion 1 transcript and EDL contracts stay
|
|
223
|
+
supported and can be compiled into the timeline model.
|
|
224
|
+
|
|
225
|
+
Consumers use the same operations through CLI and JavaScript exports. Timeline
|
|
226
|
+
operations include validation, EDL assembly, track/clip add and remove, track
|
|
227
|
+
locks, trim, slip, split, move, synchronized gap insertion and clip/range ripple
|
|
228
|
+
deletion, crossfade, registered-asset replacement, reviewable speed changes,
|
|
229
|
+
versioned fade/wipe transitions, reviewable visual framing and keyframe changes,
|
|
230
|
+
track visibility/mute/solo/lock/volume changes, caption generation, and rendering.
|
|
231
|
+
Reviewable audio clip gain/fade/stream selection, video stream selection, and
|
|
232
|
+
overlay content/style changes join this operation surface. Video stream
|
|
233
|
+
selection uses a zero-based video ordinal and compiles to a temporary clip
|
|
234
|
+
proxy, preserving the original asset. `set-audio-mix` and
|
|
235
|
+
`set-audio-mastering` expose validated reviewable changes for timeline-level
|
|
236
|
+
mix rules and final-mix settings. `set-project-state` can change timeline
|
|
237
|
+
duration and project-wide source fitting while keeping width, height, and frame
|
|
238
|
+
rate consistent with Engine project metadata.
|
|
239
|
+
Consumers can wrap immutable edits in bounded in-memory undo/redo history that returns
|
|
240
|
+
isolated snapshots and drops redo entries after a new branch of edits. CLI agents
|
|
241
|
+
can also use persistent timeline-file history across process invocations. It
|
|
242
|
+
stores bounded snapshots in an atomic sidecar journal, recovers an interrupted
|
|
243
|
+
timeline write, and refuses to overwrite a timeline modified outside the
|
|
244
|
+
history session until the user resets that session. A lock serializes history
|
|
245
|
+
updates and stale locks from exited processes are cleared. Crossfades configure GSAP opacity or
|
|
246
|
+
audio-volume fades on a validated, caller-positioned clip overlap. Video and
|
|
247
|
+
overlay clips can animate normalized placement, size, opacity, rotation, and
|
|
248
|
+
CSS visual filters with clip-local keyframes. Rendering compiles video clips, audio
|
|
249
|
+
tracks, text overlays, and timed compositions into a HyperFrames project before
|
|
250
|
+
draft/standard/high rendering. MP4, WebM, MOV, and GIF file exports are accepted
|
|
251
|
+
by extension; PNG sequences are requested explicitly. GIF and PNG sequences are
|
|
252
|
+
rejected for timelines with audio. PNG sequences are written as validated
|
|
253
|
+
full-resolution RGBA frame directories.
|
|
254
|
+
|
|
255
|
+
Injected transcription and media-analysis providers are generic JavaScript
|
|
256
|
+
adapters. Transcript output is normalized to the source duration. Media
|
|
257
|
+
findings are returned as time-validated suggestions for review and are not
|
|
258
|
+
automatically converted into timeline edits. Provider credentials remain in
|
|
259
|
+
consumer code and are not stored in project metadata.
|
|
260
|
+
Rational project frame rates are passed to
|
|
261
|
+
the renderer and checked in the output. MP4, MOV, and WebM renders can override
|
|
262
|
+
the quality preset with validated codec, CRF, or target video bitrate options.
|
|
263
|
+
Explicit codec overrides are applied by a final FFmpeg encode and the output
|
|
264
|
+
codec is checked before publishing the file. Render options can bound capture
|
|
265
|
+
workers from 1 to 64, select HyperFrames low-memory mode, and set a bounded
|
|
266
|
+
render timeout that also applies to the explicit-codec FFmpeg stage. The async
|
|
267
|
+
render APIs accept an `AbortSignal`; the CLI maps Ctrl+C to process-tree
|
|
268
|
+
cancellation. `renderTimelineAsync` applies one deadline to FFmpeg/ffprobe
|
|
269
|
+
preprocessing, HyperFrames, final encoding, output probing, and audio mastering.
|
|
270
|
+
Timeout and cancellation remove Engine and HyperFrames temporary outputs and
|
|
271
|
+
roll back timeline metadata. The async timeline renderer uses cancellable
|
|
272
|
+
FFmpeg/ffprobe child processes for media preparation and mastering, so timeout
|
|
273
|
+
and external abort signals terminate the active process tree.
|
|
274
|
+
Color profiles can request Rec.709, Rec.2020 SDR, or HDR10. HDR10 export is an
|
|
275
|
+
SDR-to-HDR conversion for MP4/MOV: it maps the Rec.709 render to 10-bit
|
|
276
|
+
BT.2020/PQ at a 203-nit reference white and requires FFmpeg `zscale` plus
|
|
277
|
+
`libx265` Main 10. This changes the transfer function and encoding precision;
|
|
278
|
+
it cannot recreate highlight information absent from the SDR render.
|
|
279
|
+
The async renderer can preserve a completed HyperFrames capture for retrying
|
|
280
|
+
the final stage. Checkpoints are content-fingerprinted, SHA-256 verified,
|
|
281
|
+
bounded by per-capture size and expiration, and removed after success. An
|
|
282
|
+
interrupted browser capture starts over; this is stage-level recovery, not
|
|
283
|
+
frame-level continuation. PNG sequences and synchronous rendering are excluded.
|
|
284
|
+
The core validator does not require FFmpeg or a
|
|
285
|
+
browser. Schema changes require a version increment or an explicit
|
|
286
|
+
backward-compatible migration.
|
|
287
|
+
|
|
288
|
+
## Current implementation
|
|
289
|
+
|
|
290
|
+
```text
|
|
291
|
+
src/
|
|
292
|
+
transcript/ normalized word timing and validation
|
|
293
|
+
edits/ silence proposals, mistake candidates, EDL retiming
|
|
294
|
+
media/ FFmpeg/ffprobe process helpers
|
|
295
|
+
project/ isolated project generation
|
|
296
|
+
render/ HyperFrames lint, preview, transcription, and render
|
|
297
|
+
cli.mjs command-line interface
|
|
298
|
+
video-projects/ generated per-video workspaces
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
The engine creates projects at caller-selected dimensions, registers and
|
|
302
|
+
fingerprints media, imports or generates transcripts, proposes editable cuts,
|
|
303
|
+
applies approved EDLs, retimes transcripts, generates captions, and
|
|
304
|
+
lints/previews/renders HyperFrames compositions. The generated starter
|
|
305
|
+
composition is intentionally small; editing intelligence and user approval
|
|
306
|
+
stay outside the renderer.
|
|
307
|
+
|
|
308
|
+
Named social-video canvas presets are 9:16, 4:5, 1:1, and 16:9, with arbitrary
|
|
309
|
+
dimensions remaining supported. The registry is exposed through the JavaScript
|
|
310
|
+
API and CLI; project metadata records the selected preset id and resolved canvas
|
|
311
|
+
dimensions. Their platform mapping and default pixel dimensions are documented
|
|
312
|
+
in [`aspect-ratio-presets.md`](aspect-ratio-presets.md). A preset selects canvas
|
|
313
|
+
dimensions only; source fit/crop behavior stays an explicit rendering choice.
|
|
314
|
+
Source-fit modes are `contain`, `cover` (center crop), and `fill` (stretch),
|
|
315
|
+
with `contain` as the non-cropping default. Project policy may be overridden by
|
|
316
|
+
a video clip's `fit` value.
|
|
317
|
+
|
|
318
|
+
## Version 1 data contracts
|
|
319
|
+
|
|
320
|
+
Transcript JSON uses `schemaVersion: 1`, `durationSeconds`, and `words` with
|
|
321
|
+
`text`, `start`, and `end` fields. Times are seconds on the original media
|
|
322
|
+
timeline. Words must be ordered by start time and stay within the media duration.
|
|
323
|
+
Provider word intervals may overlap; the engine preserves those source timings
|
|
324
|
+
and their overlap when retiming. It does not infer which provider timestamp is
|
|
325
|
+
more accurate or force neighboring words apart.
|
|
326
|
+
Registered assets retain FFprobe container and per-stream start times and time
|
|
327
|
+
bases for diagnostics and downstream timing decisions. Use `secondsToFrame`,
|
|
328
|
+
`frameToSeconds`, or `snapTimeToFrame` for explicit output-frame rounding.
|
|
329
|
+
Variable-frame-rate source timestamps remain seconds-based and must not be
|
|
330
|
+
snapped to the project frame rate; broader VFR seek/render behavior remains a
|
|
331
|
+
validation item. When linked video/audio start times differ, or a standalone
|
|
332
|
+
audio stream starts after zero, the renderer creates and removes a temporary
|
|
333
|
+
timestamp-aligned audio proxy. Original assets remain untouched.
|
|
334
|
+
|
|
335
|
+
An approved EDL uses `schemaVersion: 1`, the same `sourceDurationSeconds`, and a
|
|
336
|
+
`cuts` array. Each cut has `sourceStart`, `sourceEnd`, and a non-empty `reason`.
|
|
337
|
+
Cuts must be ordered, non-overlapping, positive-duration intervals within the
|
|
338
|
+
source. A cut may fully contain a transcript word, removing it. It may not split
|
|
339
|
+
a word; cuts that touch only the beginning or end of a word are also rejected.
|
|
340
|
+
With overlapping word intervals, a cut that fully contains one word but only
|
|
341
|
+
partly intersects another is rejected because it would clip the latter word.
|
|
342
|
+
These checks prevent the retimed transcript from claiming that clipped speech
|
|
343
|
+
is intact.
|
|
344
|
+
|
|
345
|
+
The retimer verifies both contracts and matching source durations before writing
|
|
346
|
+
anything. It drops fully cut words and shifts retained timestamps by the removed
|
|
347
|
+
duration preceding each word. Source transcript and EDL files are never modified.
|
|
348
|
+
|
|
349
|
+
## Tool boundary
|
|
350
|
+
|
|
351
|
+
- Node.js owns the CLI, validation, orchestration, and file handling.
|
|
352
|
+
- FFmpeg and ffprobe handle media probing, cuts, and encoding.
|
|
353
|
+
- HyperFrames renders HTML compositions; its supported browser runtime is part
|
|
354
|
+
of the render environment.
|
|
355
|
+
- GSAP adds timeline animation to compositions; static compositions do not need it.
|
|
356
|
+
- Playwright is for browser automation and smoke checks, not required by the
|
|
357
|
+
transcript/EDL core or every render.
|
|
358
|
+
- Transcription providers are optional adapters; credentials never enter project
|
|
359
|
+
metadata, generated HTML, logs, or committed files.
|
|
360
|
+
|
|
361
|
+
## Runtime requirements by capability
|
|
362
|
+
|
|
363
|
+
| Capability | Requirements |
|
|
364
|
+
| --- | --- |
|
|
365
|
+
| Transcript and EDL validation/retiming | Node.js 22+; current code uses built-ins only |
|
|
366
|
+
| Probe, cut, and encode media | FFmpeg and ffprobe |
|
|
367
|
+
| Render HTML compositions | HyperFrames, FFmpeg, and the browser runtime supported by the pinned HyperFrames version |
|
|
368
|
+
| Animate compositions | GSAP, when the composition uses animation |
|
|
369
|
+
| Automated browser smoke checks | Playwright, when those checks are enabled |
|
|
370
|
+
| Generate a transcript | Optional cloud provider key, or a separately installed local transcription runtime and model |
|
|
371
|
+
| Reproducible container rendering | Docker, if selected for the render workflow |
|
|
372
|
+
|
|
373
|
+
The engine checks the tools needed by the requested operation. For example,
|
|
374
|
+
transcript retiming does not require FFmpeg, a browser, or API keys. `npm run
|
|
375
|
+
doctor` checks Node.js, FFmpeg, ffprobe, HyperFrames, and GSAP, then runs
|
|
376
|
+
HyperFrames' environment doctor for browser/render setup and optional local AI
|
|
377
|
+
runtimes. Consumers can query the versioned `getEngineCapabilities()` API or
|
|
378
|
+
`aivee capabilities` CLI command to discover required tools, common
|
|
379
|
+
FFmpeg demuxers and decoders for common input media, encoders, output formats,
|
|
380
|
+
detected codec/per-format color-profile support, predefined canvas presets,
|
|
381
|
+
canvas background support and its accepted values, and optional render filters
|
|
382
|
+
without relying on doctor output parsing. Input
|
|
383
|
+
`available` reports whether FFmpeg and ffprobe are installed; `inventoryChecked`
|
|
384
|
+
reports whether the decoder and demuxer lists could be read. Container and
|
|
385
|
+
decoder fields are independent checks; having both does not prove that every
|
|
386
|
+
media stream combination will decode. Format availability reflects the relevant local FFmpeg,
|
|
387
|
+
ffprobe, HyperFrames, encoder, and filter inventory. The browser runtime is
|
|
388
|
+
reported as unchecked and must be verified with `npm run doctor`. The report
|
|
389
|
+
marks a format available when its render runtime and at least one compatible
|
|
390
|
+
encoder are present; `defaultCodecAvailable` indicates whether the default
|
|
391
|
+
encoder is installed. It does not guarantee that every input codec or
|
|
392
|
+
media-specific render operation is supported.
|
|
393
|
+
For operation-specific input checks, the JavaScript API exposes
|
|
394
|
+
`listFfmpegDecoders()`, `listFfmpegDemuxers()`, their boolean `has` helpers, and
|
|
395
|
+
their throwing `assert` helpers. `inspectMediaCompatibility(path)` probes a
|
|
396
|
+
source and checks its container plus every reported audio/video stream against
|
|
397
|
+
the local FFmpeg inventory before ingest; it does not decode the full file.
|
|
398
|
+
|
|
399
|
+
Pinned package versions are an initial baseline from the installed Herk Edit Kit
|
|
400
|
+
setup, not a promise of compatibility with future releases. Recheck versions and
|
|
401
|
+
licenses before upgrades or distributing a build.
|