Skip to content

Quick start

This exports one clip with the Upload preset (1080p at 4 Mbps in H.264, tone mapped to SDR) to a temporary file. It assumes the filmstrip artifact from Installation.

val filmstrip =
Filmstrip {
allBackends()
}
val composition =
compositionOf {
clip(MediaSource.of(path))
}
val plan =
when (val verdict = filmstrip.plan(composition, ExportSpec.Upload)) {
is Verdict.Capable -> verdict.plan
is Verdict.Degraded -> verdict.plan
is Verdict.Incapable -> return println("Can't export on this device: ${verdict.reasons}")
}
filmstrip.export(plan, MediaSink.temporary()).collect { status ->
when (status) {
is ExportStatus.Progress -> println("${(status.fraction * 100).toInt()}%")
is ExportStatus.Success -> println("Wrote ${status.output}")
is ExportStatus.Failure -> println("Failed: ${status.reasons}")
else -> Unit
}
}

What each step does:

  1. Filmstrip { allBackends() } builds one instance with this target’s export backend, the player and the built-in effects registered. Keep it for the life of your app or your DI graph.
  2. compositionOf { } describes the edit. It’s plain data, so it can be built anywhere and handed to any call.
  3. plan asks what this device will do with the edit before anything is decoded. Capable runs it as written, Degraded runs it with changes it lists, and Incapable says why it can’t.
  4. export runs the plan and reports progress as a flow. Cancel the collecting scope to cancel the export.

Next, Setup covers registering backends one by one, and Export covers everything a plan and a status can tell you.