Diffusion Studio
Clips

Video

This guide provides a comprehensive overview of manipulating videos and exporting the final product.

Adding and Manipulating Video

Loading a Video Source

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.

Creating a Video Clip

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
}); 

Performing Video Manipulations

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.

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 track = composition.createTrack('video');
await track.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:

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

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.

Browser Compatibility Fallback

If showSaveFilePicker is unavailable, use this fallback snippet:

if (!('showSaveFilePicker' in window)) {
  Object.assign(window, { showSaveFilePicker: async () => undefined });
}

Full Example

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();

On this page