Search Docs
Loading...
Skip to content

Export for Social Media

Export vertical video designs for social media platforms with the correct dimensions, format, and quality settings.

6 mins
estimated time
GitHub

Short-form vertical video uses a 9:16 aspect ratio. Instagram Reels, TikTok, and YouTube Shorts commonly use 1080×1920 pixels for that format. This guide creates a vertical video scene, exports it as MP4, and tracks frame progress while the export runs.

Creating a Scene#

Create a video scene and use pixels as the design unit so the page dimensions match the delivery size. Add a 1080×1920 page, which is the block exported later.

val scene = engine.scene.createForVideo()
engine.scene.setDesignUnit(DesignUnit.PIXEL)
val page = engine.block.create(DesignBlockType.Page)
engine.block.appendChild(parent = scene, child = page)
engine.block.setWidth(block = page, value = 1080F)
engine.block.setHeight(block = page, value = 1920F)

engine.scene.createForVideo() enables timeline behavior for the scene. engine.scene.setDesignUnit(DesignUnit.PIXEL) makes the width and height values line up with the requested social video resolution.

Adding a Video#

Each video clip is a graphic block with a rectangle shape and a video fill. Use ContentFillMode.COVER when the source video should fill the clip frame, cropping edges if needed.

private data class SocialMediaVideoClip(
val block: DesignBlock,
val fill: DesignBlock,
)
private fun createSocialMediaVideoClip(
engine: Engine,
videoUri: Uri,
): SocialMediaVideoClip {
val clip = engine.block.create(DesignBlockType.Graphic)
engine.block.setShape(block = clip, shape = engine.block.createShape(type = ShapeType.Rect))
engine.block.setContentFillMode(block = clip, mode = ContentFillMode.COVER)
val videoFill = engine.block.createFill(FillType.Video)
engine.block.setUri(
block = videoFill,
property = "fill/video/fileURI",
value = videoUri,
)
engine.block.setFill(block = clip, fill = videoFill)
return SocialMediaVideoClip(block = clip, fill = videoFill)
}

Add the clip to a track and make the track fill the page.

val clip = createSocialMediaVideoClip(
engine = engine,
videoUri = Uri.parse("https://img.ly/static/ubq_video_samples/bbb.mp4"),
)
val track = engine.block.create(DesignBlockType.Track)
engine.block.appendChild(parent = page, child = track)
engine.block.appendChild(parent = track, child = clip.block)
engine.block.fillParent(track)

For groups and tracks, fillParent(...) also sizes child graphics against the nearest non-group, non-track parent, so the unsized clip fills the page frame.

Loading Media and Setting Duration#

Load the media resource before export so duration metadata is available. The sample exports one second of video and applies the same duration to the clip and the page.

engine.block.forceLoadAVResource(block = clip.fill)
// Keep this sample compact by exporting at most one second of source media.
val exportDuration = 1.0.coerceAtMost(engine.block.getAVResourceTotalDuration(block = clip.fill))
check(exportDuration > 0.0) { "The source video must contain playable media." }
engine.block.setDuration(block = clip.block, duration = exportDuration)
engine.block.setDuration(block = page, duration = exportDuration)

Configuring Export Options#

ExportVideoOptions controls the encoded output. For short-form vertical video, export to 1080×1920 at 30 frames per second with an 8 Mbps video bitrate.

val exportOptions = ExportVideoOptions(
targetWidth = 1080F,
targetHeight = 1920F,
// 30 fps is a common default for short-form vertical video.
frameRate = 30F,
// 8 Mbps balances quality and upload size for short-form video.
videoBitrate = 8_000_000,
)

Key video export settings:

  • targetWidth / targetHeight: Output resolution, 1080×1920 for vertical video.
  • frameRate: Target export frame rate in Hz, commonly 30 for social video.
  • videoBitrate: Video bitrate in bits per second; 8 Mbps balances quality and upload size for short-form video.

Higher bitrates can improve quality but increase the file size. Set videoBitrate to 0 when you want CE.SDK to choose a bitrate automatically.

Exporting Videos#

Export the page with engine.block.exportVideo(...). Use MimeType.MP4 for broad platform compatibility, pass the full page duration, and attach the export options. The callback reports each progress event before forwarding it to the caller’s observer, so observing progress does not replace the reporting path.

val progressCallback: (ExportVideoProgress) -> Unit = { progress ->
reportExportProgress(progress)
progressObserver(progress)
}
val videoData = engine.block.exportVideo(
block = page,
// Start at the beginning of the page timeline.
timeOffset = 0.0,
duration = engine.block.getDuration(block = page),
mimeType = MimeType.MP4,
progressCallback = progressCallback,
options = exportOptions,
)
check(videoData.remaining() > 0) { "The exported MP4 data must not be empty." }

The Android API returns a ByteBuffer containing the encoded MP4 data. The sample verifies that the buffer is non-empty before saving it.

Tracking Export Progress#

Video exports run across multiple engine update iterations. The callback receives ExportVideoProgress with these frame counts:

  • renderedFrames: Frames rendered by the engine.
  • encodedFrames: Frames written by the encoder.
  • totalFrames: Total frames expected for the export.

The reporting function calculates progress from encodedFrames / totalFrames and guards against totalFrames == 0 before dividing.

private fun reportExportProgress(progress: ExportVideoProgress) {
if (progress.totalFrames > 0) {
val percent = (progress.encodedFrames.toFloat() / progress.totalFrames * 100).toInt()
Log.i(
"SocialMediaExport",
"Encoded $percent% (${progress.encodedFrames}/${progress.totalFrames} frames)",
)
}
}

Use the forwarded observer to update your app’s progress UI or collect export metrics while preserving the same reporting path.

Saving the Exported Video#

Write a read-only view of the returned ByteBuffer to an .mp4 file when your app needs to hand the result to a share sheet, upload pipeline, or media storage flow.

val outputFile = withContext(Dispatchers.IO) {
val file = File.createTempFile("social-media-export-", ".mp4")
file.outputStream().use { output ->
val buffer = videoData.asReadOnlyBuffer()
while (buffer.hasRemaining()) {
output.channel.write(buffer)
}
}
file
}
check(outputFile.length() > 0L) { "The exported MP4 file must not be empty." }

For uploads, stream the same buffer data to your app’s storage client instead of writing a temporary file first. The sample returns ownership of its temporary file to the caller. Persist it if it must outlive the current operation, and delete it after sharing or uploading.

API Reference#

Android API Purpose
engine.scene.createForVideo() Create a scene with timeline support.
engine.scene.setDesignUnit(designUnit=_) Set the scene unit used by page dimensions.
engine.block.create(blockType=_) Create page, track, and graphic blocks.
engine.block.createShape(type=_) Create the rectangular clip shape.
engine.block.setShape(block=_, shape=_) Assign the shape to the video graphic.
engine.block.setContentFillMode(block=_, mode=_) Control how the video fills the graphic frame.
engine.block.createFill(fillType=_) Create the video fill.
engine.block.setUri(block=_, property="fill/video/fileURI", value=_) Set the source URI on the video fill.
engine.block.setFill(block=_, fill=_) Attach the video fill to the graphic.
engine.block.appendChild(parent=_, child=_) Attach scene, page, track, and clip blocks.
engine.block.fillParent(block=_) Resize a block to its parent frame.
engine.block.setWidth(block=_, value=_) Set the page width.
engine.block.setHeight(block=_, value=_) Set the page height.
engine.block.forceLoadAVResource(block=_) Load video metadata before duration reads and export.
engine.block.getAVResourceTotalDuration(block=_) Read the source media duration in seconds.
engine.block.setDuration(block=_, duration=_) Set clip and page playback duration in seconds.
engine.block.getDuration(block=_) Read the page duration passed to export.
engine.block.exportVideo(block=_, timeOffset=_, duration=_, mimeType=_, progressCallback=_, options=_, onPreExport=_, uriResolver=_) Export a page timeline as MP4 bytes.

Export Options (Videos)#

Option Type Description
targetWidth Float? Output width in pixels when used with targetHeight.
targetHeight Float? Output height in pixels when used with targetWidth.
frameRate Float Target export frame rate in Hz.
videoBitrate Int Video bitrate in bits per second, or 0 for automatic selection.
audioBitrate Int Audio bitrate in bits per second, or 0 for automatic selection.
allowTextOverhang Boolean Include glyph overhang bounds to avoid clipping text during export.

Next Steps#

  • Options — Explore export options, supported formats, and configuration features for sharing or rendering output.