Search Docs
Loading...
Skip to content

Working With Resources

Manage external media files—images, videos, audio, and fonts—that blocks reference via URIs in CE.SDK.

10 mins
estimated time
GitHub

Resources are external media files that blocks reference through URI properties like fill/image/imageFileURI or fill/video/fileURI. CE.SDK loads resources automatically when needed, but you can preload them for better performance. When working with temporary data like buffers or blobs, you need to persist them before saving. If resource URLs change (such as during CDN migration), you can update the mappings without modifying scene data.

This guide covers on-demand and preloaded resource loading, identifying and persisting transient resources, relocating resources when URLs change, and discovering all media URIs in a scene.

MethodCategoryPurpose
engine.block.forceLoadResources(_:)PreloadingLoad resources for blocks and their children
engine.block.forceLoadAVResource(_:)PreloadingLoad audio/video resource for a block
engine.block.getAVResourceTotalDuration(_:)PropertiesGet total duration of audio/video resource
engine.block.getVideoWidth(_:)PropertiesGet video resource width in pixels
engine.block.getVideoHeight(_:)PropertiesGet video resource height in pixels
engine.editor.findAllTransientResources()DiscoveryFind temporary resources that need persistence
engine.editor.findAllMediaURIs()DiscoveryGet all media URIs referenced in the scene
engine.editor.getMIMEType(url:)DiscoveryGet the MIME type of a resource
engine.editor.relocateResource(currentURL:relocatedURL:)ManagementUpdate URL mapping for a relocated resource
engine.scene.saveToString(allowedResourceSchemes:onDisallowedResourceScheme:)SerializationSave scene with resource scheme handling

On-Demand Loading#

The engine fetches resources automatically when rendering blocks or preparing exports. This approach requires no extra code but may delay the initial render while resources download.

// Create a graphic block with an image fill.
// The image loads on-demand when the engine renders the block.
let imageBlock = try engine.block.create(.graphic)
let rectShape = try engine.block.createShape(.rect)
try engine.block.setShape(imageBlock, shape: rectShape)
let imageFill = try engine.block.createFill(.image)
try engine.block.setString(
imageFill,
property: "fill/image/imageFileURI",
value: "https://img.ly/static/ubq_samples/sample_4.jpg",
)
try engine.block.setFill(imageBlock, fill: imageFill)
try engine.block.setEnum(imageBlock, property: "contentFill/mode", value: "Cover")
try engine.block.appendChild(to: page, child: imageBlock)

When you create a block with an image fill, the image doesn’t load immediately. The engine fetches it when the block first renders on the canvas.

Preloading Resources#

Load resources before they’re needed with forceLoadResources(_:). Pass block IDs to load resources for those blocks and their children. Preloading eliminates render delays and is useful when you want the scene fully ready before displaying it.

// Preload all resources in the scene before rendering.
try await engine.block.forceLoadResources([scene])
// Preload specific blocks only.
let graphics = try engine.block.find(byType: .graphic)
try await engine.block.forceLoadResources(graphics)

Pass the scene to preload all resources in the entire design, or pass specific blocks to load only what you need.

Preloading Audio and Video#

Audio and video resources require forceLoadAVResource(_:) for full metadata access. The engine needs to download and parse media files before you can query properties like duration or dimensions.

// Create a video fill and preload its resource to query properties.
let videoBlock = try engine.block.create(.graphic)
let videoShape = try engine.block.createShape(.rect)
try engine.block.setShape(videoBlock, shape: videoShape)
let videoFill = try engine.block.createFill(.video)
try engine.block.setString(
videoFill,
property: "fill/video/fileURI",
value: "https://img.ly/static/ubq_video_samples/bbb.mp4",
)
try engine.block.setFill(videoBlock, fill: videoFill)
try engine.block.setEnum(videoBlock, property: "contentFill/mode", value: "Cover")
try engine.block.appendChild(to: page, child: videoBlock)
try await engine.block.forceLoadAVResource(videoFill)
let duration = try engine.block.getAVResourceTotalDuration(videoFill)
let videoWidth = try engine.block.getVideoWidth(videoFill)
let videoHeight = try engine.block.getVideoHeight(videoFill)
print("Video: \(duration)s, \(videoWidth)x\(videoHeight)")

Without preloading, properties like getAVResourceTotalDuration(_:) or getVideoWidth(_:) may return zero or incomplete values.

Finding Transient Resources#

Transient resources are temporary data stored in buffers or blobs that won’t survive scene serialization. Use findAllTransientResources() to discover them before saving.

// Find transient resources that won't survive serialization.
let transientResources = try engine.editor.findAllTransientResources()
for resource in transientResources {
print("Transient: \(resource.url), \(resource.size) bytes")
}

Each entry includes the resource URL and its size in bytes. Common transient resources include images from clipboard paste operations, camera captures, or programmatically generated content.

Finding Media URIs#

Get all media file URIs referenced in a scene with findAllMediaURIs(). This returns a deduplicated list of URLs from image fills, video fills, audio blocks, and other media sources.

// Get all media URIs referenced in the scene.
let mediaURIs = try engine.editor.findAllMediaURIs()
for uri in mediaURIs {
print("Media URI: \(uri)")
}

Use this for pre-fetching resources, validating availability, or building a manifest of all assets in a design.

Detecting MIME Types#

Determine a resource’s content type with getMIMEType(url:). The engine downloads the resource if it’s not already cached.

// Detect the MIME type of a resource.
let imageURL = URL(string: "https://img.ly/static/ubq_samples/sample_4.jpg")!
let mimeType = try await engine.editor.getMIMEType(url: imageURL)
print("MIME type: \(mimeType)")

Common return values include image/jpeg, image/png, video/mp4, and audio/mpeg. This is useful when you need to verify resource types or make format-dependent decisions.

Relocating Resources#

Update URL mappings when resources move with relocateResource(currentURL:relocatedURL:). This updates all resource references in the scene and clears the internal cache.

// Update a resource's URL mapping after moving it to a new location.
let currentURL = URL(string: "https://example.com/old-location/image.jpg")!
let relocatedURL = URL(string: "https://cdn.example.com/new-location/image.jpg")!
try engine.editor.relocateResource(currentURL: currentURL, relocatedURL: relocatedURL)

Use relocation after uploading resources to a CDN or when migrating assets between storage locations. The engine updates all references in the scene and clears cached data so that the resource is fetched from the new URL.

Persisting Transient Resources#

Handle transient resources during save with the onDisallowedResourceScheme callback in saveToString. The callback receives each resource URL with a disallowed scheme (like buffer: or blob:) and returns the permanent URL after uploading.

// Save the scene with a persistence callback for transient resources.
let sceneString = try await engine.scene.saveToString(
allowedResourceSchemes: ["http", "https"],
onDisallowedResourceScheme: { url, _ in
// Upload the resource to permanent storage and return the new URL.
// let permanentURL = try await uploadToCDN(url)
// return permanentURL
url
},
)
print("Saved scene (\(sceneString.count) characters)")

This pattern lets you intercept temporary resources, upload them to permanent storage, and save the scene with stable URLs that will work when reloaded.

Troubleshooting#

Slow initial render: Preload resources with forceLoadResources(_:) before displaying the scene.

Export fails with missing resources: Check findAllTransientResources() and persist any temporary resources before export.

Video duration returns 0: Ensure the video resource is loaded with forceLoadAVResource(_:) before querying properties.

Resources not found after reload: Transient resources (buffers, blobs) are not serialized—relocate them to persistent URLs before saving.

Next Steps#

  • Buffers — Work with in-memory data
  • Scenes — Understand scene serialization and persistence
  • Export — Learn about exporting designs