Export video compositions as WebM files with VP8, VP9 or AV1 video and Opus or Vorbis audio, and keep the transparency of the page.
WebM is an open video format. Its codecs are royalty-free, so you can encode and publish them without a patent license. The engine bundles the VP8, VP9, AV1, Opus and Vorbis encoders, so a WebM export works on every Android device. Where the device has a hardware encoder for VP8 or VP9, the engine uses it.
This guide covers how to export a page to WebM, choose the codecs, keep the transparency of the page, and write the result to a file.
Export to WebM#
Call engine.block.exportVideo(...) with a page block, the timeline range and MimeType.WEBM. The method returns a
ByteBuffer with the WebM file.
suspend fun exportWebm( engine: Engine, page: DesignBlock, pageDuration: Double,): ByteBuffer { val videoBytes = engine.block.exportVideo( block = page, timeOffset = 0.0, duration = pageDuration, mimeType = MimeType.WEBM, progressCallback = { progress -> Log.i( "ExportToWebmGuide", "Encoded ${progress.encodedFrames} of ${progress.totalFrames} frames", ) }, )
check(videoBytes.hasRemaining()) { "WebM export is empty" } return videoBytes}Without options, the export encodes VP9 video and Opus audio. Every other ExportVideoOptions value, such as
targetWidth, frameRate and videoBitrate, works the same as for an MP4 export. So do
progress, cancellation and partial export.
Choose the Codecs#
Set videoCodec and audioCodec in ExportVideoOptions to choose the codecs. A WebM file holds VP8, VP9 or
AV1 video and OPUS or VORBIS audio.
suspend fun exportWebmWithCodecs( engine: Engine, page: DesignBlock, pageDuration: Double,): ByteBuffer { val options = ExportVideoOptions( videoCodec = VideoCodec.VP8, audioCodec = AudioCodec.VORBIS, videoBitrate = 4_000_000, )
val videoBytes = engine.block.exportVideo( block = page, timeOffset = 0.0, duration = pageDuration, mimeType = MimeType.WEBM, progressCallback = {}, options = options, )
check(videoBytes.hasRemaining()) { "VP8 WebM export is empty" } return videoBytes}- VP8 is the oldest of the three video codecs, and almost every player decodes it.
- AV1 makes the smallest file at the same quality, but it takes the longest to encode.
- A codec that WebM cannot hold, such as
H264orAAC, fails the export. The engine does not change the codec for you.
Keep the Transparency#
Set exportAlpha = true to keep the transparent areas of the page. The WebM file then has a second video stream with
the transparency. Only VP8 and VP9 keep it.
suspend fun exportWebmWithAlpha( engine: Engine, page: DesignBlock, pageDuration: Double,): ByteBuffer { // Hide the page background, so only the blocks on the page are opaque. engine.block.setFillEnabled(page, enabled = false) val background = engine.block.getChildren(page).first() engine.block.setVisible(background, visible = false)
try { val videoBytes = engine.block.exportVideo( block = page, timeOffset = 0.0, duration = pageDuration, mimeType = MimeType.WEBM, progressCallback = {}, options = ExportVideoOptions( videoCodec = VideoCodec.VP9, exportAlpha = true, ), )
check(videoBytes.hasRemaining()) { "alpha WebM export is empty" } return videoBytes } finally { engine.block.setVisible(background, visible = true) engine.block.setFillEnabled(page, enabled = true) }}- Hide the page fill and every block that covers the whole page. Otherwise no area of the page is transparent.
exportAlphawithAV1or withMimeType.MP4fails the export.- Whether a player shows the transparency depends on the player.
Handle Export Results#
The returned ByteBuffer stays in memory. Write it to app storage, upload it, or pass it to another Android API.
suspend fun writeWebmToTempFile(videoBytes: ByteBuffer): File = withContext(Dispatchers.IO) { val outputFile = File.createTempFile("export-to-webm-", ".webm") val videoData = videoBytes.asReadOnlyBuffer() outputFile.outputStream().channel.use { channel -> while (videoData.hasRemaining()) { channel.write(videoData) } }
check(outputFile.length() > 0L) { "WebM output file is empty" } outputFile}Troubleshooting#
- The export fails with
ENCODE.VIDEO_CODEC_CONTAINER_MISMATCHorENCODE.AUDIO_CODEC_CONTAINER_MISMATCH: The codec does not fit the file type. UseVP8,VP9orAV1withOPUSorVORBISfor WebM, or leave the codecs atAUTO. - The export fails with
ENCODE.VIDEO_ALPHA_UNSUPPORTED: UseVP8orVP9withMimeType.WEBMwhenexportAlphaistrue. - The transparent areas are black: Set
exportAlpha, hide the page fill and the background blocks, and play the file in a player that reads the transparency stream. - The export is slow: AV1 encodes in software. Use VP9 or VP8, or lower
targetWidth,targetHeightandframeRate.
API Reference#
| API | Description |
|---|---|
engine.block.exportVideo(block=_, timeOffset=_, duration=_, mimeType=_, progressCallback=_, options=_) |
Exports a page timeline to a video ByteBuffer. |
ExportVideoOptions(videoCodec=_, audioCodec=_, exportAlpha=_, videoBitrate=_) |
Selects the codecs, the transparency stream and the bitrate. |
engine.block.setFillEnabled(block=_, enabled=_) |
Hides the page fill before a transparent export. |
engine.block.setVisible(block=_, visible=_) |
Hides a background block before a transparent export. |
WebM Export Options#
| Option | Default | Description |
|---|---|---|
mimeType |
Required | MimeType.WEBM for a WebM file. |
videoCodec |
VideoCodec.AUTO |
VP8, VP9 or AV1. AUTO picks VP9 for WebM. |
audioCodec |
AudioCodec.AUTO |
OPUS or VORBIS. AUTO picks Opus for WebM. |
exportAlpha |
false |
Keeps the transparency of the page. Only VP8 and VP9. |
Next Steps#
- Export to MP4 - Export with H.264 or HEVC, track progress and cancel an export
- Export Overview - Compare all supported export formats
- Partial Export - Export specific blocks or timeline segments