Search
Loading...
Skip to content

Control Audio and Video

Query metadata, seek to specific positions, and check block visibility programmatically using CE.SDK’s playback control APIs in headless mode.

10 mins
estimated time
Download
StackBlitz
GitHub

CE.SDK provides playback control for audio and video through the Block API. In headless mode, playback time, seeking, and visibility checks are controlled programmatically. Resources must be loaded before accessing metadata like duration and dimensions.

This guide covers how to load media resources, seek to specific positions, check visibility at playback time, and access video resource metadata.

Setup#

We start by initializing the engine in headless mode and creating a video scene with a page and track.

// Initialize CE.SDK engine in headless mode
const engine = await CreativeEngine.init({
// license: process.env.CESDK_LICENSE, // Optional (trial mode available)
});

The video block is created with specified dimensions and duration, then added to the track.

// Create a video block and add it to the track
const videoBlock = engine.block.create('graphic');
engine.block.setShape(videoBlock, engine.block.createShape('rect'));
engine.block.setWidth(videoBlock, 1920);
engine.block.setHeight(videoBlock, 1080);
// Create and configure video fill
const videoFill = engine.block.createFill('video');
engine.block.setString(videoFill, 'fill/video/fileURI', videoUri);
engine.block.setFill(videoBlock, videoFill);
// Add to track and set duration
engine.block.appendChild(track, videoBlock);
engine.block.setDuration(videoBlock, 10);

Force Loading Resources#

Media resource metadata is unavailable until the resource is loaded. We call engine.block.forceLoadAVResource() on the video fill to ensure dimensions and duration are accessible.

// Force load the video resource to access metadata
// This is required before accessing duration, dimensions, or other properties
console.log('Loading video resource...');
await engine.block.forceLoadAVResource(videoFill);
console.log('Video resource loaded successfully');

Without loading the resource first, accessing properties like duration or dimensions throws an error.

Getting Video Metadata#

Once the resource is loaded, we can query the video dimensions and total duration.

// Query video dimensions from the loaded resource
const videoWidth = engine.block.getVideoWidth(videoFill);
const videoHeight = engine.block.getVideoHeight(videoFill);
console.log(`Video dimensions: ${videoWidth}x${videoHeight} pixels`);
// Get the total duration of the source media
const totalDuration = engine.block.getAVResourceTotalDuration(videoFill);
console.log(`Source media duration: ${totalDuration} seconds`);

The engine.block.getVideoWidth() and engine.block.getVideoHeight() methods return the original video dimensions in pixels. The engine.block.getAVResourceTotalDuration() method returns the full duration of the source media in seconds.

Playback Control#

We check if the block supports playback control using engine.block.supportsPlaybackControl(). In headless mode, this determines whether the block can be positioned programmatically on the timeline. The engine.block.isPlaying() method returns whether the block is currently playing, which will be false in headless mode since there is no active playback.

// Check if a block supports playback control
// Pages and scenes support playback control for timeline-based playback
const pageSupportsPlayback = engine.block.supportsPlaybackControl(page);
console.log(`Page supports playback control: ${pageSupportsPlayback}`);
// Video fills support playback for individual block preview
const fillSupportsPlayback = engine.block.supportsPlaybackControl(videoFill);
console.log(`Video fill supports playback control: ${fillSupportsPlayback}`);
// Check if the page is currently playing
// In headless mode, this will be false as there is no active playback
const isPlaying = engine.block.isPlaying(page);
console.log(`Is playing: ${isPlaying}`);

Seeking#

To position the timeline at a specific point, we use engine.block.setPlaybackTime(). First, check if the block supports playback time with engine.block.supportsPlaybackTime().

// Check if the page supports playback time operations
if (engine.block.supportsPlaybackTime(page)) {
// Set the playback time to position the timeline
// This is useful for rendering frames at specific times
engine.block.setPlaybackTime(page, 3.0);
console.log('Playback time set to 3.0 seconds');
// Get the current playback time
const currentTime = engine.block.getPlaybackTime(page);
console.log(`Current playback time: ${currentTime} seconds`);
}

Playback time is specified in seconds. The engine.block.getPlaybackTime() method returns the current position.

Visibility at Current Time#

We can check if a block is visible at the current playback position using engine.block.isVisibleAtCurrentPlaybackTime(). This is useful when blocks have different time offsets or durations.

// Check if the video block is visible at the current playback time
// This is useful when working with multiple blocks that have different time offsets
const isVisible = engine.block.isVisibleAtCurrentPlaybackTime(videoBlock);
console.log(`Video block visible at current time: ${isVisible}`);

Time Offset and Duration#

Time offset controls when a block becomes active in the timeline, while duration controls how long the block appears. Use engine.block.getTimeOffset() and engine.block.getDuration() to query these values, and their corresponding setters to modify them.

// Time offset controls when a block becomes active in the timeline
// Duration controls how long the block appears
const blockDuration = engine.block.getDuration(videoBlock);
const blockTimeOffset = engine.block.getTimeOffset(videoBlock);
console.log(`Video block duration: ${blockDuration} seconds`);
console.log(`Video block time offset: ${blockTimeOffset} seconds`);
// Modify time offset to start the block at 1 second
engine.block.setTimeOffset(videoBlock, 1.0);
console.log(
`Updated time offset to: ${engine.block.getTimeOffset(videoBlock)} seconds`
);

Trim#

Trim controls which portion of the source media plays. The trim offset specifies where playback starts within the source file, and trim length defines how much of the source to play. Check engine.block.supportsTrim() before applying trim operations.

// Trim controls which portion of the source media plays
// Check if the video fill supports trimming
if (engine.block.supportsTrim(videoFill)) {
// Set trim offset to start playback 2 seconds into the source video
engine.block.setTrimOffset(videoFill, 2.0);
// Set trim length to play 5 seconds of the source video
engine.block.setTrimLength(videoFill, 5.0);
const trimOffset = engine.block.getTrimOffset(videoFill);
const trimLength = engine.block.getTrimLength(videoFill);
console.log(
`Trim offset: ${trimOffset} seconds (starts at this point in source)`
);
console.log(
`Trim length: ${trimLength} seconds (plays this much of source)`
);
}

Troubleshooting#

Properties Unavailable Before Resource Load#

Symptom: Accessing duration, dimensions, or trim values throws an error.

Cause: Media resource not yet loaded.

Solution: Always await engine.block.forceLoadAVResource() before accessing these properties.

Block Not Playing#

Symptom: Calling setPlaying(true) has no effect.

Cause: Block doesn’t support playback control or scene not in playback mode.

Solution: Check supportsPlaybackControl() returns true; ensure scene playback is active.

Solo Playback Not Working#

Symptom: Enabling solo doesn’t isolate the block.

Cause: Solo applied to wrong block type or block not visible.

Solution: Apply solo to video fills or audio blocks, ensure block is at current playback time.