Video Clip
This guide provides a comprehensive overview of manipulating videos and exporting the final product.
Adding and Manipulating Video
Loading a Video Source
To efficiently share resources between muliple VideoClip
s you can create a VideoSource
. You can create a VideoSource
from a file/blob or an external URL. Here, we will use a URL:
import * as core from '@diffusionstudio/core';
const source = await core.Source.from<core.VideoSource>('https://diffusion-studio-public.s3.eu-central-1.amazonaws.com/videos/big_buck_bunny_1080p_30fps.mp4');
For smaller files, you can also load the video into memory to render it faster:
const source = await core.Source.from<core.VideoSource>(..., { prefetch: true });
Creating a Video Clip
Now, create a VideoClip
from the VideoSource
:
const video = new core.VideoClip(source, { // also accepts files/blobs or urls
position: 'center', // ensures the clip is centered
height: '100%', // stretches the clip to the full height
});
Note: By not setting width to 100%, the video will maintain its original aspect ratio.
Performing Video Manipulations
You can perform various manipulations on the VideoClip
:
video
.offset(-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 delay 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.
Adding the Clip to the Composition
Add the clip to the composition:
await composition.add(video);
Alternatively, if adding multiple clips to the same track, use:
const layer = composition.createLayer();
await layer.add(video);
The add
method is asynchronous, ensuring the clip is fully loaded before proceeding.
Using Realtime Playback
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
Exporting the Composition
To export the composition, use the Encoder
:
const encoder = new core.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 core.Encoder(composition, { video: { resolution: 2, fps: 25 } });
Export the video with the render
method:
await encoder.render('myVideo.mp4'); // specifies a filename
Using the showSaveFilePicker
API
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.
Full Example
Here is a complete example putting everything together:
import * as core from '@diffusionstudio/core';
const composition = new core.Composition();
const player = document.getElementById('player') as HTMLDivElement;
composition.attachPlayer(player);
const video = new VideoClip('https://diffusion-studio-public.s3.eu-central-1.amazonaws.com/videos/big_buck_bunny_1080p_30fps.mp4', {
position: 'center',
height: '100%',
width: '100%',
})
.offset(-30)
.subclip(0, 180);
await composition.add(video);
const encoder = new core.Encoder(composition);
await encoder.render('myVideo.mp4');