Search
Loading...
Skip to content

Video Fills

Apply motion content to design elements by filling shapes, backgrounds, and text with videos using CE.SDK’s video fill system.

CE.SDK video fills example showing a 3x3 grid with video content applied to different blocks including rectangles, ellipse, and opacity variations

15 mins
estimated time
Download
StackBlitz
GitHub

Understanding the distinction between video fills and video blocks is essential. Video fills are fill objects that can be applied to any block supporting fills—shapes, text, backgrounds—to paint them with video content. Video blocks, created with addVideo(), are dedicated timeline elements with full editing capabilities like trimming and duration control. Video fills focus on applying video as a visual treatment, while video blocks provide complete video editing functionality.

This guide covers how to create video fills, apply them to blocks, configure fill modes, and work with video resources programmatically.

Understanding Video Fills#

What is a Video Fill?#

A video fill is a fill object that paints a design block with video content. Like color and image fills, video fills are part of CE.SDK’s broader fill system.

Video fills are identified by the type '//ly.img.ubq/fill/video' or the short form 'video'. They contain properties for the video source, positioning, scaling, and playback behavior.

Video Fill vs Video Blocks#

Video fills are fill objects created with createFill('video') and applied to blocks with setFill(). You can use them to fill shapes with video content, create video backgrounds, or add video textures to text.

Video blocks are created with the convenience method addVideo() and come pre-configured with timeline integration, trim support, and playback controls. Use video blocks when building video editors or when you need features like trimming, duration adjustment, and precise playback control.

For this guide, we focus on video fills—applying video content as a fill to design elements. For video editing workflows, see the Trim Video guide.

Video Mode Requirement#

Video fills can only be created in Video mode scenes. Design mode doesn’t support video fills. You must initialize CE.SDK with createVideoScene() instead of createDesignScene().

// Create Video mode scene (required for video fills)
await cesdk.createVideoScene();
// Verify scene mode
const mode = engine.scene.getMode();
console.log(mode); // "Video"

Checking Video Fill Support#

Before applying video fills, verify that blocks support fills and that you’re in the correct scene mode.

// Create a sample block to demonstrate fill support checking
const sampleBlock = engine.block.create('graphic');
engine.block.setShape(sampleBlock, engine.block.createShape('rect'));
// Check if the block supports fills
const supportsFills = engine.block.supportsFill(sampleBlock);
// eslint-disable-next-line no-console
console.log('Block supports fills:', supportsFills); // true for graphic blocks
// Verify we're in Video mode (required for video fills)
const sceneMode = engine.scene.getMode();
if (sceneMode !== 'Video') {
throw new Error('Video fills require Video mode.');
}
// eslint-disable-next-line no-console
console.log('Scene mode:', sceneMode); // "Video"

Graphic blocks, shapes, and text blocks typically support fills. Pages and scenes don’t. Always check supportsFill() before attempting to apply video fills to prevent errors.

Creating Video Fills#

Creating Video Fills#

Creating a video fill involves three steps: create the fill object, set the video source, and apply it to a block.

// Pattern #1: Demonstrate Individual Before Combined
// Create a basic video fill demonstration
const basicBlock = engine.block.create('graphic');
engine.block.setShape(basicBlock, engine.block.createShape('rect'));
engine.block.setWidth(basicBlock, blockWidth);
engine.block.setHeight(basicBlock, blockHeight);
engine.block.appendChild(page, basicBlock);
// Create a video fill
const basicVideoFill = engine.block.createFill('video');
// or using full type name: engine.block.createFill('//ly.img.ubq/fill/video');
// Set the video source URI
engine.block.setString(basicVideoFill, 'fill/video/fileURI', videoUri);
// Apply the fill to the block
engine.block.setFill(basicBlock, basicVideoFill);

The video fill exists independently until you attach it to a block. This allows you to configure the fill completely before applying it. Once applied, the fill paints the block with the video content.

Getting Current Fill Information#

We can retrieve the current fill from a block and inspect its type to verify it’s a video fill.

// Get and verify the current fill
const fillId = engine.block.getFill(basicBlock);
const fillType = engine.block.getType(fillId);
// eslint-disable-next-line no-console
console.log('Fill type:', fillType); // '//ly.img.ubq/fill/video'

This is useful when building UIs that need to adapt based on the current fill type or when implementing undo/redo functionality that tracks fill changes.

Content Fill Modes#

Content fill modes control how video scales and positions within blocks. The two primary modes are Cover and Contain, each suited to different use cases.

Cover Mode#

Cover mode fills the entire block with video while maintaining the video’s aspect ratio. If the aspect ratios don’t match, CE.SDK crops portions of the video to ensure no empty space appears in the block.

// Pattern #2: Content fill mode - Cover
// Cover mode fills entire block, may crop video to fit
const coverBlock = engine.block.create('graphic');
engine.block.setShape(coverBlock, engine.block.createShape('rect'));
engine.block.setWidth(coverBlock, blockWidth);
engine.block.setHeight(coverBlock, blockHeight);
engine.block.appendChild(page, coverBlock);
const coverVideoFill = engine.block.createFill('video');
engine.block.setString(coverVideoFill, 'fill/video/fileURI', videoUri);
engine.block.setFill(coverBlock, coverVideoFill);
// Set content fill mode to Cover
engine.block.setEnum(coverBlock, 'contentFill/mode', 'Cover');
// Get current fill mode
const coverMode = engine.block.getEnum(coverBlock, 'contentFill/mode');
// eslint-disable-next-line no-console
console.log('Cover block fill mode:', coverMode); // 'Cover'

Use Cover mode for background videos, full-frame video content, and situations where visual consistency matters more than showing the entire video. It guarantees no empty space but may crop content.

Contain Mode#

Contain mode fits the entire video within the block while maintaining aspect ratio. If aspect ratios don’t match, CE.SDK adds empty space to preserve the full video visibility.

// Content fill mode - Contain
// Contain mode fits entire video, may leave empty space
const containBlock = engine.block.create('graphic');
engine.block.setShape(containBlock, engine.block.createShape('rect'));
engine.block.setWidth(containBlock, blockWidth);
engine.block.setHeight(containBlock, blockHeight);
engine.block.appendChild(page, containBlock);
const containVideoFill = engine.block.createFill('video');
engine.block.setString(containVideoFill, 'fill/video/fileURI', videoUri);
engine.block.setFill(containBlock, containVideoFill);
// Set content fill mode to Contain
engine.block.setEnum(containBlock, 'contentFill/mode', 'Contain');

Use Contain mode when the entire video must remain visible—presentations, product demos, or content where cropping would lose important information. Empty space is acceptable to preserve complete visibility.

Loading Video Resources#

Before accessing video metadata like duration or dimensions, you must force load the video resource. This ensures CE.SDK has downloaded the necessary information.

// Force load video resource to access metadata
const resourceBlock = engine.block.create('graphic');
engine.block.setShape(resourceBlock, engine.block.createShape('rect'));
engine.block.setWidth(resourceBlock, blockWidth);
engine.block.setHeight(resourceBlock, blockHeight);
engine.block.appendChild(page, resourceBlock);
const resourceVideoFill = engine.block.createFill('video');
engine.block.setString(resourceVideoFill, 'fill/video/fileURI', videoUri);
engine.block.setFill(resourceBlock, resourceVideoFill);
// Force load the video resource before accessing metadata
await engine.block.forceLoadAVResource(resourceVideoFill);
// Now we can access video metadata
const totalDuration = engine.block.getDouble(
resourceVideoFill,
'fill/video/totalDuration'
);
// eslint-disable-next-line no-console
console.log('Video total duration:', totalDuration, 'seconds');

Skipping this step causes errors when trying to access metadata. Videos load asynchronously, so forceLoadAVResource ensures the metadata is available before you query it.

Once loaded, you can access properties like fill/video/totalDuration to get the video length in seconds. This information helps you build UI previews or validate user input.

Common Use Cases#

Video as Shape Fill#

Video fills aren’t limited to rectangles. You can fill any shape with video content.

// Use case: Video as shape fill - Ellipse
const ellipseBlock = engine.block.create('graphic');
const ellipseShape = engine.block.createShape('//ly.img.ubq/shape/ellipse');
engine.block.setShape(ellipseBlock, ellipseShape);
engine.block.setWidth(ellipseBlock, blockWidth);
engine.block.setHeight(ellipseBlock, blockHeight);
engine.block.appendChild(page, ellipseBlock);
const ellipseVideoFill = engine.block.createFill('video');
engine.block.setString(ellipseVideoFill, 'fill/video/fileURI', videoUri);
engine.block.setFill(ellipseBlock, ellipseVideoFill);

Ellipse shapes, polygons, stars, and custom paths all support video fills. The video content fills the shape boundary, masking the video.

Video with Opacity#

Control the transparency of video-filled blocks to create overlay effects or blend video content with backgrounds.

// Advanced: Video fill with opacity
const opacityBlock = engine.block.create('graphic');
engine.block.setShape(opacityBlock, engine.block.createShape('rect'));
engine.block.setWidth(opacityBlock, blockWidth);
engine.block.setHeight(opacityBlock, blockHeight);
engine.block.appendChild(page, opacityBlock);
const opacityVideoFill = engine.block.createFill('video');
engine.block.setString(opacityVideoFill, 'fill/video/fileURI', videoUri);
engine.block.setFill(opacityBlock, opacityVideoFill);
// Set block opacity to 70%
engine.block.setFloat(opacityBlock, 'opacity', 0.7);

Opacity affects the entire block, including its video fill. This technique creates semi-transparent video overlays, watermarks, or layered compositions where video content blends with other elements.

Additional Techniques#

Sharing Video Fills#

Memory efficiency improves when multiple blocks share a single video fill instance. Changes to the shared fill affect all blocks using it.

// Advanced: Share one video fill between multiple blocks
const sharedFill = engine.block.createFill('video');
engine.block.setString(sharedFill, 'fill/video/fileURI', videoUri);
// First block using shared fill
const sharedBlock1 = engine.block.create('graphic');
engine.block.setShape(sharedBlock1, engine.block.createShape('rect'));
engine.block.setWidth(sharedBlock1, blockWidth);
engine.block.setHeight(sharedBlock1, blockHeight);
engine.block.appendChild(page, sharedBlock1);
engine.block.setFill(sharedBlock1, sharedFill);
// Second block using the same shared fill
const sharedBlock2 = engine.block.create('graphic');
engine.block.setShape(sharedBlock2, engine.block.createShape('rect'));
engine.block.setWidth(sharedBlock2, blockWidth * 0.8); // Slightly smaller
engine.block.setHeight(sharedBlock2, blockHeight * 0.8);
engine.block.appendChild(page, sharedBlock2);
engine.block.setFill(sharedBlock2, sharedFill);
// eslint-disable-next-line no-console
console.log(
'Shared fill - Two blocks using the same video fill instance for memory efficiency'
);

This pattern reduces memory usage when the same video appears multiple times in a composition. It’s particularly useful for repeated elements like watermarks or background patterns.

Shared fills play back synchronized—all blocks display the same frame at the same time during playback. This ensures visual consistency across multiple elements.

Troubleshooting#

Video Not Visible#

If your video fill doesn’t appear, check several common causes. Verify the fill is enabled with isFillEnabled(block). Ensure the video URL is accessible—CORS restrictions on web platforms can block video loading. Confirm the block has valid dimensions (width and height greater than zero) and exists in the scene hierarchy.

Check that the video format is supported on your platform. MP4 with H.264 encoding works reliably across platforms, while other codecs may have limited support.

Cannot Create Video Fill#

If creating a video fill throws an error, verify you’re in Video mode. Design mode doesn’t support video fills. Use engine.scene.getMode() to check the current mode. If it returns “Design”, you need to create a video scene instead.

Call await cesdk.createVideoScene() during initialization rather than createDesignScene() to enable video capabilities.

Video Not Loading#

When videos fail to load, verify network connectivity for remote URLs. Check CORS headers—web browsers enforce cross-origin restrictions that can block video access. Validate the URI format uses https:// for remote videos or appropriate schemes for local files.

Test with a known working video URL to isolate whether the issue is with your specific video or a broader configuration problem. Check the browser console for detailed error messages.

Memory Leaks#

Always destroy replaced fills to prevent memory leaks. When changing a block’s fill, retrieve the old fill with getFill(), assign the new fill with setFill(), then destroy the old fill with destroy().

Don’t create fills without attaching them to blocks—unattached fills remain in memory indefinitely. Clean up shared fills when no blocks reference them anymore.

Performance Issues#

Video playback is resource-intensive. Use appropriately sized videos—avoid massive files that strain decoding hardware. Consider lower resolutions for editing with high-resolution sources reserved for export.

Limit the number of simultaneously playing videos, especially on mobile devices. Too many concurrent video decodes overwhelm device capabilities. Compress videos before use to reduce file sizes and improve loading times.

API Reference#

MethodDescription
createFill('video')Create a new video fill object
setFill(block, fill)Assign fill to a block
getFill(block)Get the fill ID from a block
setString(fill, property, value)Set video URI property
getString(fill, property)Get current video URI
setSourceSet(fill, property, sources)Set responsive video sources
getSourceSet(fill, property)Get current source set
setEnum(block, property, value)Set content fill mode
getEnum(block, property)Get current fill mode
setFillEnabled(block, enabled)Enable or disable fill rendering
isFillEnabled(block)Check if fill is enabled
supportsFill(block)Check if block supports fills
forceLoadAVResource(fill)Force load video metadata
getVideoFillThumbnail(fill, height)Get single thumbnail frame
adjustCropToFillFrame(block, fillIndex)Adjust crop to fill frame

Video Fill Properties#

PropertyTypeDescription
fill/video/fileURIStringSingle video URI (URL, data URI, file path)
fill/video/sourceSetSourceSet[]Array of responsive video sources
fill/video/totalDurationDoubleTotal duration of video in seconds

Content Fill Properties#

PropertyTypeValuesDescription
contentFill/modeEnum’Cover’, ‘Contain’How video scales within block

Next Steps#