LightCompressor

repository·master·Indexed 20 days ago

https://github.com/abedelazizshe/lightcompressor

An Android video compression library based on the Telegram Android project. It utilizes the MediaCodec API to reduce video bitrate and dimensions to create smaller MP4 files. The library supports asynchronous processing via VideoCompressor.start(), customizable quality settings through the Configuration class, and various output options via the StorageConfiguration interface (AppSpecific, Shared, and Cache storage).

Tokens
3.2K
Snippets
8
Records
10
Agent score
20%

What's inside LightCompressor

  1. Manage video storage with StorageConfiguration

    master

    The StorageConfiguration interface determines where the compressed video is saved. The library provides several built-in implementations:

    1. AppSpecificStorageConfiguration

    Saves the file in the app's private storage directory.

    • subFolderName: (Optional) A subfolder name within the app's specific storage.

    2. SharedStorageConfiguration

    Saves the file in public directories accessible by other apps.

    • saveAt: The directory to save in. Must be one of: SaveLocation.pictures, SaveLocation.movies, or SaveLocation.downloads. (Default is movies).
    • subFolderName: (Optional) A subfolder name within the shared directory.

    3. CacheStorageConfiguration

    Saves the file in the system-defined cache directory.

    4. Custom Implementation

    If none of the above fit, you can implement the StorageConfiguration interface yourself to define exactly how and where the file is created.

    class FullyCustomizedStorageConfiguration(
    ) : StorageConfiguration {
        override fun createFileToSave(
            context: Context,
            videoFile: File,
            fileName: String,
            shouldSave: Boolean
        ): File = ??? // Your custom logic
    }
  2. How VideoQuality affects bitrate

    master

    The VideoQuality enum determines the compression ratio by multiplying the original bitrate by a specific factor:

    • VERY_HIGH: original-bitrate * 0.6
    • HIGH: original-bitrate * 0.4
    • MEDIUM: original-bitrate * 0.3
    • LOW: original-bitrate * 0.2
    • VERY_LOW: original-bitrate * 0.1
  3. Install LightCompressor via Gradle

    master

    To use LightCompressor, follow these steps to configure your Gradle files:

    1. Project-level build.gradle: Add the JitPack repository.
    2. Module-level build.gradle: Add the LightCompressor dependency.
    3. Kotlin Version: Ensure your Kotlin version is 1.8.21 or higher.
    4. Coroutines: Import Kotlin coroutine dependencies to support the library's asynchronous operations.

    If you encounter repository resolution issues, ensure settings.gradle is configured to allow JitPack within dependencyResolutionManagement.

    ### Project-level build.gradle
    ```groovy
    allprojects {
        repositories {
            maven { url 'https://jitpack.io' }
        }
    }

    Module-level build.gradle

    implementation 'com.github.AbedElazizShe:LightCompressor:1.3.3'

    Coroutine dependencies

    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Version.coroutines}"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:${Version.coroutines}"

    settings.gradle (if needed)

    dependencyResolutionManagement {
        repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
        repositories {
            google()
            mavenCentral()
            maven { url 'https://jitpack.io' }
        }
    }
  4. Configure Android Storage Permissions

    master

    Depending on the Android API level, you must request the appropriate permissions in your AndroidManifest.xml and handle runtime permissions in your code.

    • API < 29: Requires READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE.
    • API >= 29 (up to 32): Requires READ_EXTERNAL_STORAGE with maxSdkVersion="32".
    • API >= 33 (Tiramisu): Requires READ_MEDIA_VIDEO.

    Runtime Permission Logic: Use Build.VERSION.SDK_INT to check if the device is running Tiramisu (API 33) or lower to request the correct permission.

    ### AndroidManifest.xml
    
    **API < 29**
    ```xml
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="28"
        tools:ignore="ScopedStorage" />

    API >= 29

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
        android:maxSdkVersion="32"/>

    API >= 33

    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>

    Runtime Permission Check

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
         // request READ_MEDIA_VIDEO run-time permission
     } else {
         // request WRITE_EXTERNAL_STORAGE run-time permission
     }
  5. Configure video output location with StorageConfiguration

    master

    The StorageConfiguration interface determines where the compressed video file is saved. You can choose between internal app storage, shared public storage, or temporary cache storage.

    Implementations

    1. AppSpecificStorageConfiguration

    Saves files to the application's internal filesDir. This is private to your app.

    • subFolderName: (Optional) A folder within filesDir to organize files.

    2. SharedStorageConfiguration

    Saves files to public directories (Downloads, Pictures, or Movies) accessible by other apps. This implementation handles Scoped Storage requirements for Android 10 (API 29) and above.

    • saveAt: A SaveLocation enum specifying the directory:
      • SaveLocation.downloads -> Environment.DIRECTORY_DOWNLOADS
      • SaveLocation.pictures -> Environment.DIRECTORY_PICTURES
      • SaveLocation.movies -> Environment.DIRECTORY_MOVIES
    • subFolderName: (Optional) A sub-folder within the chosen public directory.

    3. CacheStorageConfiguration

    Saves files as temporary files in the system cache. These files may be deleted by the system at any time.

    // Example: Saving to public Downloads folder in a subfolder
    val storageConfig = SharedStorageConfiguration(
        saveAt = SaveLocation.downloads,
        subFolderName = "MyCompressedVideos"
    )
    
    // Example: Saving to private app storage
    val privateStorage = AppSpecificStorageConfiguration(subFolderName = "exports")
    
    // Example: Using cache
    val cacheStorage = CacheStorageConfiguration()
  6. Compress videos with VideoCompressor.start()

    master

    The primary way to use the library is by calling VideoCompressor.start(). This method processes a list of video URIs asynchronously and provides feedback via a CompressionListener.

    Key Parameters:

    • context: The application context.
    • uris: A List<Uri> of the source videos.
    • isStreamable: If true, optimizes the output for streaming.
    • storageConfiguration: Defines where the file is saved (see StorageConfiguration).
    • configureWith: A Configuration object defining quality, bitrate, and resizing.
    • listener: A CompressionListener to handle lifecycle events.

    Important Notes:

    • All listener callbacks return an index corresponding to the position of the URI in the input list.
    • onSuccess provides the file path of the compressed video.
    • Threading: Callbacks like onProgress run on a worker thread. You must use runOnUiThread if you want to update the UI or show Toasts.
    VideoCompressor.start(
       context = applicationContext,
       uris = List<Uri>,
       isStreamable = false, 
       storageConfiguration = SharedStorageConfiguration(
           saveAt = SaveLocation.movies,
           subFolderName = "my-videos"
       ),
       configureWith = Configuration(
          videoNames = listOf<String>(),
          quality = VideoQuality.MEDIUM,
          isMinBitrateCheckEnabled = true,
          videoBitrateInMbps = 5,
          disableAudio = false,
          resizer = VideoResizer.matchSize(360, 480)
       ),
       listener = object : CompressionListener {
           override fun onProgress(index: Int, percent: Float) {
              runOnUiThread { /* Update UI */ }
           }
           override fun onStart(index: Int) {}
           override fun onSuccess(index: Int, size: Long, path: String?) {}
           override fun onFailure(index: Int, failureMessage: String) {}
           override fun onCancelled(index: Int) {}
       }
    )
  7. Configure video compression settings with Configuration

    master

    The Configuration data class defines how a video should be compressed. You can specify quality, bitrate, audio settings, and resolution resizing.

    Properties

    • quality: Sets the compression level using VideoQuality (e.g., VideoQuality.MEDIUM).
    • isMinBitrateCheckEnabled: If true, ensures the bitrate doesn't drop below a minimum threshold.
    • videoBitrateInMbps: An optional integer to set a specific bitrate in Mbps.
    • disableAudio: If true, the audio track will be removed from the output.
    • resizer: An optional VideoResizer to control output dimensions. Use VideoResizer.auto for automatic resizing or VideoResizer.matchSize(width, height) for specific dimensions.
    • videoNames: A list of strings representing the names for the output files.
    val config = Configuration(
        quality = VideoQuality.HIGH,
        isMinBitrateCheckEnabled = true,
        videoBitrateInMbps = 5,
        disableAudio = false,
        resizer = VideoResizer.auto,
        videoNames = listOf("compressed_video")
    )
  8. Configure video compression settings

    master

    The Configuration object allows you to fine-tune the compression process. Use these keys to control quality, bitrate, and dimensions.

    KeyTypeDescription
    qualityVideoQualitySets target bitrate based on original. Options: VERY_HIGH, HIGH, MEDIUM, LOW, VERY_LOW.
    isMinBitrateCheckEnabledBooleanIf true, prevents compression if the video bitrate is below 2mbps to avoid quality loss.
    videoBitrateInMbpsInt?A custom bitrate value in Mbps.
    disableAudioBooleanIf true, generates a video without an audio track. Default is false.
    resizerVideoResizerFunction to resize dimensions. Default is VideoResizer.auto.