A JavaScript library for creating and editing videos in the browser.
Try Shotstack Studio in your preferred framework:
- Create video compositions with multiple tracks and clips
- Visual timeline interface
- WYSIWYG text editing
- Multi-track, drag-and-drop clip manipulation with snap-to-grid
- Use in conjunction with the Shotstack Edit API to render video
- Export to video using browser-based FFmpeg
npm install @shotstack/shotstack-studio
yarn add @shotstack/shotstack-studio
Install FFmpeg to use the browser based VideoExporter
class. This is kept separate to prevent WASM / Web Worker clashes in frameworks like Next.js.
npm install @ffmpeg/ffmpeg
You can skip this if you're using the Shotstack Edit API for rendering videos.
import { Edit, Canvas, Controls, Timeline } from "@shotstack/shotstack-studio";
// 1. Load a template
const response = await fetch("https://shotstack-assets.s3.amazonaws.com/templates/hello-world/hello.json");
const template = await response.json();
// 2. Initialize the edit
const edit = new Edit(template.output.size, template.timeline.background);
await edit.load();
// 3. Create a canvas to display the edit
const canvas = new Canvas(template.output.size, edit);
await canvas.load(); // Renders to [data-shotstack-studio] element
// 4. Load the template
await edit.loadEdit(template);
// 5. Initialize the Timeline
const timeline = new Timeline(edit, { width: 1280, height: 300 });
await timeline.load(); // Renders to [data-shotstack-timeline] element
// 6. Add keyboard controls
const controls = new Controls(edit);
await controls.load();
Your HTML should include containers for both the canvas and timeline:
<div data-shotstack-studio></div>
<div data-shotstack-timeline></div>
The Edit class represents a video project with its timeline, clips, and properties.
// Create an edit with dimensions and background
const edit = new Edit({ width: 1280, height: 720 }, "#000000");
await edit.load();
// Load from template
await edit.loadEdit(templateJson);
// Playback controls
edit.play();
edit.pause();
edit.seek(2000); // Seek to 2 seconds (in milliseconds)
edit.stop(); // Stop and return to beginning
// Editing functions
edit.addClip(0, {
asset: {
type: "image",
src: "https://example.com/image.jpg"
},
start: 0,
length: 5
});
edit.addTrack(1, { clips: [] });
edit.deleteClip(0, 0);
edit.deleteTrack(1);
// Undo/Redo
edit.undo();
edit.redo();
// Get edit information
const clip = edit.getClip(0, 0);
const track = edit.getTrack(0);
const editJson = edit.getEdit();
const duration = edit.totalDuration; // in milliseconds
The Edit class provides an event system to listen for specific actions:
// Listen for clip selection events
edit.events.on("clip:selected", data => {
console.log("Clip selected:", data.clip);
console.log("Track index:", data.trackIndex);
console.log("Clip index:", data.clipIndex);
});
// Listen for clip update events
edit.events.on("clip:updated", data => {
console.log("Previous state:", data.previous); // { clip, trackIndex, clipIndex }
console.log("Current state:", data.current); // { clip, trackIndex, clipIndex }
});
Available events:
clip:selected
- Emitted when a clip is initially selected, providing data about the clip, its track index, and clip index.clip:updated
- Emitted when a clip's properties are modified, providing both previous and current states.
The Canvas class provides the visual rendering of the edit.
// Create and load the canvas
const canvas = new Canvas(edit.size, edit);
await canvas.load();
// Zoom and positioning
canvas.centerEdit();
canvas.zoomToFit();
canvas.setZoom(1.5); // 1.0 is 100%, 0.5 is 50%, etc.
canvas.dispose(); // Clean up resources when done
The Controls class adds keyboard controls for playback.
const controls = new Controls(edit);
await controls.load();
// Available keyboard controls:
// Space - Play/Pause
// J - Stop
// K - Pause
// L - Play
// Left Arrow - Seek backward
// Right Arrow - Seek forward
// Shift + Arrow - Seek larger amount
// Comma - Step backward one frame
// Period - Step forward one frame
// Cmd/Ctrl + Z - Undo
// Cmd/Ctrl + Shift + Z - Redo
The Timeline class provides a visual timeline interface for editing.
import { Timeline } from "@shotstack/shotstack-studio";
const timeline = new Timeline(edit, { width: 1280, height: 300 });
await timeline.load();
// Timeline features:
// - Visual track and clip representation
// - Drag-and-drop clip manipulation
// - Clip resizing with edge detection
// - Playhead control for navigation
// - Snap-to-grid functionality
// - Zoom and scroll controls
The VideoExporter class exports the edit to a video file.
const exporter = new VideoExporter(edit, canvas);
await exporter.export("my-video.mp4", 25); // filename, fps
Shotstack Studio supports theming for visual components. Currently, theming is available for the Timeline component, with Canvas theming coming in a future releases.
The library includes pre-designed themes that you can use immediately:
import { Timeline } from "@shotstack/shotstack-studio";
import darkTheme from "@shotstack/shotstack-studio/themes/dark.json";
import minimalTheme from "@shotstack/shotstack-studio/themes/minimal.json";
// Apply a theme when creating the timeline
const timeline = new Timeline(edit, { width: 1280, height: 300 }, { theme: darkTheme });
Create your own theme by defining colors and dimensions for each component:
const customTheme = {
timeline: {
// Main timeline colors
background: "#1e1e1e",
divider: "#1a1a1a",
playhead: "#ff4444",
snapGuide: "#888888",
dropZone: "#00ff00",
trackInsertion: "#00ff00",
// Toolbar styling
toolbar: {
background: "#1a1a1a",
surface: "#2a2a2a", // Button backgrounds
hover: "#3a3a3a", // Button hover state
active: "#007acc", // Button active state
divider: "#3a3a3a", // Separator lines
icon: "#888888", // Icon colors
text: "#ffffff", // Text color
height: 36 // Toolbar height in pixels
},
// Ruler styling
ruler: {
background: "#404040",
text: "#ffffff", // Time labels
markers: "#666666", // Time marker dots
height: 40 // Ruler height in pixels
},
// Track styling
tracks: {
surface: "#2d2d2d", // Primary track color
surfaceAlt: "#252525", // Alternating track color
border: "#3a3a3a", // Track borders
height: 60 // Track height in pixels
},
// Clip colors by asset type
clips: {
video: "#4a9eff",
audio: "#00d4aa",
image: "#f5a623",
text: "#d0021b",
shape: "#9013fe",
html: "#50e3c2",
luma: "#b8e986",
default: "#8e8e93", // Unknown asset types
selected: "#007acc", // Selection border
radius: 4 // Corner radius in pixels
}
}
// Canvas theming will be available in future releases
// canvas: { ... }
};
const timeline = new Timeline(edit, { width: 1280, height: 300 }, { theme: customTheme });
Themes are organized by component, making it intuitive to customize specific parts of the interface:
-
Timeline: Controls the appearance of the timeline interface
toolbar
: Playback controls and buttonsruler
: Time markers and labelstracks
: Track backgrounds and bordersclips
: Asset-specific colors and selection states- Global timeline properties (background, playhead, etc.)
-
Canvas (coming soon): Will control the appearance of the video preview area
Templates use a JSON format with the following structure:
{
timeline: {
background: "#000000",
fonts: [
{ src: "https://example.com/font.ttf" }
],
tracks: [
{
clips: [
{
asset: {
type: "image", // image, video, text, shape, audio
src: "https://example.com/image.jpg",
// Other asset properties depend on type
},
start: 0, // Start time in seconds
length: 5, // Duration in seconds
transition: { // Optional transitions
in: "fade",
out: "fade"
},
position: "center", // Positioning
scale: 1, // Scale factor
offset: {
x: 0.1, // X-axis offset relative to position
y: 0 // Y-axis offset relative to position
}
}
]
}
]
},
output: {
format: "mp4",
size: {
width: 1280,
height: 720
}
}
}
PolyForm Shield License 1.0.0
The Edit
class represents a video editing project with its timeline, clips, and properties.
import { Edit } from "@shotstack/shotstack-studio";
import { EditSchema } from "@shotstack/shotstack-studio";
constructor(size: Size, backgroundColor: string = "#ffffff")
Creates a new Edit instance with the specified dimensions and background color.
assetLoader
- Asset loader instance for managing media assetsevents
- Event emitter for handling eventsplaybackTime
- Current playback position in millisecondstotalDuration
- Total duration of the edit in milliseconds
async load()
- Initialize and prepare the edit for renderingasync loadEdit(edit: EditType)
- Load an edit from a JSON templateplay()
- Start playbackpause()
- Pause playbackseek(target: number)
- Seek to a specific time in millisecondsstop()
- Stop playback and return to beginningaddClip(trackIdx: number, clip: ClipType)
- Add a clip to a specific trackdeleteClip(trackIdx: number, clipIdx: number)
- Delete a clipgetClip(trackIdx: number, clipIdx: number)
- Get a clip by track and indexaddTrack(trackIdx: number, track: TrackType)
- Add a new trackgetTrack(trackIdx: number)
- Get a track by indexdeleteTrack(trackIdx: number)
- Delete a trackgetEdit()
- Get the full edit configuration as a JSON objectundo()
- Undo the last editing operationredo()
- Redo the last undone operation
clip:selected
- Triggered when a clip is selectedclip:updated
- Triggered when a clip is modifiededit:undo
- Triggered when an undo operation is performededit:redo
- Triggered when a redo operation is performed
The Canvas
class provides the visual rendering of the edit.
import { Canvas } from "@shotstack/shotstack-studio";
import type { Size } from "@shotstack/shotstack-studio";
constructor(size: Size, edit: Edit)
Creates a new canvas with specified dimensions for rendering the edit.
async load()
- Initialize the canvas and add it to the DOMcenterEdit()
- Center the edit in the canvaszoomToFit()
- Zoom to fit the entire editsetZoom(zoom: number)
- Set zoom leveldispose()
- Clean up resources and remove the canvas from the DOM
The Controls
class adds keyboard controls for playback.
import { Controls } from "@shotstack/shotstack-studio";
constructor(edit: Edit)
Creates a new controls instance for the provided Edit.
async load()
- Set up event listeners for keyboard controls
The Timeline
class provides a visual timeline interface for video editing.
import { Timeline } from "@shotstack/shotstack-studio";
constructor(edit: Edit, size: { width: number, height: number }, themeOptions?: TimelineThemeOptions)
Creates a new timeline interface for the provided Edit.
async load()
- Initialize the timeline and add it to the DOMsetTheme(themeOptions: TimelineThemeOptions)
- Change the timeline themesetOptions(options: Partial<TimelineOptions>)
- Update timeline optionsdispose()
- Clean up resources and remove from DOM
The VideoExporter
class handles exporting the edit to mp4.
import { VideoExporter } from "@shotstack/shotstack-studio";
constructor(edit: Edit, canvas: Canvas)
Creates a new exporter for the provided Edit and Canvas.
async export(filename: string = "shotstack-export.mp4", fps: number = 25)
- Export the edit to a video file