ef-timegroup
Attributes
modeRequiredstringDuration calculation mode
fixedsequencecontainfitdurationtimestringExplicit duration (for fixed mode)
overlaptimestringOverlap time between sequence items (e.g., "1s")
fpsnumberFrame rate for rendering
30auto-initbooleanAuto-seek to frame 0 on load (root only)
falseworkbenchbooleanEnable timeline/hierarchy UI (root only)
falseMethods
async renderToVideo(options?: RenderToVideoOptions): Promise<Uint8Array | undefined>Export timegroup to MP4 video using WebCodecs API
Promise<Uint8Array | undefined>async createRenderClone(): Promise<RenderCloneResult>Create independent off-DOM clone for background rendering without affecting preview
Promise<RenderCloneResult>addFrameTask(callback: FrameTaskCallback): () => voidRegister callback executed on each frame during rendering or playback
Cleanup function that removes the callbackasync seek(timeMs: number): Promise<void>Seek to specific time position and wait for content to be ready
Promise<void>Container for sequencing and grouping elements.
Modes
-
fixed- Usesdurationattribute -
sequence- Sum of children (sequential playback) -
contain- Longest child duration -
fit- Inherit from parent
Root Timegroup
Scene (Fixed Duration)
<ef-timegroup mode="fixed" duration="5s" class="absolute w-full h-full"><ef-video src="clip.mp4" class="size-full object-cover"></ef-video><ef-text class="absolute top-4 left-4 text-white">Overlay</ef-text></ef-timegroup>
Nested Sequence
<ef-timegroup mode="sequence"><ef-timegroup mode="fixed" duration="3s"><!-- Scene 1 --></ef-timegroup><ef-timegroup mode="fixed" duration="5s"><!-- Scene 2 --></ef-timegroup><ef-timegroup mode="fixed" duration="4s"><!-- Scene 3 --></ef-timegroup></ef-timegroup>
Sequence with Overlap
Use overlap to create transitions between items:
<ef-timegroup mode="sequence" overlap="1s"><ef-timegroup mode="contain"><!-- Scene 1 --></ef-timegroup><ef-timegroup mode="contain"><!-- Scene 2 --></ef-timegroup></ef-timegroup>
See transitions.md for crossfade examples.
Methods
renderToVideo()
Export the timegroup composition to MP4 video using the WebCodecs API. See render-api.md for complete documentation.
async renderToVideo(options?: RenderToVideoOptions): Promise<Uint8Array | undefined>
Basic Example:
const tg = document.querySelector('ef-timegroup');await tg.renderToVideo({fps: 30,codec: 'avc',filename: 'output.mp4',onProgress: (progress) => {console.log(`${Math.round(progress.progress * 100)}% complete`);}});
RenderToVideoOptions:
fps- Frame rate (default: 30)codec- Video codec: "avc", "hevc", "vp9", "av1", "vp8" (default: "avc")bitrate- Video bitrate in bits/second (default: 5000000)filename- Download filename (default: "video.mp4")scale- Resolution multiplier (default: 1)fromMs,toMs- Time range to exportonProgress- Progress callback receivingRenderProgressobjectincludeAudio- Include audio tracks (default: true)signal- AbortSignal for cancellationreturnBuffer- Return Uint8Array instead of downloading- And more - see render-api.md
createRenderClone()
Create an independent off-DOM clone for background rendering without affecting the preview timeline.
async createRenderClone(): Promise<RenderCloneResult>
Example:
const tg = document.querySelector('ef-timegroup');// Create isolated render cloneconst { clone, container, cleanup } = await tg.createRenderClone();try {// Clone has independent time stateawait clone.seek(5000); // Seek clone to 5 seconds// Original timeline unaffectedconsole.log('Clone time:', clone.currentTimeMs);console.log('Original time:', tg.currentTimeMs);} finally {// Always clean upcleanup();}
RenderCloneResult:
interface RenderCloneResult {clone: EFTimegroup; // Cloned timegroup with independent statecontainer: HTMLElement; // Off-screen container holding the clonecleanup: () => void; // Remove clone from DOM and clean up}
Clones automatically re-run the initializer function if set, enabling JavaScript-driven animations in renders.
addFrameTask()
Register a callback that executes on each frame during playback or rendering. Returns cleanup function.
addFrameTask(callback: FrameTaskCallback): () => void
Example:
const tg = document.querySelector('ef-timegroup');const cleanup = tg.addFrameTask((info) => {// Update DOM based on current timeconst progress = info.percentComplete;console.log(`Frame at ${info.ownCurrentTimeMs}ms (${Math.round(progress * 100)}%)`);// Modify child elementsconst textEl = info.element.querySelector('.dynamic-text');if (textEl) {textEl.textContent = `Time: ${(info.ownCurrentTimeMs / 1000).toFixed(2)}s`;}});// Remove callback when donecleanup();
FrameTaskCallback:
type FrameTaskCallback = (info: {ownCurrentTimeMs: number; // This element's local timecurrentTimeMs: number; // Root timeline's global timedurationMs: number; // This element's durationpercentComplete: number; // Completion percentage (0.0 to 1.0)element: EFTimegroup; // The timegroup instance}) => void | Promise<void>;
The callback can be sync or async. Multiple callbacks can be registered and execute in parallel.
seek()
Seek to a specific time position and wait for all visible content to be ready.
async seek(timeMs: number): Promise<void>
Example:
const tg = document.querySelector('ef-timegroup');// Seek to 3 secondsawait tg.seek(3000);// Timeline is now at 3s, all visible media loadedconsole.log('Current time:', tg.currentTimeMs);
Time is automatically quantized to frame boundaries based on the fps attribute.
Scripting
Add dynamic behavior with JavaScript using the initializer property. The initializer function runs on both the original timeline and all render clones.
<ef-timegroup id="dynamic-scene" mode="fixed" duration="5s"><div class="dynamic-text"></div></ef-timegroup><script>const tg = document.querySelector('#dynamic-scene');// Initializer runs once per instance (original + clones)tg.initializer = (instance) => {instance.addFrameTask((info) => {const text = instance.querySelector('.dynamic-text');text.textContent = `Time: ${(info.ownCurrentTimeMs / 1000).toFixed(2)}s`;});};</script>
TimegroupInitializer:
type TimegroupInitializer = (timegroup: EFTimegroup) => void;
Constraints:
- Must be synchronous (no async/await, no Promise return)
- Must complete quickly (<10ms warning, <100ms error)
- Should only register callbacks and set up behavior
- Runs once per instance (prime timeline + each render clone)