Diffusion Studio
Clips

Custom

Diffusion Studio is highly extensible using Pixi.js, an HTML5 creation engine. In this guide, we will walk through the steps of creating a custom Clip object using Pixi.js. Before diving into the example, let's first discuss the lifecycle of a Clip object.

Clip Lifecycle

When Clip objects are rendered to the canvas, they pass through several key phases:

Constructor

The constructor() method is invoked first, during the initialization of the clip. This is where the initial state and values should be set up.

The method receives props as arguments, and you must always call super(props) to ensure the base class is properly initialized.

Init

The init() method is called asynchronously before the Clip is added to a track/composition. This makes it the ideal place for I/O operations, such as fetching assets or loading buffers.

Enter

This method is triggered right before the Clip is drawn to the canvas. Use enter() to perform any synchronous actions that need to be executed once, rather than on every render cycle.

Update

The update() method is called on every redraw of the clip. It receives a Timestamp argument, which you can use to implement time-based state changes. The update() function may also return a promise—this is useful during video export to ensure frame accuracy. However, for playback, promises are not awaited to maintain smooth performance.

Exit

This method is called after the Clip has been drawn to the canvas for the last time. It is commonly used to perform cleanup operations, such as removing filters or other resources to free memory.

Example: Custom Alien Clip

This example is inspired by the Pixi.js Texture Swap guide. You can refer to it for additional insights.

import { ClipProps, Clip, Timestamp } from '@diffusionstudio/core';
import { Sprite, Assets } from 'pixi.js';
 
// Define custom Clip properties extending `ClipProps`, such as start, stop, etc.
interface AlienClipProps extends ClipProps {
  speed?: number;  // Optional speed property
}
 
// Create a new class extending `Clip` and apply your custom properties
class AlienClip extends Clip<AlienClipProps> {
  // Declare custom fields
  public sprite = new Sprite();
  public speed = 0.2;
 
  public constructor(props: AlienClipProps = {}) {
    // Ensure parent class `Clip` is properly initialized
    super(props);
 
    // Perform synchronous actions such as setting sprite properties
    this.sprite.anchor.set(0.5);
    this.sprite.scale.set(2);
 
    // Assign provided properties to the Clip instance
    Object.assign(this, props);
 
    // Add the sprite to the clip view (a container)
    this.view.addChild(this.sprite);
  }
 
  // Initialize the clip, typically used for loading assets asynchronously
  public async init(): Promise<void> {
    this.sprite.texture = await Assets.load('https://pixijs.com/assets/flowerTop.png');
  }
 
  // Enter phase: invoked when the clip is about to be drawn to the canvas
  public enter(): void {
    // No specific actions in this example, but can be used for one-time setup
  }
 
  // Update the clip's state on each frame. Receives a `Timestamp` argument.
  public update(time: Timestamp): void | Promise<void> {
    // Ensure track and composition are defined before accessing them
    this.sprite.x = this.track!.composition!.width / 2;
    this.sprite.y = this.track!.composition!.height / 2;
 
    // Adjust the sprite's angle based on elapsed time and configured speed
    this.sprite.angle = time.millis * this.speed;
    
    // Access the track or composition's scene graph if needed:
    // this.track.view (track-level) or this.track.composition.stage (composition-level)
    // This can be useful for collision detection, etc.
  }
 
  // Exit phase: invoked when the clip is no longer needed
  public exit(): void {
    // Cleanup resources (e.g., removing filters)
  }
}

Adding the Clip to a Composition

To include this AlienClip in a composition, you can do the following:

import { Composition } from '@diffusionstudio/core';
 
const composition = new Composition();
 
// Add the custom AlienClip to the composition
await composition.add(new AlienClip({ speed: 0.4, stop: 150 }));

On this page