How to Implement Transition Effects Between Clips on Clypra's Timeline
Clypra treats transitions as special timeline items that sit between adjacent visual clips, validated by the timeline store and rendered via a GPU-based pipeline.
Adding professional transitions between video or text clips in Clypra requires understanding how the timeline store validates adjacency and how the rendering engine applies GPU shaders. According to the Clypra source code, transitions are first-class citizens in the data model, stored alongside clips and resolved during export.
Creating Transition Items in the Timeline Store
The entry point for adding transitions is the createTransitionBetweenClips method located in src/store/timelineStore.ts (lines 616-632). This method constructs a TransitionTimelineItem and inserts it into the store only after rigorous validation.
Validation Rules for Adjacent Clips
Before creating any transition, the store enforces three strict constraints:
- Both clips must belong to the same unlocked track
- The clips must be directly adjacent with no gap between them
- Each clip must be long enough to accommodate half of the requested transition duration
If validation fails, the method returns an error such as "Move clips together before adding a transition," preventing invalid timeline states.
The TransitionTimelineItem Structure
Upon successful validation, the store generates a transition object following the TransitionTimelineItem type defined in src/types/index.ts (lines 374-447):
{
id: string; // generated with `generateId("transition")`
kind: "transition";
fromItemId: string; // ID of the preceding clip
toItemId: string; // ID of the following clip
placement: { trackId: string }; // inherits the track of the clips
renderer: string; // GPU renderer identifier (e.g., "cross-dissolve")
startTime: number; // calculated start position on the timeline
duration: number; // user-specified length in seconds
}
The transition is stored in the transitions array via the addTransition reducer, maintaining referential integrity with the clip IDs.
Rendering Pipeline and GPU Execution
When exporting or previewing, Clypra resolves transition definitions and delegates the visual effect to the GPU engine.
Resolving Transition Definitions
The export pipeline in src/lib/export/videoExport.ts (lines 23-41) calls resolveTransitionDefinition and mergeTransitionParams to prepare the transition for rendering. This logic maps the stored renderer string to a concrete implementation in the engine's transition package (@clypra/engine/transitions).
GPU Shader Implementation
The selected renderer is retrieved from the TransitionRenderer registry (referenced in src/types/index.ts). At render time, the engine creates a temporary off-screen buffer and executes the following steps:
- Draws the outgoing clip (fromItemId) to the buffer
- Draws the incoming clip (toItemId) to a secondary buffer
- Applies the shader effect (e.g., cross-dissolve) over the specified duration
Because the transition runs entirely on the GPU, it composites with other visual effects without CPU bottlenecks.
Implementation Examples
To add a fade transition between two clips, call the store method with the clip IDs, transition type, duration, and renderer identifier:
import { useTimelineStore } from '@/store/timelineStore';
const result = useTimelineStore.getState().createTransitionBetweenClips(
'clipA-id', // ID of the left clip
'clipB-id', // ID of the following clip
'fade', // Transition type (mapped to a renderer)
1.0, // Duration in seconds
'cross-dissolve' // GPU renderer identifier
);
if (result.error) {
console.error('Cannot add transition:', result.error);
} else {
console.log('Transition added:', result.transition);
}
During export, the pipeline automatically resolves and renders any transitions stored in the timeline:
import { exportProject } from '@/lib/export/videoExport';
await exportProject(project, {
// Other export options
});
The UI layer in src/components/editor/preview/previewMode.ts provides controls that trigger this same store method, displaying validation errors to users when clips are not properly positioned.
Summary
- Validation is mandatory: The
createTransitionBetweenClipsmethod enforces adjacency, track locking, and duration constraints before creating any transition. - Transitions are typed items: Each transition is a
TransitionTimelineItemwithfromItemId,toItemId, and arendererfield pointing to GPU implementations. - GPU rendering: The export pipeline resolves transitions via
resolveTransitionDefinitionand executes them through theTransitionRendererregistry using off-screen buffers. - Simple API: Use
useTimelineStore.getState().createTransitionBetweenClips()with clip IDs and renderer parameters to add effects programmatically.
Frequently Asked Questions
What are the requirements for adding a transition between two clips in Clypra?
Both clips must reside on the same unlocked track, be directly adjacent without gaps, and each must have sufficient duration to accommodate half of the transition length. The createTransitionBetweenClips method in src/store/timelineStore.ts enforces these constraints and returns an error if clips are not properly positioned.
How does Clypra render transitions during video export?
The export pipeline calls resolveTransitionDefinition and mergeTransitionParams in src/lib/export/videoExport.ts to prepare the transition. The engine then uses the TransitionRenderer registry to execute GPU shaders that blend the outgoing and incoming clips using off-screen buffers, ensuring smooth performance even with complex effects.
Can I use custom GPU shaders for transitions in Clypra?
Yes, the renderer field in TransitionTimelineItem accepts custom identifiers that map to implementations in the @clypra/engine/transitions package. The engine's registry looks up these identifiers during rendering, allowing you to extend the default transition library with custom GPU shaders.
What happens if I try to add a transition to clips that are not adjacent?
The timeline store rejects the request and returns an error message such as "Move clips together before adding a transition." This validation prevents visual glitches and ensures that the GPU renderer has valid frame data from both clips to blend during the transition period.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →