Add background music and audio tracks to video projects using CE.SDK audio blocks.
Audio blocks are standalone time-based blocks that play alongside video content, independent of video fills. You can set an audio source URI, position the block in the timeline, configure volume, query audio assets, and layer multiple audio blocks in the same video scene.
This guide focuses on the Android Engine API. It assumes you already have an Engine instance and want to add music to an existing or newly created video scene.
Creating a Video Scene#
Create a video scene with a page that owns the timeline. The page duration defines the composition length that audio blocks play within.
val scene = engine.scene.createForVideo()val page = engine.block.create(DesignBlockType.Page)engine.block.appendChild(parent = scene, child = page)engine.block.setWidth(page, value = 1920F)engine.block.setHeight(page, value = 1080F)engine.block.setDuration(page, duration = 30.0)Audio blocks must be children of a page. Set a page duration before adding audio so the timeline has a clear playback range.
Programmatic Audio Creation#
Create Audio Block#
Create an audio block with DesignBlockType.Audio, append it to the page, and assign the source file URI through the audio/fileURI property.
val music = engine.block.create(DesignBlockType.Audio)engine.block.appendChild(parent = page, child = music)
val musicUri = Uri.parse("https://cdn.img.ly/assets/demo/v3/ly.img.audio/audios/far_from_home.m4a")engine.block.setString(block = music, property = "audio/fileURI", value = musicUri.toString())Audio blocks support common audio formats including M4A, MP3, and WAV. The source URI can point to a network resource or a URI your app can resolve.
Configure Time Position#
Load the audio resource before reading its metadata. Then set the block’s time offset and duration in seconds.
engine.block.forceLoadAVResource(block = music)val sourceDuration = engine.block.getAVResourceTotalDuration(block = music)val musicDuration = minOf(sourceDuration, 30.0)
engine.block.setTimeOffset(block = music, offset = 0.0)engine.block.setDuration(block = music, duration = musicDuration)setTimeOffset() controls when the music starts relative to the page timeline. setDuration() controls how long the block remains active during playback.
Configure Volume#
Set volume on the audio block with a value from 0.0 for silent playback to 1.0 for full volume.
engine.block.setVolume(block = music, volume = 0.8F)val musicVolume = engine.block.getVolume(block = music)Volume changes affect preview and export. Use lower values for background music when other audio remains important.
Working with Audio Assets#
Query Audio Assets#
Use the Asset API to query the demo audio source. The sample registers the ly.img.audio source with engine.asset.addLocalSourceFromJSON(...) before querying it, which is the same source the editor uses for demo music.
val audioSourceId = "ly.img.audio"val demoAssetsBaseUri = Uri.parse("https://cdn.img.ly/assets/demo/v3")if (audioSourceId !in engine.asset.findAllSources()) { engine.asset.addLocalSourceFromJSON( contentUri = demoAssetsBaseUri.buildUpon() .appendPath(audioSourceId) .appendPath("content.json") .build(), )}
val audioAssets = engine.asset.findAssets( sourceId = audioSourceId, query = FindAssetsQuery(page = 0, perPage = 10),)val secondAudioAsset = audioAssets.assets.first { it.id.endsWith("dance_harder") }val secondAudioUri = Uri.parse(requireNotNull(secondAudioAsset.meta?.get("uri")))Each asset can carry metadata such as a URI, duration, MIME type, and tags. Use that metadata to build a custom picker or to select music programmatically.
Adding Multiple Audio Tracks#
Create additional audio blocks when a scene needs more than one music, voiceover, or sound-effect track. Each block has independent timing, duration, and volume.
val secondAudio = engine.block.create(DesignBlockType.Audio)engine.block.appendChild(parent = page, child = secondAudio)engine.block.setString(block = secondAudio, property = "audio/fileURI", value = secondAudioUri.toString())
engine.block.forceLoadAVResource(block = secondAudio)val secondAudioDuration = engine.block.getAVResourceTotalDuration(block = secondAudio)
// Start the secondary track inside the 30-second page so it is audible in this Android sample.engine.block.setTimeOffset(block = secondAudio, offset = 10.0)val secondAudioTimeOffset = engine.block.getTimeOffset(secondAudio)engine.block.setDuration(block = secondAudio, duration = minOf(secondAudioDuration, 15.0))val secondAudioPlaybackDuration = engine.block.getDuration(secondAudio)engine.block.setVolume(block = secondAudio, volume = 0.5F)val secondAudioVolume = engine.block.getVolume(secondAudio)Balance multiple tracks by keeping the primary track louder and lowering secondary tracks when they should sit behind it.
Managing Audio Blocks#
List Audio Blocks#
Use findByType(DesignBlockType.Audio) to retrieve all audio blocks in the scene.
val audioBlocks = engine.block.findByType(DesignBlockType.Audio)audioBlocks.forEach { audioBlock -> println( "Audio starts at ${engine.block.getTimeOffset(audioBlock)}s " + "with volume ${engine.block.getVolume(audioBlock)}", )}Listing audio blocks is useful for custom timeline controls, validation, or batch changes across a composition.
Remove Audio#
Destroy audio blocks that are no longer part of the composition.
engine.block.destroy(secondAudio)val remainingAudioBlocks = engine.block.findByType(DesignBlockType.Audio)Destroyed blocks are detached from the scene and no longer participate in playback or export.
Troubleshooting#
Audio does not play: Verify that the audio block is appended to a page and that the page duration covers the block’s time offset and duration.
Duration is unavailable: Call forceLoadAVResource() before reading getAVResourceTotalDuration().
Volume sounds wrong after export: Set volume on each audio block before exporting the page, and keep values in the 0.0 to 1.0 range.
API Reference#
| Method | Purpose |
|---|---|
engine.scene.createForVideo() | Create a video scene for time-based playback |
engine.block.create(blockType=DesignBlockType.Page) | Create a page for the video scene |
engine.block.create(blockType=DesignBlockType.Audio) | Create a new audio block |
engine.block.appendChild(parent=_, child=_) | Attach a page or audio block to its parent |
engine.block.setWidth(block=_, value=_) | Set the page width |
engine.block.getWidth(block=_) | Read the page width |
engine.block.setHeight(block=_, value=_) | Set the page height |
engine.block.getHeight(block=_) | Read the page height |
engine.block.setString(block=_, property="audio/fileURI", value=_) | Set the audio source URI |
engine.block.getString(block=_, property="audio/fileURI") | Read the audio source URI |
engine.block.forceLoadAVResource(block=_) | suspend; load audio metadata before reading duration |
engine.block.getAVResourceTotalDuration(block=_) | Read the source audio duration in seconds |
engine.block.setTimeOffset(block=_, offset=_) | Set when the audio starts on the page timeline |
engine.block.getTimeOffset(block=_) | Read when the audio starts on the page timeline |
engine.block.setDuration(block=_, duration=_) | Set how long the audio block plays |
engine.block.getDuration(block=_) | Read how long a page or audio block plays |
engine.block.setVolume(block=_, volume=_) | Set volume from 0.0 to 1.0 |
engine.block.getVolume(block=_) | Read the current volume |
engine.asset.findAllSources() | List registered asset source IDs |
engine.asset.addLocalSourceFromJSON(contentUri=_) | suspend; register an audio asset source from a content JSON file |
engine.asset.findAssets(sourceId=_, query=_) | suspend; query audio assets |
engine.block.findByType(type=DesignBlockType.Audio) | Find all audio blocks in the scene |
engine.block.destroy(block=_) | Remove an audio block |