Video This guide provides a comprehensive overview of manipulating videos and exporting the final product.
To add a video, you need a VideoClip
and a VideoSource
. You can create a VideoSource
from a file or an external URL. Here, we will use a URL:
import { VideoSource } from '@diffusionstudio/core' ;
const source = await VideoSource. from ( 'https://diffusion-studio-public.s3.eu-central-1.amazonaws.com/videos/big_buck_bunny_1080p_30fps.mp4' );
A VideoSource
is a reusable reference that can be shared across multiple clips, optimizing memory usage.
Now, create a VideoClip
from the VideoSource
:
import { VideoClip } from '@diffusionstudio/core' ;
const video = new VideoClip (source, { // also accepts new File(...)
position: 'center' , // ensures the clip is centered
height: '100%' , // stretches the clip to the full height
width: '100%' , // stretches the clip to the full width
});
You can perform various manipulations on the VideoClip
:
video
. offsetBy ( - 30 ) // time offset in frames (relative to current offset)
. subclip ( 0 , 180 ); // trims the clip from start to end frames
This sets the video's start time to -30 frames
at 30 FPS
, resulting in a 5-second visible clip (180 - 30 = 150 frames
). The video is centered and scaled to fill the entire composition. Specifying either height or width maintains the aspect ratio, while setting both does not.
Add the clip to the composition:
await composition. add (video);
Alternatively, if adding multiple clips to the same track, use:
const track = composition. createTrack ( 'video' );
await track. add (video);
The add
method is asynchronous, ensuring the clip is fully loaded before proceeding.
The composition provides various realtime playback options:
composition. play (); // start playback
composition. pause (); // pause playback
composition. seek ( 120 ); // seek to a specific frame
composition. time (); // get human-readable time (e.g., 00:04 / 00:05)
composition. on ( 'currentframe' , console.log); // log frame events
To export the composition, use the Encoder
:
import { Encoder } from '@diffusionstudio/core' ;
const encoder = new Encoder (composition);
You can customize the render settings with the second argument of the Encoder
constructor. For example, to render at 4K resolution and 25 FPS:
const encoder = new Encoder (composition, { resolution: 2 , fps: 25 });
Export the video with the render
method:
encoder. render (); // downloads the video with a default name
encoder. render ( 'myVideo.mp4' ); // specifies a filename
encoder. render ( 'https://my-s3.com' ); // uploads to a URL
The recommended method for client-side export is using showSaveFilePicker
:
const fileHandle = await window. showSaveFilePicker ({
suggestedName: 'untitled_video.mp4' ,
types: [
{
description: 'Video File' ,
accept: { 'video/mp4' : [ '.mp4' ] },
},
],
});
await encoder. render (fileHandle);
This writes the MP4 chunks directly to disk, allowing the export of large files while consuming minimal RAM.
If showSaveFilePicker
is unavailable, use this fallback snippet:
if ( ! ( 'showSaveFilePicker' in window)) {
Object. assign (window, { showSaveFilePicker : async () => undefined });
}
Here is a complete example putting everything together:
import { Composition, VideoSource, VideoClip, Encoder } from '@diffusionstudio/core' ;
const composition = new Composition ();
const player = document. getElementById ( 'player' ) as HTMLDivElement ;
composition. attachPlayer (player);
const source = await VideoSource. from ( 'https://diffusion-studio-public.s3.eu-central-1.amazonaws.com/videos/big_buck_bunny_1080p_30fps.mp4' );
const video = new VideoClip (source, {
position: 'center' ,
height: '100%' ,
width: '100%' ,
})
. offsetBy ( - 30 )
. subclip ( 0 , 180 );
await composition. add (video);
const encoder = new Encoder (composition, { resolution: 2 , fps: 25 });
await encoder. render ();