- Overview
- Prepare export flow
- Prepare effects
- Get export flow manager
- Manage export execution
- Handle export result
- Create slideshow
This guide helps you quickly integrate the Export API into your project. You'll learn to export media files (video, audio, GIF) with various effects and resolutions.
Export API produces video as .mp4 files.
Important Performance Considerations Export is CPU/GPU intensive. Execution time depends on:
- Video duration
- Number of video/audio sources
- Number and complexity of effects
- Number of exported files
- Device hardware capabilities
| Mode | Description |
|---|---|
| Foreground | User waits on progress screen until completion |
| Background | User can navigate away; notification sent when done |
Corresponding implementations:
Create a class implementing ExportParamsProvider to define what media files to export.
Example: Export one HD video (720p) with watermark and effects:
private class CustomExportParamsProvider(
private val exportDir: Uri,
private val mediaFileNameHelper: MediaFileNameHelper,
private val watermarkBuilder: WatermarkBuilder
) : ExportParamsProvider {
override fun provideExportParams(
effects: Effects,
videoRangeList: VideoRangeList,
musicEffects: List<MusicEffect>,
videoVolume: Float
): List<ExportParams> {
val exportSessionDir = exportDir.toFile().apply {
// Export dir must be created
mkdirs()
}
// Specify name for your exported video. Do not use ext i.e. .mp4
val exportVideoFileName = mediaFileNameHelper.generateExportName() + "_watermark"
val paramsHdWithWatermark =
ExportParams.Builder(VideoResolution.Exact.HD) // Video Quality resolution
.effects(effects.withWatermark(watermarkBuilder, WatermarkAlignment.BottomRight(marginRightPx = 16.toPx)))
.fileName(exportVideoFileName)
.debugEnabled(true)
.videoRangeList(videoRangeList)
.destDir(exportSessionDir)
.musicEffects(musicEffects)
.volumeVideo(videoVolume)
.build()
return listOf(paramsHdWithWatermark)
}
}set file name,
ExportParams.Builder(VideoResolution.Exact.HD) // Video Quality resolution
.effects(effects.withWatermark(watermarkBuilder, WatermarkAlignment.BottomRight(marginRightPx = 16.toPx)))
+ .fileName(exportVideoFileName)
.debugEnabled(true)
.videoRangeList(videoRangeList)
.destDir(exportSessionDir)
.musicEffects(musicEffects)
.volumeVideo(videoVolume)
.build()set watermark to bottom right of the video,
ExportParams.Builder(VideoResolution.Exact.HD) // Video Quality resolution
+ .effects(effects.withWatermark(watermarkBuilder, WatermarkAlignment.BottomRight(marginRightPx = 16.toPx)))
.fileName(exportVideoFileName)
.debugEnabled(true)
.videoRangeList(videoRangeList)
.destDir(exportSessionDir)
.musicEffects(musicEffects)
.volumeVideo(videoVolume)
.build()Set video effects and audio tracks as MusicEffect to ExportParams.
Then when export starts these values are passed to implementation of ExportParamsProvider.
private class CustomExportParamsProvider(
private val exportDir: Uri,
private val mediaFileNameHelper: MediaFileNameHelper,
private val watermarkBuilder: WatermarkBuilder
) : ExportParamsProvider {
override fun provideExportParams(
+ effects: Effects,
videoRangeList: VideoRangeList,
+ musicEffects: List<MusicEffect>,
videoVolume: Float
): List<ExportParams> {
...
val paramsHdWithWatermark =
ExportParams.Builder(VideoResolution.Exact.HD) // Video Quality resolution
+ .effects(effects.withWatermark(watermarkBuilder, WatermarkAlignment.BottomRight(marginRightPx = 16.toPx)))
+ .musicEffects(musicEffects)
...
.build()
...
}
}Other properties
ExportParams.Builder class requires just single parameter resolution, others are optional:
fileName(fileName: String)- name of exported video file.effects(effects: Effects)- list of effects to export in video.videoRangeList(videoRangeList: VideoRangeList)- video sources to export target videomusicEffects(musicEffects: List<MusicEffect>)- music effects for export video i.e. audio tracks you want to apply on top of videodestDir(destDir: File)- where to store exported videoextraAudioFile(extraAudioTrack: Uri)- where to store extra audio file from videovolumeVideo(volume: Float)- set audio volume in video
Add your provider in VideoEditorApiModule
factory<ExportParamsProvider> {
CustomExportParamsProvider(
exportDir = get(named("exportDir")),
mediaFileNameHelper = get(),
watermarkBuilder = get()
)
}Choose and configure export mode in VideoEditorApiModule.
// Foreground export
single<ExportFlowManager>(named("foregroundExportFlowManager")) {
ForegroundExportFlowManager(
exportDataProvider = get(),
sessionParamsProvider = get(),
exportSessionHelper = get(),
exportDir = get(named("exportDir")),
publishManager = get(),
errorParser = get(),
mediaFileNameHelper = get(),
exportBundleProvider = get()
)
}
// Background export similarly with BackgroundExportFlowManager📌 Full CustomExportParamsProvider implementation
Two approaches to prepare effects for export:
- From Playback API - User adds effects during editing; pass same effects to export
- Isolated preparation - Create effects programmatically without UI
See Manage effects guide for detailed effect creation.
Access ExportFlowManager instance:
+ import org.koin.android.ext.android.inject
class SampleActivity : AppCompatActivity() {
+ private val exportFlowManager: ExportFlowManager by inject(named("foregroundExportFlowManager"))
...
} viewModel {
ExportViewModel(
+ foregroundExportFlowManager = get(named("foregroundExportFlowManager"))
)
}❗ Important
Use Koin's named qualifier when using multiple ExportFlowManager instances.
Convert video URIs to ExportTaskParams:
fun startExport(
context: Context,
videosUri: List<Uri>
) {
exportFlowManager.startExport(createExportParams(context, videosUri))
}
fun createExportParams(
context: Context,
videosUri: List<Uri>
): ExportTaskParams {
val videoRanges = prepareVideoRages(videosUri)
val totalVideoDuration = videoRanges.data.sumOf { it.durationMs }
val coverFrameSize = Size(720, 1280) // Cover size resolution
val effects = ... // Provide list of effects to export
val musicEffects = ... // Provide list of audio tracks to export
return ExportTaskParams(
videoRanges = videoRanges,
effects = effects,
musicEffects = musicEffects,
videoVolume = 1F,
coverFrameSize = coverFrameSize,
aspect = AspectRatio(9.0 / 16)
)
}
fun prepareVideoRages(
context: Context,
videosUri: List<Uri>
): VideoRangeList {
val videoRecords = videosUri.map { fileUri ->
val videoDuration = DurationExtractor().extractDurationMilliSec(context, fileUri)
val videoSpeed = 1f
VideoRecordRange(
sourceUri = fileUri, //mandatory, uri of video file
durationMs = videoDuration, //mandatory, duration of video
speed = videoSpeed, //mandatory, video playback speed
playFromMs = 0, //optional, by default equals 0
playToMs = videoDuration, //optional, by default equals duration of video,
rotation = Rotation.ROTATION_0, //optional, by default ROTATION_0
type = VideoSourceType.GALLERY, //mandatory, type of video source (gallery, camera, slideshow)
pipApplied = false
)
}
return VideoRangeList(videoRecords)
}// Foreground
foregroundExportFlowManager.stopExport()
// Background
backgroundExportFlowManager.stopExport()Observe export results using LiveData:
exportFlowmanager.resultData.observe(this, exportResultObserver)Implement observer:
val exportResultObserver = Observer<ExportResult> { exportResult ->
when (exportResult) {
is ExportResult.Progress -> {
// Export execution is in progress
}
is ExportResult.Success -> {
// Export execution completed successfully
// For example, let's take the first exported video. The number of exported video depends on your implementation in ExportParamsProvider
val exportedVideo = exportResult.videoList.first().sourceUri
Log.d(TAG, "Export video finished successfully = $exportedVideo")
}
is ExportResult.Error -> {
// Export execution failed
}
is ExportResult.Inactive, is ExportResult.Stopped -> {
// Export execution stopped or inactive
}
}
}📌 Complete example in ExportActivity
Generate video from images (with optional animation)..
❗ Important
Slideshows don't support audio tracks or video effects.
val videoFHD = Size(1080, 1920)
val sources = imageUriList.map { uri ->
SlideShowSource.File(
durationMs = 3000L, // Each image: 3 seconds
source = uri
)
}
val params = SlideShowTask.Params.create(
context = context,
size = videoFHD,
destFile = File(...), // Output location
sources = sources
)
try {
SlideShowTask.makeVideo(params)
// Success - no exception thrown
} catch (e: Exception) {
// Handle error
}