Skip to content

Repository files navigation

JitPack

VideoCompressor

A lightweight Android library for compressing video files using MediaCodec or optimizing MP4 files for fast-start playback without compression.

Based on the LightCompressor and uses some of its parts. The API is inspired by Android ImageDecoder.

Features

  • Compress video files using H.264 codecs via MediaCodec
  • Optimize MP4 files for fast-start playback without compression
  • Inspect video metadata and apply settings before processing
  • Coroutines and cancellation
  • Compatible with Android 5.0+ (API 21+)

Usage

Add the JitPack repository to your project level build.gradle.kts:

allprojects {
    repositories {
        google()
        maven(url = "https://jitpack.io")
    }
}

Add this to your app build.gradle.kts:

dependencies {
    implementation("com.github.pachca:VideoCompressor:v2.0.3")
}
scope.launch {
    val result = VideoCompressor.compress(
        context = context,

        // Input File
        input = input,

        // Output file (make sure the app can actually write at this path)
        output = output,

        // Callback is fired before the actual compression.
        // Allows setting parameters like video resolution and bitrate.
        onMetadataDecoded = { compressor, metadata ->
            
            // Return a CompressionSettings instance to proceed or null to cancel
            CompressionSettings.Builder()
                .setTargetSize(
                    width = metadata.actualWidth / 2,
                    height = metadata.actualHeight / 2
                )
                .setBitrate(2_000_000)
                .setFastStart(true)
                .allowSizeAdjustments(true)
                .setEncoderSelectionMode(EncoderSelectionMode.TRY_ALL)
                .build()
        }
    )
}

Fast-start-only processing

Use fast-start-only mode to skip compression and move MP4 metadata before its media data. Target dimensions and other compression settings are not required. Input and output must be different files.

Metadata.isFastStartOptimized reports whether the input already has the required atom order. Return null from the metadata callback to avoid creating an unnecessary output copy. Because null produces CompressionResult.Cancelled, track this decision separately from other forms of cancellation and continue using the input file.

scope.launch {
    var useInput = false
    val result = VideoCompressor.compress(
        context = context,
        input = input,
        output = output,
        onMetadataDecoded = { _, metadata ->
            if (metadata.isFastStartOptimized) {
                useInput = true
                null
            } else {
                CompressionSettings.Builder()
                    .setFastStartOnly(true)
                    .build()
            }
        }
    )

    val processedFile = when {
        useInput -> input
        result == CompressionResult.Success -> output
        else -> null
    }
}

If a separate output file is required even when the input is already optimized, always return fast-start-only settings. The input will then be copied unchanged.

Compatibility

Minimum Android SDK: VideoCompressor requires a minimum API level of 21.

What's next?

Credits

Telegram for Android.

LightCompressor - original library.

About

A powerful and easy-to-use video compression library for Android via MediaCodec

Resources

Stars

19 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages