Git Product home page Git Product logo

lightcompressor's Introduction

JitPack

LightCompressor

LightCompressor can now be used in Flutter through light_compressor plugin.

A powerful and easy-to-use video compression library for android uses MediaCodec API. This library generates a compressed MP4 video with a modified width, height, and bitrate (the number of bits per seconds that determines the video and audio files’ size and quality). It is based on Telegram for Android project.

The general idea of how the library works is that, extreme high bitrate is reduced while maintaining a good video quality resulting in a smaller size.

I would like to mention that the set attributes for size and quality worked just great in my projects and met the expectations. It may or may not meet yours. I’d appreciate your feedback so I can enhance the compression process.

LightCompressor is now available in iOS, have a look at LightCompressor_iOS.

Change Logs

What's new in 1.3.2

  • Bugs fixes.
  • Thanks to vitorpamplona, Fixes a crash when the user tries a video with malformed bitrate information
  • Thanks to amrreda1995 for Force compressing code to run in IO thread

How it works

When the video file is called to be compressed, the library checks if the user wants to set a min bitrate to avoid compressing low resolution videos. This becomes handy if you don’t want the video to be compressed every time it is to be processed to avoid having very bad quality after multiple rounds of compression. The minimum is;

  • Bitrate: 2mbps

You can pass one of a 5 video qualities; VERY_HIGH, HIGH, MEDIUM, LOW, OR VERY_LOW and the library will handle generating the right bitrate value for the output video

return when (quality) {
    VideoQuality.VERY_LOW -> (bitrate * 0.1).roundToInt()
    VideoQuality.LOW -> (bitrate * 0.2).roundToInt()
    VideoQuality.MEDIUM -> (bitrate * 0.3).roundToInt()
    VideoQuality.HIGH -> (bitrate * 0.4).roundToInt()
    VideoQuality.VERY_HIGH -> (bitrate * 0.6).roundToInt()
}

when {
   width >= 1920 || height >= 1920 -> {
      newWidth = (((width * 0.5) / 16).roundToInt() * 16)
      newHeight = (((height * 0.5) / 16f).roundToInt() * 16)
   }
   width >= 1280 || height >= 1280 -> {
      newWidth = (((width * 0.75) / 16).roundToInt() * 16)
      newHeight = (((height * 0.75) / 16).roundToInt() * 16)
   }
   width >= 960 || height >= 960 -> {
      newWidth = (((width * 0.95) / 16).roundToInt() * 16)
      newHeight = (((height * 0.95) / 16).roundToInt() * 16)
   }
   else -> {
      newWidth = (((width * 0.9) / 16).roundToInt() * 16)
      newHeight = (((height * 0.9) / 16).roundToInt() * 16)
   }
}

You can as well pass custom videoHeight, videoWidth, and videoBitrate values if you don't want the library to auto-generate the values for you. The compression will fail if height or width is specified without the other, so ensure you pass both values.

These values were tested on a huge set of videos and worked fine and fast with them. They might be changed based on the project needs and expectations.

Demo

Demo

Usage

To use this library, you must add the following permission to allow read and write to external storage. Refer to the sample app for a reference on how to start compression with the right setup.

API < 29

<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"/>
 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
     // request READ_MEDIA_VIDEO run-time permission
 } else {
     // request WRITE_EXTERNAL_STORAGE run-time permission
 }

And import the following dependencies to use kotlin coroutines

Groovy

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

Then just call [VideoCompressor.start()] and pass context, uris, isStreamable, configureWith, and either sharedStorageConfiguration OR appSpecificStorageConfiguration.

The method has a callback for 5 functions;

  1. OnStart - called when compression started
  2. OnSuccess - called when compression completed with no errors/exceptions
  3. OnFailure - called when an exception occurred or video bitrate and size are below the minimum required for compression.
  4. OnProgress - called with progress new value
  5. OnCancelled - called when the job is cancelled

Important Notes:

  • All the callback functions returns an index for the video being compressed in the same order of the urls passed to the library. You can use this index to update the UI or retrieve information about the original uri/file.
  • The source video must be provided as a list of content uris.
  • OnSuccess returns the path of the stored video.
  • If you want an output video that is optimised to be streamed, ensure you pass [isStreamable] flag is true.

Configuration values

  • VideoQuality: VERY_HIGH (original-bitrate * 0.6) , HIGH (original-bitrate * 0.4), MEDIUM (original-bitrate * 0.3), LOW (original-bitrate * 0.2), OR VERY_LOW (original-bitrate * 0.1)

  • isMinBitrateCheckEnabled: this means, don't compress if bitrate is less than 2mbps

  • videoBitrateInMbps: any custom bitrate value in Mbps.

  • disableAudio: true/false to generate a video without audio. False by default.

  • keepOriginalResolution: true/false to tell the library not to change the resolution.

  • videoWidth: custom video width.

  • videoHeight: custom video height.

AppSpecificStorageConfiguration Configuration values

  • subFolderName: a subfolder name created in app's specific storage.

SharedStorageConfiguration Configuration values

  • saveAt: the directory where the video should be saved in. Must be one of the following; [SaveLocation.pictures], [SaveLocation.movies], or [SaveLocation.downloads].
  • subFolderName: a subfolder name created in shared storage.

To cancel the compression job, just call [VideoCompressor.cancel()]

Kotlin

VideoCompressor.start(
   context = applicationContext, // => This is required
   uris = List<Uri>, // => Source can be provided as content uris
   isStreamable = false, 
   // THIS STORAGE 
   sharedStorageConfiguration = SharedStorageConfiguration(
       saveAt = SaveLocation.movies, // => default is movies
       subFolderName = "my-videos" // => optional
   ),
   // OR AND NOT BOTH
   appSpecificStorageConfiguration = AppSpecificStorageConfiguration(
       subFolderName = "my-videos" // => optional
   ),   
   configureWith = Configuration(
      videoName = listOf<String>(), /*list of video names, the size should be similar to the passed uris*/
      quality = VideoQuality.MEDIUM,
      isMinBitrateCheckEnabled = true,
      videoBitrateInMbps = 5, /*Int, ignore, or null*/
      disableAudio = false, /*Boolean, or ignore*/
      keepOriginalResolution = false, /*Boolean, or ignore*/
      videoWidth = 360.0, /*Double, ignore, or null*/
      videoHeight = 480.0 /*Double, ignore, or null*/
   ),
   listener = object : CompressionListener {
       override fun onProgress(index: Int, percent: Float) {
          // Update UI with progress value
          runOnUiThread {
          }
       }

       override fun onStart(index: Int) {
          // Compression start
       }

       override fun onSuccess(index: Int, size: Long, path: String?) {
         // On Compression success
       }

       override fun onFailure(index: Int, failureMessage: String) {
         // On Failure
       }

       override fun onCancelled(index: Int) {
         // On Cancelled
       }

   }
)

Common issues

  • Sending the video to whatsapp when disableAudio = false, won't succeed [ at least for now ]. Whatsapp's own compression does not work with LightCompressor library. You can send the video as document.

  • You cannot call Toast.makeText() and other functions dealing with the UI directly in onProgress() which is a worker thread. They need to be called from within the main thread. Have a look at the example code above for more information.

Reporting issues

To report an issue, please specify the following:

  • Device name
  • Android version
  • If the bug/issue exists on the sample app (version 1.3.2) of the library that could be downloaded at this link.

Compatibility

Minimum Android SDK: LightCompressor requires a minimum API level of 24.

How to add to your project?

Gradle

Ensure Kotlin version is 1.8.21

Include this in your Project-level build.gradle file:

Groovy

allprojects {
    repositories {
        .
        .
        .
        maven { url 'https://jitpack.io' }
    }
}

Include this in your Module-level build.gradle file:

Groovy

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

If you're facing problems with the setup, edit settings.gradle by adding this at the beginning of the file:

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

Getting help

For questions, suggestions, or anything else, email elaziz.shehadeh(at)gmail.com

Credits

Telegram for Android.

lightcompressor's People

Contributors

abedelazizshe avatar arpanbag001 avatar goooler avatar hpanahiird avatar mohammadnt avatar ow-ro avatar vitorpamplona avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lightcompressor's Issues

Crash - Compress video from videocamera

If I compress video recorded directly from the camera, a library error will occur. Only on certain devices.
Crash happens at the end of the compression

I use this intent - Intent(MediaStore.ACTION_VIDEO_CAPTURE)

Xiaomi Max
Android 7.1.1

Stacktrace:
Process: cz.skodaauto.connect.addon.carfeedback.sample, PID: 21280 java.lang.AssertionError: The given long is not in the range of uint32 (-3071) at com.coremedia.iso.IsoTypeWriter.writeUInt32(IsoTypeWriter.java:28) at com.coremedia.iso.boxes.TimeToSampleBox.getContent(TimeToSampleBox.java:75) at com.googlecode.mp4parser.AbstractBox.getBox(AbstractBox.java:142) at com.googlecode.mp4parser.BasicContainer.writeContainer(BasicContainer.java:216) at com.googlecode.mp4parser.AbstractContainerBox.getBox(AbstractContainerBox.java:88) at com.googlecode.mp4parser.BasicContainer.writeContainer(BasicContainer.java:216) at com.googlecode.mp4parser.AbstractContainerBox.getBox(AbstractContainerBox.java:88) at com.googlecode.mp4parser.BasicContainer.writeContainer(BasicContainer.java:216) at com.googlecode.mp4parser.AbstractContainerBox.getBox(AbstractContainerBox.java:88) at com.googlecode.mp4parser.BasicContainer.writeContainer(BasicContainer.java:216) at com.googlecode.mp4parser.AbstractContainerBox.getBox(AbstractContainerBox.java:88) at com.googlecode.mp4parser.BasicContainer.writeContainer(BasicContainer.java:216) at com.googlecode.mp4parser.AbstractContainerBox.getBox(AbstractContainerBox.java:88) at com.abedelazizshe.lightcompressorlibrary.MP4Builder.finishMovie(MP4Builder.java:151) at com.abedelazizshe.lightcompressorlibrary.Compressor.compressVideo(Compressor.kt:415) at com.abedelazizshe.lightcompressorlibrary.VideoCompressor$startCompression$2.invokeSuspend(VideoCompressor.kt:97) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106) at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)

use gradle import online aar , debug run failed

Duplicate class org.aspectj.runtime.reflect.AdviceSignatureImpl found in modules LightCompressor-0.7.2-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.7.2) and aspectjrt-1.8.6.jar (org.aspectj:aspectjrt:1.8.6)
Duplicate class org.aspectj.runtime.reflect.CatchClauseSignatureImpl found in modules LightCompressor-0.7.2-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.7.2) and aspectjrt-1.8.6.jar (org.aspectj:aspectjrt:1.8.6)
Duplicate class org.aspectj.runtime.reflect.CodeSignatureImpl found in modules LightCompressor-0.7.2-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.7.2) and aspectjrt-1.8.6.jar (org.aspectj:aspectjrt:1.8.6)
Duplicate class org.aspectj.runtime.reflect.ConstructorSignatureImpl found in modules LightCompressor-0.7.2-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.7.2) and aspectjrt-1.8.6.jar (org.aspectj:aspectjrt:1.8.6)
Duplicate class org.aspectj.runtime.reflect.Factory found in modules LightCompressor-0.7.2-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.7.2) and aspectjrt-1.8.6.jar (org.aspectj:aspectjrt:1.8.6)
Duplicate class org.aspectj.runtime.reflect.FieldSignatureImpl found in modules LightCompressor-0.7.2-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.7.2) and aspectjrt-1.8.6.jar (org.aspectj:aspectjrt:1.8.6)
Duplicate class org.aspectj.runtime.reflect.InitializerSignatureImpl found in modules LightCompressor-0.7.2-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.7.2) and aspectjrt-1.8.6.jar (org.aspectj:aspectjrt:1.8.6)
Duplicate class org.aspectj.runtime.reflect.JoinPointImpl found in modules LightCompressor-0.7.2-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.7.2) and aspectjrt-1.8.6.jar (org.aspectj:aspectjrt:1.8.6)
Duplicate class org.aspectj.runtime.reflect.JoinPointImpl$EnclosingStaticPartImpl found in modules LightCompressor-0.7.2-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.7.2) and aspectjrt-1.8.6.jar (org.aspectj:aspectjrt:1.8.6)
Duplicate class org.aspectj.runtime.reflect.JoinPointImpl$StaticPartImpl found in modules LightCompressor-0.7.2-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.7.2) and aspectjrt-1.8.6.jar (org.aspectj:aspectjrt:1.8.6)
Duplicate class org.aspectj.runtime.reflect.LockSignatureImpl found in modules LightCompressor-0.7.2-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.7.2) and aspectjrt-1.8.6.jar (org.aspectj:aspectjrt:1.8.6)
Duplicate class org.aspectj.runtime.reflect.MemberSignatureImpl found in modules LightCompressor-0.7.2-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.7.2) and aspectjrt-1.8.6.jar (org.aspectj:aspectjrt:1.8.6)
Duplicate class org.aspectj.runtime.reflect.MethodSignatureImpl found in modules LightCompressor-0.7.2-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.7.2) and aspectjrt-1.8.6.jar (org.aspectj:aspectjrt:1.8.6)
Duplicate class org.aspectj.runtime.reflect.SignatureImpl found in modules LightCompressor-0.7.2-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.7.2) and aspectjrt-1.8.6.jar (org.aspectj:aspectjrt:1.8.6)
Duplicate class org.aspectj.runtime.reflect.SignatureImpl$Cache found in modules LightCompressor-0.7.2-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.7.2) and aspectjrt-1.8.6.jar (org.aspectj:aspectjrt:1.8.6)
Duplicate class org.aspectj.runtime.reflect.SignatureImpl$CacheImpl found in modules LightCompressor-0.7.2-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.7.2) and aspectjrt-1.8.6.jar (org.aspectj:aspectjrt:1.8.6)
Duplicate class org.aspectj.runtime.reflect.SourceLocationImpl found in modules LightCompressor-0.7.2-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.7.2) and aspectjrt-1.8.6.jar (org.aspectj:aspectjrt:1.8.6)
Duplicate class org.aspectj.runtime.reflect.StringMaker found in modules LightCompressor-0.7.2-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.7.2) and aspectjrt-1.8.6.jar (org.aspectj:aspectjrt:1.8.6)
Duplicate class org.aspectj.runtime.reflect.UnlockSignatureImpl found in modules LightCompressor-0.7.2-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.7.2) and aspectjrt-1.8.6.jar (org.aspectj:aspectjrt:1.8.6)

Compressor: Error 0x80000000

For my a video, some days before I can compress successfully, but today when I tried to compress that video, it's failed with error code 0x80000000
Below is the log:

Error 0x80000000 2020-05-05 01:36:45.734 3249-3249/com.abc.test D/create_session_benefits_media_video: Compress starting... 2020-05-05 01:36:45.882 3249-3865/com.abc.test D/CCodec: allocate(c2.qti.avc.encoder) 2020-05-05 01:36:45.882 3249-3865/com.abc.test I/Codec2Client: Creating a Codec2 client to service "default" 2020-05-05 01:36:45.883 3249-3865/com.abc.test I/Codec2Client: Client to Codec2 service "default" created 2020-05-05 01:36:45.883 3249-3865/com.abc.test I/CCodec: setting up 'default' as default (vendor) store 2020-05-05 01:36:45.885 3249-3865/com.abc.test I/CCodec: Created component [c2.qti.avc.encoder] 2020-05-05 01:36:45.885 3249-3865/com.abc.test D/CCodecConfig: read media type: video/avc 2020-05-05 01:36:45.888 3249-3865/com.abc.test D/CCodecConfig: ignoring local param raw.color (0xc2001809) as it is already supported 2020-05-05 01:36:45.888 3249-3865/com.abc.test I/CCodecConfig: query failed after returning 20 values (BAD_INDEX) 2020-05-05 01:36:45.888 3249-3865/com.abc.test D/CCodecConfig: c2 config diff is Dict { c2::u32 algo.bitrate-mode.value = 3 c2::i32 algo.priority.value = -1 c2::u32 algo.quality.value = 50 c2::float algo.rate.value = 4.2039e-44 c2::u32 coded.bitrate.value = 20000000 c2::float coded.frame-rate.value = 30 c2::u32 coded.pl.level = 20480 c2::u32 coded.pl.profile = 20480 c2::u32 coded.vui.color.matrix = 0 c2::u32 coded.vui.color.primaries = 0 c2::u32 coded.vui.color.range = 0 c2::u32 coded.vui.color.transfer = 0 c2::i32 coding.gop.intra-period = 1 c2::u32 coding.request-sync-frame.value = 0 Buffer coding.temporal-layering = { 00000000: 10 00 00 00 07 20 01 52 01 00 00 00 00 00 00 00 ..... .R........ } c2::u32 default.color.matrix = 0 c2::u32 default.color.primaries = 0 c2::u32 default.color.range = 0 c2::u32 default.color.transfer = 0 c2::u32 input.delay.value = 8 string input.media-type.value = "video/raw" c2::u32 output.buffers.prepend-header.value = 2 c2::u32 output.delay.value = 8 string output.media-type.value = " 2020-05-05 01:36:45.889 3249-3865/com.abc.test W/ColorUtils: expected specified color aspects (0:0:0:0) 2020-05-05 01:36:45.892 3249-3865/com.abc.test D/CCodecConfig: no c2 equivalents for color-format 2020-05-05 01:36:45.892 3249-3865/com.abc.test D/CCodecConfig: no c2 equivalents for encoder 2020-05-05 01:36:45.892 3249-3865/com.abc.test D/CCodecConfig: c2 config diff is c2::u32 coded.bitrate.value = 2000000 c2::i32 coding.gop.intra-period = 450 c2::u32 raw.pixel-format.value = 34 c2::u32 raw.size.height = 1920 c2::u32 raw.size.width = 1080 2020-05-05 01:36:45.893 3249-3865/com.abc.test W/ColorUtils: expected specified color aspects (0:0:0:0) 2020-05-05 01:36:45.893 3249-3865/com.abc.test W/Codec2Client: query -- param skipped: index = 1107298332. 2020-05-05 01:36:45.893 3249-3865/com.abc.test W/Codec2Client: query -- param skipped: index = 3254781982. 2020-05-05 01:36:45.893 3249-3865/com.abc.test D/CCodec: setup formats input: AMessage(what = 0x00000000) = { Rect crop(0, 0, 1079, 1919) int32_t color-standard = 0 int32_t color-range = 0 int32_t color-transfer = 0 int32_t frame-rate = 30 int32_t height = 1920 int32_t i-frame-period = 450 string mime = "video/raw" int32_t prepend-sps-pps-to-idr-frames = 1 int32_t priority = 1 int32_t width = 1080 int32_t android._dataspace = 0 int32_t android._color-format = 2130708361 int32_t color-format = 2130708361 } and output: AMessage(what = 0x00000000) = { int32_t bitrate = 2000000 int32_t bitrate-mode = 1 Rect crop(0, 0, 1079, 1919) int32_t width = 1080 int32_t color-standard = 0 int32_t color-range = 0 int32_t color-transfer = 0 int32_t frame-rate = 30 int32_t height = 1920 int32_t i-frame-period = 450 int32_t level = 1 int32_t max-bitrate = 2000000 string mime = "video/avc" int32_t prepend-sps-pps-to-idr-frames = 1 int32_t priority = 1 int32_t profile = 1 } 2020-05-05 01:36:45.895 3249-3865/com.abc.test D/CCodec: input format changed to AMessage(what = 0x00000000) = { Rect crop(0, 0, 1079, 1919) int32_t color-standard = 1 int32_t color-range = 2 int32_t color-transfer = 3 int32_t frame-rate = 30 int32_t height = 1920 int32_t i-frame-period = 450 string mime = "video/raw" int32_t prepend-sps-pps-to-idr-frames = 1 int32_t priority = 1 int32_t width = 1080 int32_t android._dataspace = 260 int32_t android._color-format = 2130708361 int32_t color-format = 2130708361 } 2020-05-05 01:36:45.900 3249-3865/com.abc.test D/GraphicBufferSource: setting dataspace: 0x104, acquired=0 2020-05-05 01:36:45.900 3249-3865/com.abc.test D/CCodec: ISConfig timeOffset 0us (=> INVALID_OPERATION) timeLapse 0fps as 0fps (=> INVALID_OPERATION) start at 0us resume at -1us 2020-05-05 01:36:45.908 3249-3865/com.abc.test W/Codec2Client: query -- param skipped: index = 1342179345. 2020-05-05 01:36:45.908 3249-3865/com.abc.test W/Codec2Client: query -- param skipped: index = 2415921170. 2020-05-05 01:36:45.908 3249-3865/com.abc.test W/Codec2Client: query -- param skipped: index = 1610614798. 2020-05-05 01:36:45.908 3249-3865/com.abc.test D/CCodecBufferChannel: [c2.qti.avc.encoder#182] Query input allocators returned 0 params => BAD_INDEX (6) 2020-05-05 01:36:45.908 3249-3865/com.abc.test D/CCodecBufferChannel: [c2.qti.avc.encoder#182] Using basic input block pool with poolID 1 => got 1 - OK (0) 2020-05-05 01:36:45.908 3249-3865/com.abc.test D/CCodecBufferChannel: [c2.qti.avc.encoder#182] Query output allocators returned 0 params => BAD_INDEX (6) 2020-05-05 01:36:45.909 3249-3476/com.abc.test D/BufferPoolAccessor: bufferpool2 0x7bdd8c0620 : 0(0 size) total buffers - 0(0 size) used buffers - 42/59 (recycle/alloc) - 17/51 (fetch/transfer) 2020-05-05 01:36:45.910 3249-3476/com.abc.test D/BufferPoolAccessor: Destruction - bufferpool2 0x7bdd8c0620 cached: 0/0M, 0/0% in use; allocs: 59, 71% recycled; transfers: 51, 67% unfetced 2020-05-05 01:36:45.910 3249-3865/com.abc.test I/CCodecBufferChannel: [c2.qti.avc.encoder#182] Created output block pool with allocatorID 16 => poolID 342 - OK 2020-05-05 01:36:45.910 3249-3865/com.abc.test D/CCodecBufferChannel: [c2.qti.avc.encoder#182] Configured output block pool ids 342 => BAD_INDEX 2020-05-05 01:36:45.917 3249-3871/com.abc.test D/CCodec: allocate(c2.qti.avc.decoder) 2020-05-05 01:36:45.917 3249-3871/com.abc.test I/Codec2Client: Creating a Codec2 client to service "default" 2020-05-05 01:36:45.920 3249-3871/com.abc.test I/Codec2Client: Client to Codec2 service "default" created 2020-05-05 01:36:45.920 3249-3871/com.abc.test I/CCodec: setting up 'default' as default (vendor) store 2020-05-05 01:36:45.922 3249-3871/com.abc.test I/CCodec: Created component [c2.qti.avc.decoder] 2020-05-05 01:36:45.922 3249-3871/com.abc.test D/CCodecConfig: read media type: video/avc 2020-05-05 01:36:45.923 3249-3871/com.abc.test D/ReflectedParamUpdater: extent() != 1 for single value type: output.buffers.pool-ids.values 2020-05-05 01:36:45.925 3249-3871/com.abc.test D/CCodecConfig: ignoring local param raw.size (0xd2001800) as it is already supported 2020-05-05 01:36:45.925 3249-3871/com.abc.test D/CCodecConfig: ignoring local param raw.color (0xd2001809) as it is already supported 2020-05-05 01:36:45.925 3249-3871/com.abc.test D/CCodecConfig: ignoring local param raw.hdr-static-info (0xd200180a) as it is already supported 2020-05-05 01:36:45.926 3249-3871/com.abc.test I/CCodecConfig: query failed after returning 17 values (BAD_INDEX) 2020-05-05 01:36:45.926 3249-3871/com.abc.test D/CCodecConfig: c2 config diff is Dict { c2::i32 algo.priority.value = -1 c2::float algo.rate.value = 4.2039e-44 c2::u32 algo.secure-mode.value = 0 c2::float coded.frame-rate.value = 30 c2::u32 coded.pl.level = 20480 c2::u32 coded.pl.profile = 20480 c2::u32 coded.vui.color.matrix = 0 c2::u32 coded.vui.color.primaries = 0 c2::u32 coded.vui.color.range = 0 c2::u32 coded.vui.color.transfer = 0 c2::u32 default.color.matrix = 0 c2::u32 default.color.primaries = 3 c2::u32 default.color.range = 2 c2::u32 default.color.transfer = 0 c2::u32 input.buffers.max-size.value = 13271040 c2::u32 input.delay.value = 4 string input.media-type.value = "video/avc" c2::u32 output.delay.value = 18 string output.media-type.value = "video/raw" c2::u32 raw.color.matrix = 0 c2::u32 raw.color.primaries = 0 c2::u32 raw.color.range = 0 c2::u32 raw.color.transfer = 0 c2::float raw.hdr-static-info.mastering.blue.x = 1.4013e-45 c2::float raw.hdr-static-info.mastering.blue.y = 1.4013e-45 c2::float raw.hdr- 2020-05-05 01:36:45.926 3249-3871/com.abc.test W/ColorUtils: expected specified color aspects (0:0:0:0) 2020-05-05 01:36:45.929 3249-3870/com.abc.test D/SurfaceUtils: connecting to surface 0x7c38dd8010, reason connectToSurface 2020-05-05 01:36:45.929 3249-3870/com.abc.test I/MediaCodec: [c2.qti.avc.decoder] setting surface generation to 3326983 2020-05-05 01:36:45.929 3249-3870/com.abc.test D/SurfaceUtils: disconnecting from surface 0x7c38dd8010, reason connectToSurface(reconnect) 2020-05-05 01:36:45.929 3249-3870/com.abc.test D/SurfaceUtils: connecting to surface 0x7c38dd8010, reason connectToSurface(reconnect) 2020-05-05 01:36:45.929 3249-3871/com.abc.test D/CCodecConfig: no c2 equivalents for track-id 2020-05-05 01:36:45.929 3249-3871/com.abc.test D/CCodecConfig: no c2 equivalents for frame-count 2020-05-05 01:36:45.929 3249-3871/com.abc.test D/CCodecConfig: no c2 equivalents for language 2020-05-05 01:36:45.929 3249-3871/com.abc.test D/CCodecConfig: no c2 equivalents for color-standard 2020-05-05 01:36:45.929 3249-3871/com.abc.test D/CCodecConfig: no c2 equivalents for display-width 2020-05-05 01:36:45.929 3249-3871/com.abc.test D/CCodecConfig: no c2 equivalents for csd-1 2020-05-05 01:36:45.929 3249-3871/com.abc.test D/CCodecConfig: no c2 equivalents for durationUs 2020-05-05 01:36:45.929 3249-3871/com.abc.test D/CCodecConfig: no c2 equivalents for display-height 2020-05-05 01:36:45.929 3249-3871/com.abc.test D/CCodecConfig: no c2 equivalents for native-window 2020-05-05 01:36:45.930 3249-3871/com.abc.test D/CCodecConfig: c2 config diff is c2::float coded.frame-rate.value = 60 c2::u32 coded.pl.level = 20495 c2::u32 coded.pl.profile = 20484 c2::u32 default.color.matrix = 1 c2::u32 default.color.primaries = 1 c2::u32 default.color.transfer = 3 c2::u32 input.buffers.max-size.value = 6266880 c2::u32 raw.color.matrix = 1 c2::u32 raw.color.primaries = 1 c2::u32 raw.color.range = 2 c2::u32 raw.color.transfer = 3 c2::u32 raw.pixel-format.value = 34 c2::i32 raw.rotation.value = -90 c2::u32 raw.size.height = 2160 c2::u32 raw.size.width = 3840 2020-05-05 01:36:45.930 3249-3871/com.abc.test W/Codec2Client: query -- param skipped: index = 1107298332. 2020-05-05 01:36:45.930 3249-3871/com.abc.test D/CCodec: client requested max input size 637610, which is smaller than what component recommended (6266880); overriding with component recommendation. 2020-05-05 01:36:45.930 3249-3871/com.abc.test W/CCodec: This behavior is subject to change. It is recommended that app developers double check whether the requested max input size is in reasonable range. 2020-05-05 01:36:45.930 3249-3871/com.abc.test D/CCodec: setup formats input: AMessage(what = 0x00000000) = { int32_t feature-secure-playback = 0 int32_t frame-rate = 60 int32_t height = 2160 int32_t level = 32768 int32_t max-input-size = 6266880 string mime = "video/avc" int32_t priority = 1 int32_t profile = 8 int32_t width = 3840 Rect crop(0, 0, 3839, 2159) } and output: AMessage(what = 0x00000000) = { int32_t android._video-scaling = 1 Rect crop(0, 0, 3839, 2159) int32_t color-standard = 1 int32_t color-range = 2 int32_t color-transfer = 3 int32_t android._dataspace = 260 int32_t width = 3840 int32_t feature-secure-playback = 0 int32_t frame-rate = 60 int32_t height = 2160 int32_t max-height = 1080 int32_t max-width = 1920 string mime = "video/raw" int32_t priority = 1 int32_t rotation-degrees = 90 Buffer hdr-static-info = { 00000000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000010: 00 00 00 00 00 00 00 00 00 ......... } int32_t android._color-f 2020-05-05 01:36:45.944 3249-3871/com.abc.test W/Codec2Client: query -- param skipped: index = 1342179345. 2020-05-05 01:36:45.944 3249-3871/com.abc.test W/Codec2Client: query -- param skipped: index = 2415921170. 2020-05-05 01:36:45.944 3249-3871/com.abc.test W/Codec2Client: query -- param skipped: index = 1610614798. 2020-05-05 01:36:45.944 3249-3871/com.abc.test D/CCodecBufferChannel: [c2.qti.avc.decoder#174] Query input allocators returned 0 params => BAD_INDEX (6) 2020-05-05 01:36:45.945 3249-3871/com.abc.test D/CCodecBufferChannel: [c2.qti.avc.decoder#174] Created input block pool with allocatorID 16 => poolID 23 - OK (0) 2020-05-05 01:36:45.945 3249-3871/com.abc.test D/CCodecBufferChannel: [c2.qti.avc.decoder#174] Query output allocators returned 0 params => BAD_INDEX (6) 2020-05-05 01:36:45.945 3249-3871/com.abc.test D/CCodecBufferChannel: [c2.qti.avc.decoder#174] Query output surface allocator returned 0 params => BAD_INDEX (6) 2020-05-05 01:36:45.951 3249-3871/com.abc.test I/CCodecBufferChannel: [c2.qti.avc.decoder#174] Created output block pool with allocatorID 18 => poolID 343 - OK 2020-05-05 01:36:45.952 3249-3871/com.abc.test D/CCodecBufferChannel: [c2.qti.avc.decoder#174] Configured output block pool ids 343 => OK 2020-05-05 01:36:45.952 3249-3871/com.abc.test D/Codec2-block_helper: remote graphic buffer migration 0/0 2020-05-05 01:36:45.952 3249-3871/com.abc.test D/Codec2Client: generation remote change 3326983 2020-05-05 01:36:45.981 3249-3476/com.abc.test D/PipelineWatcher: onInputBufferReleased: frameIndex not found (8); ignored 2020-05-05 01:36:45.981 3249-3859/com.abc.test E/Compressor: Error 0x1 2020-05-05 01:36:45.984 3249-3870/com.abc.test E/MediaCodec: Codec reported err 0x80000000, actionCode 0, while in state 9 2020-05-05 01:36:45.984 3249-3870/com.abc.test D/SurfaceUtils: disconnecting from surface 0x7c38dd8010, reason disconnectFromSurface 2020-05-05 01:36:45.984 3249-3870/com.abc.test E/AMessage: trying to post a duplicate reply 2020-05-05 01:36:45.984 3249-3859/com.abc.test E/Compressor: Error 0x80000000 2020-05-05 01:36:45.984 3249-3249/com.abc.test D/create_session_benefits_media_video: Compress success 2020-05-05 01:36:45.993 3249-3249/com.abc.test D/create_session_benefits_media_video: newSizeInMB: 2.2888184E-5 2020-05-05 01:36:46.014 3249-3249/com.abc.test E/MediaMetadataRetrieverJNI: getEmbeddedPicture: Call to getEmbeddedPicture failed. 2020-05-05 01:36:46.563 3249-3265/com.abc.test W/System: A resource failed to call close. 2020-05-05 01:36:46.566 3249-3265/com.abc.test W/System: A resource failed to call close. 2020-05-05 01:36:46.575 3249-3265/com.abc.test W/System: A resource failed to call release. 2020-05-05 01:36:46.575 3249-3265/com.abc.test W/System: A resource failed to call release. 2020-05-05 01:36:46.587 3249-3476/com.abc.test E/BufferQueueProducer: [SurfaceTexture-1-3249-0] detachBuffer: BufferQueue has been abandoned

Does not work for 4K quality videos or return 0 byte video

This is the best video compression library I have found, but when I used it, I realized that it could not compress 4K quality videos and it went wrong. It works for some video and returned 0-byte video for some.

Many videos from the below website are not working.

https://www.pexels.com/video/5645774/

FYI: I tested on the demo APK you attached on Github.

Device: Google Pixel 4a OS 11, Samsung s10 OS 10 (NOT working on these devices) but the same video worked on Pixel2xl device.

inputFormat --> {has-sdtp=1, track-id=1, level=65536, mime=video/avc, frame-count=1021, profile=8, language=und, color-standard=1, display-width=2160, track-fourcc=828601953, csd-1=java.nio.HeapByteBuffer[pos=0 lim=9 cap=9], color-transfer=3, durationUs=40840000, display-height=4096, width=2160, color-range=2, max-input-size=6291456, frame-rate=25, height=4096, csd-0=java.nio.HeapByteBuffer[pos=0 lim=32 cap=32]}

Exception i get --> java.lang.NullPointerException on line number
Risky code
val decoderName = MediaCodecList(REGULAR_CODECS).findDecoderForFormat(inputFormat)
----> decoder = MediaCodec.createByCodecName(decoderName) <-------

because decoderName is null (MediaCodecList can not find decoder according inputformat) inpuformat string write above

How to cancel compression job correctly?

I have tried to implement as below by getting a Job when starting a video compression, but this does not work. The job cancelation is executed but its task still runs (I was checking log to know that via Log.d(TAG, "Compress process: " + v);
I think I need to get the correct scope of that compression coroutine so that I can cancel it.

// Compress
mCompressJob = VideoCompressor.INSTANCE.doVideoCompression(source.getPath(), mNewTempFileUpload.getPath(), new CompressionListener() {
@Override
public void onStart() {
	Log.d(TAG, "Compress starting...");
	mProgressDialog.show();
}

@Override
public void onSuccess() {
	Log.d(TAG, "Compress success");
	if (mProgressDialog != null) {
		mProgressDialog.dismiss();
	}
	checkUploadLimitSize(mNewTempFileUpload);
}

@Override
public void onFailure() {
	Log.d(TAG, "Compress fail");
	handleWhenCompressFail(false, source.getPath(), mNewTempFileUpload.getPath());
}

@Override
public void onProgress(float v) {
	Log.d(TAG, "Compress process: " + v);
	if (v > 0) {
		mProgressDialog.setProgress((int) v);
	}
}
});

// Cancel
if (mCompressJob != null && mCompressJob.isActive() && !mCompressJob.isCancelled()) {
	// cancel current running job
	CancellationException cancellationException = new CancellationException();
	cancellationException.printStackTrace();
	mCompressJob.cancel(cancellationException);
}

Video get Burst

Please can u share the method not decreasing resolution on ly bitrate according to video size

Does not work for 4K quality videos

This is the best video compression library I have found, but when I used it, I realized that it could not compress 4K quality videos and it went wrong.

Smart compression option

Hi, could you please add option to library to configure compression params. Now it's 30% of bitrate but it's not reliable. Maybe Telegram code is good ref how to do it right.

Can't work with Android Q

We can not get file path from Android Q, but this compressor work only if we pass source file path

The compression operation is very slow

I'm trying to compress 47 MB video but the compression is very slow

Xiaomi Redmi Note 8 with 6 GB of RAM

Video format = mp4
Video size = 47 MB
Video duration = 03:27
resolution = 480*480

Did I write wrong?
`

    txt_check.visibility = View.GONE
    lin_uploadProgress.visibility = View.VISIBLE


   VideoCompressor.start(path, desFile.path, object : CompressionListener {
            override fun onProgress(percent: Float) {


                val f_percent = percent.toInt()



                txtUploadedStatus.text = "Compressing ..."

                runOnUiThread {
                    txtUploadedPercent.text = "$f_percent%"
                    progress_upload.progress = f_percent

                }



            }


            override fun onStart() {}

            override fun onSuccess() {
                uploadVideo(caption,desFile)

            }

            override fun onFailure(failureMessage: String) {
                mlog("compress fail => $failureMessage")
                txtUploadedStatus.text = "failureMessage"
            }

            override fun onCancelled() {
                mlog("compress has been cancelled")
                // make UI changes, cleanup, etc
            }
        }, VideoQuality.MEDIUM, isMinBitRateEnabled = false, keepOriginalResolution = false
    )


}`

cannot access CoroutineScope

I am getting an error on importing this library

error: cannot access CoroutineScope
VideoCompressor.start(String.valueOf(contentURI), "//sdcard//Download//", new CompressionListener() {

the class file for kotlinx.coroutines.CoroutineScope not found

Need some help

Video is not showing

I have recorded a video of 10 secs and then I try to compress it. It is showing a black screen with audio only.

Licences

I wanted to ask a couple of questions before I try using your library.

  1. Does this use any FFMPEG (L)GPL licensed code or patented algorithms by MPEG LA?

  2. As this is licensed under apache 2.0 am I okay to use this in a commercial project?

Thanks a lot :)

Video shrink issue

For Video size which fall in below condition

width >= 960 || height >= 960 -> {
newWidth = MIN_HEIGHT
newHeight = MIN_WIDTH
}

video getting shrink after compress, i think their should be a small correction in this condition
newWidth = MIN_WIDTH
newHeight = MIN_HEIGHT

or like other
newWidth = width * 0.8
newHeight = height * 0.8

so please have a look for these type of videos, rest is working fine.
Thanks for your great work.

Exception The given long is not in the range of uint32

I tried running given demo code, got the exception below

java.lang.AssertionError: The given long is not in the range of uint32 (-3074)
at com.coremedia.iso.IsoTypeWriter.writeUInt32(IsoTypeWriter.java:28)
at com.coremedia.iso.boxes.TimeToSampleBox.getContent(TimeToSampleBox.java:75)
at com.googlecode.mp4parser.AbstractBox.getBox(AbstractBox.java:142)
at com.googlecode.mp4parser.BasicContainer.writeContainer(BasicContainer.java:216)
at com.googlecode.mp4parser.AbstractContainerBox.getBox(AbstractContainerBox.java:88)
at com.googlecode.mp4parser.BasicContainer.writeContainer(BasicContainer.java:216)
at com.googlecode.mp4parser.AbstractContainerBox.getBox(AbstractContainerBox.java:88)
at com.googlecode.mp4parser.BasicContainer.writeContainer(BasicContainer.java:216)
at com.googlecode.mp4parser.AbstractContainerBox.getBox(AbstractContainerBox.java:88)
at com.googlecode.mp4parser.BasicContainer.writeContainer(BasicContainer.java:216)
at com.googlecode.mp4parser.AbstractContainerBox.getBox(AbstractContainerBox.java:88)
at com.googlecode.mp4parser.BasicContainer.writeContainer(BasicContainer.java:216)
at com.googlecode.mp4parser.AbstractContainerBox.getBox(AbstractContainerBox.java:88)
at com.abedelazizshe.lightcompressorlibrary.MP4Builder.finishMovie(MP4Builder.java:151)
at com.abedelazizshe.lightcompressorlibrary.Compressor.compressVideo(Compressor.kt:415)
at com.abedelazizshe.lightcompressorlibrary.VideoCompressor$startCompression$2.invokeSuspend(VideoCompressor.kt:97)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)

Sound

the output video has no sound !

Always get java.lang.IllegalStateException: mediaMetadataRetriever.e…ETADATA_KEY_VIDEO_HEIGHT) must not be null

I use light compressor to compress video right after completing it's recording.

Before starting light compressor, I export the video with this code:

final ContentValues values = new ContentValues(5);
// The number 5 above, refer to these 5 lines
values.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");
values.put(MediaStore.Video.Media.DATA, filePath);
values.put(MediaStore.Video.Media.DURATION, videoDuration);
values.put(MediaStore.Video.Media.HEIGHT, videoHeight);
values.put(MediaStore.Video.Media.WIDTH, videoWidth);

Uri uri = context.getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
        values);
context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));

I have added MediaStore.Video.MEDIA.HEIGHT value, but why the exception state that it's null? Is it because the different value?

Instance nullpointer

VideoCompressor.**INSTANCE**.start(
					Source.getPath(),
					Destination.getPath(),

The instance propery always null.
How can i fix this?

Im using inside a service.

Thanks!

Not getting sound on compressed videos

Not getting sound on compression
Video Compression is very good and also compressed video quality is very nice but not getting sound on some video after compression .I have tried this on device with android 10
I think when i am recording video with camera and adding a sound (.AAC format) in it and then compressing it
its not getting any sound.

Java Version.

How can i put this lib in my project with java code?

Getting Error regarding permissions

I have provided 4 permission

uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE
uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE
uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION
uses-permission android:name="android.permission.CAMERA

and even given permission to my testing device.

D/path: /storage/emulated/0/download/Class 12 Maths - Continuity and Differentiation - Reuploaded (first video freezed on YouTube).mp4
W/System.err: java.io.FileNotFoundException: /storage/emulated/0/download/Class 12 Maths - Continuity and Differentiation - Reuploaded (first video freezed on YouTube).mp4: open failed: EACCES (Permission denied)
W/System.err: at libcore.io.IoBridge.open(IoBridge.java:496)
at java.io.FileInputStream.(FileInputStream.java:159)
at com.example.video_compressor.MainActivity.saveVideoToInternalStorage(MainActivity.java:175)
at com.example.video_compressor.MainActivity.onActivityResult(MainActivity.java:111)
at android.app.Activity.dispatchActivityResult(Activity.java:8249)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4931)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4979)
at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2044)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7562)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
W/System.err: at libcore.io.Linux.open(Native Method)
at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:252)
at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7461)
at libcore.io.IoBridge.open(IoBridge.java:482)
... 16 more
D/MediaPlayer: currentOpPackageName=com.example.video_compressor
I/System.out: Source path: content://com.miui.gallery.open/raw/%2Fstorage%2Femulated%2F0%2Fdownload%2FClass%2012%20Maths%20-%20Continuity%20and%20Differentiation%20-%20Reuploaded%20(first%20video%20freezed%20on%20YouTube).mp4 can be invalid! or you don't have READ_EXTERNAL_STORAGE permission
I/Toast: Show toast from OpPackageName:com.example.video_compressor, PackageName:com.example.video_compressor
D/MediaPlayerNative: getMetadata
V/MediaPlayer: resetDrmState: mDrmInfo=null mDrmProvisioningThread=null mPrepareDrmInProgress=false mActiveDrmScheme=false
cleanDrmObj: mDrmObj=null mDrmSessionId=null
V/MediaPlayer: resetDrmState: mDrmInfo=null mDrmProvisioningThread=null mPrepareDrmInProgress=false mActiveDrmScheme=false
cleanDrmObj: mDrmObj=null mDrmSessionId=null
W/System: A resource failed to call close.
W/System: A resource failed to call close.

readme doc error

the readme shows

VideoCompressor.doVideoCompression(

now is

VideoCompressor.start(

Compressing videos from whatsapp causes null height

when trying to compress video that was downloaded from whatsapp (which is already compressed), it causes following error :

java.lang.IllegalStateException: mediaMetadataRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT) must not be null
at com.abedelazizshe.lightcompressorlibrary.Compressor.compressVideo(Compressor.kt:41)
at com.abedelazizshe.lightcompressorlibrary.VideoCompressor$startCompression$2.invokeSuspend(VideoCompressor.kt:37)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)

Compress procession Time

First, very very thanks for this library share , very useful and good working.

by the way, some question in my Project

how can i more fast compress processing?

( Samsung galaxy S6 )
get video from Album OriginFile Size : 33823052 Byte
Compress with Quality.VERY_LOW
process time : 21sec
Result file Size close 1/10 byte (very good and i wanted size)

how can faster process time? just use better Phone?

========== example =============

afterFile = new File(this.getFilesDir(), "temp_"+originFile.getName());

VideoCompressor.start( originFile.getPath(), afterFile.getPath(),
new CompressionListener() {...}, VideoQuality.VERY_LOW );

how to resolve Execution failed for task ':app:checkDebugDuplicateClasses'

When I use the following two libraries simultaneously, I see an error in the build section

implementation 'com.github.AbedElazizShe:LightCompressor:0.5.0'‍
implementation 'com.github.AndroidDeveloperLB:VideoTrimmer:6'

But if I comment on any of these libraries, everything works fine How can I fix this problem?

`Execution failed for task ':app:checkDebugDuplicateClasses'.

1 exception was raised by workers:
java.lang.RuntimeException: Duplicate class com.coremedia.iso.AbstractBoxParser found in modulesLightCompressor-0.5.0-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.5.0) and isoparser-1.1.22.jar (com.googlecode.mp4parser:isoparser:1.1.22)
Duplicate class com.googlecode.mp4parser.authoring.tracks.SilenceTrackImpl found in modules LightCompressor-0.5.0-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.5.0) and isoparser-1.1.22.jar (com.googlecode.mp4parser:isoparser:1.1.22)

Duplicate class com.googlecode.mp4parser.authoring.tracks.TextTrackImpl$Line found in modules LightCompressor-0.5.0-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.5.0) and isoparser-1.1.22.jar (com.googlecode.mp4parser:isoparser:1.1.22)
Duplicate class com.googlecode.mp4parser.authoring.tracks.h265.H265TrackImpl found in modules LightCompressor-0.5.0-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.5.0) and isoparser-1.1.22.jar (com.googlecode.mp4parser:isoparser:1.1.22)
Duplicate class com.googlecode.mp4parser.authoring.tracks.h265.PicTiming found in modules LightCompressor-0.5.0-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.5.0) and isoparser-1.1.22.jar (com.googlecode.mp4parser:isoparser:1.1.22)
Duplicate class com.googlecode.mp4parser.authoring.tracks.h265.SEIMessage found in modules LightCompressor-0.5.0-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.5.0) and isoparser-1.1.22.jar (com.googlecode.mp4parser:isoparser:1.1.22)
Duplicate class com.googlecode.mp4parser.authoring.tracks.h265.SequenceParameterSetRbsp found in modules LightCompressor-0.5.0-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.5.0) and isoparser-1.1.22.jar (com.googlecode.mp4parser:isoparser:1.1.22)
Duplicate class com.googlecode.mp4parser.authoring.tracks.h265.VideoParameterSet found in modules LightCompressor-0.5.0-runtime.jar (com.github.AbedElazizShe:LightCompressor:0.5.0) and isoparser-1.1.22.jar (com.googlecode.mp4parser:isoparser:1.1.22)`

Green screen after compression

Huawei P9 compresses the video and sends it to iPhone 8. When it is played, it will be green. How can I solve this problem? Thank you

When try to compress video output as black screen with audio

i try this library , when i try to compress video that output will only black screen video. here is my code

                            selectedContentUri = contentURI
                            selectedVideoPath = getMediaPath(context!!, selectedContentUri)
                            videoUriList.add(contentURI)
                            type = "video"
                            val file = File(selectedVideoPath)

                            val downloadsPath =
                                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
                            val desFile = File(downloadsPath, "${System.currentTimeMillis()}_${file.name}")
                            if (desFile.exists()) {
                                desFile.delete()
                                try {
                                    desFile.createNewFile()
                                } catch (e: IOException) {
                                    e.printStackTrace()
                                }

                            }

                            VideoCompressor.start(
                                selectedVideoPath,
                                desFile.path,
                                object : CompressionListener {
                                    override fun onProgress(percent: Float) {
                                         progressDialog = ProgressDialog(context)
                                        progressDialog!!.setMessage("Please wait ${percent.toLong()}")
                                        progressDialog!!.show()

                                    }

                                    override fun onStart() {

                                    }

                                    override fun onSuccess() {

                                        Toast.makeText(context,"Sucess",Toast.LENGTH_SHORT).show()
                                        selectedVideoPath = desFile.path
                                        Log.e("SUCESSS","Sucess === "+selectedVideoPath)

                                    }

                                    override fun onFailure(failureMessage: String) {
                                        Toast.makeText(context,""+failureMessage,Toast.LENGTH_SHORT).show()
                                    }


                                    override fun onCancelled() {
                                       
                                    }
                                }, VideoQuality.MEDIUM, isMinBitRateEnabled = false, keepOriginalResolution = false)

Proguard rules

Video compression is working perfectly but I'm not able create release build because of proguard.
@AbedElazizShe Can you please provide proguard rules for the compressor.

Trim video

Hello, Good job with this library. Is it possible to trim a video while it is compressing? For example:

VideoCompressor.start("/stora...", "...dest/", new CompressionListener() {
....
}, VideoQuality.MEDIUM, true, false, 3, 15);//start = 3s, end = 15sec);

If this feature is not available can you point me in the right direction so I can add this feature myself?

Thanks!

E/Compressor: Attempt to invoke interface method 'java.lang.Object java.util.Map.get(java.lang.Object)' on a null object reference

VideoCompressor.start(volleyFileObject.getFile().getAbsolutePath(),volleyFileObjectCompress.getFilePath(), new CompressionListener() {
@OverRide
public void onStart() {
Log.d(TAG,"onStart compress:");
}

                @Override
                public void onSuccess() {
                    // On Compression success
                }

                @Override
                public void onFailure(String failureMessage) {
                    Log.d(TAG,"failur:"+failureMessage);
                    // On Failure
                }

                @Override
                public void onProgress(float v) {
                    Log.d(TAG,"onProgress compress:");
                }

                @Override
                public void onCancelled() {
                    Log.d(TAG,"onCancelled compress:");
                }
            }, VideoQuality.MEDIUM, false, false);


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

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2"

Audio Process Issue

In the Compressor processAudio function not working properly. Compressed video file not playing always I am facing audio renderer issue.

Video already compressed

I downloaded a video from WhatsApp/Instagram, the video is already compressed with very low resolution. If I compress it further and try to play it in macbook, it shows greenish kind of color in the video. Please introduce a feature in your library to check certain stats of a video, if they are low enough, it shouldn't compress the video further.
Thanks in advance.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.