Query metadata, seek to specific positions, and check block visibility programmatically using CE.SDK’s playback control APIs in headless mode.
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 modeconst 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 trackconst 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 fillconst videoFill = engine.block.createFill('video');engine.block.setString(videoFill, 'fill/video/fileURI', videoUri);engine.block.setFill(videoBlock, videoFill);
// Add to track and set durationengine.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 propertiesconsole.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 resourceconst 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 mediaconst 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 playbackconst pageSupportsPlayback = engine.block.supportsPlaybackControl(page);console.log(`Page supports playback control: ${pageSupportsPlayback}`);
// Video fills support playback for individual block previewconst 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 playbackconst 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 operationsif (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 offsetsconst 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 appearsconst 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 secondengine.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 trimmingif (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.