From 3d948fa75007456e55636ae17208eeace9d219a9 Mon Sep 17 00:00:00 2001 From: Arman Ak Date: Sat, 14 Jan 2023 11:25:02 +0330 Subject: [PATCH] Add bitrate parameter to compressVideo - Add CustomQuality feature to quality parameter in compressVideo - Set frameRate for all qualities in compressVideo --- android/build.gradle | 2 +- .../video_compress/VideoCompressPlugin.kt | 163 +++++++++++++++++- lib/src/video_compress/video_compressor.dart | 16 +- lib/src/video_compress/video_quality.dart | 3 +- 4 files changed, 172 insertions(+), 12 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index ae95c4ff..ff99adf9 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -41,5 +41,5 @@ android { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - implementation 'com.otaliastudios:transcoder:0.9.1' + implementation 'com.otaliastudios:transcoder:0.10.4' } diff --git a/android/src/main/kotlin/com/example/video_compress/VideoCompressPlugin.kt b/android/src/main/kotlin/com/example/video_compress/VideoCompressPlugin.kt index 2861da1d..43498982 100644 --- a/android/src/main/kotlin/com/example/video_compress/VideoCompressPlugin.kt +++ b/android/src/main/kotlin/com/example/video_compress/VideoCompressPlugin.kt @@ -13,7 +13,9 @@ import com.otaliastudios.transcoder.strategy.RemoveTrackStrategy import com.otaliastudios.transcoder.strategy.TrackStrategy import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.plugin.common.BinaryMessenger -import com.otaliastudios.transcoder.internal.Logger +import com.otaliastudios.transcoder.internal.utils.Logger +import com.otaliastudios.transcoder.resize.AtMostResizer +import com.otaliastudios.transcoder.resize.ExactResizer import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel.MethodCallHandler @@ -83,6 +85,9 @@ class VideoCompressPlugin : MethodCallHandler, FlutterPlugin { val duration = call.argument("duration") val includeAudio = call.argument("includeAudio") ?: true val frameRate = if (call.argument("frameRate")==null) 30 else call.argument("frameRate") + val bitRate = call.argument("bitRate") + val outputWidth = call.argument("outputWidth") + val outputHeight = call.argument("outputHeight") val tempDir: String = context.getExternalFilesDir("video_compress")!!.absolutePath val out = SimpleDateFormat("yyyy-MM-dd hh-mm-ss").format(Date()) @@ -94,14 +99,59 @@ class VideoCompressPlugin : MethodCallHandler, FlutterPlugin { when (quality) { 0 -> { - videoTrackStrategy = DefaultVideoStrategy.atMost(720).build() + + assert(value = frameRate != null) + videoTrackStrategy = if (bitRate==null){ + DefaultVideoStrategy.Builder() + .keyFrameInterval(3f) + .frameRate(frameRate!!) // will be capped to the input frameRate + .addResizer(AtMostResizer(720)) + .build() + }else{ + DefaultVideoStrategy.Builder() + .keyFrameInterval(3f) + .bitRate(bitRate.toLong()) + .frameRate(frameRate!!) // will be capped to the input frameRate + .addResizer(AtMostResizer(720)) + .build() + } } 1 -> { - videoTrackStrategy = DefaultVideoStrategy.atMost(360).build() + + assert(value = frameRate != null) + videoTrackStrategy = if (bitRate==null){ + DefaultVideoStrategy.Builder() + .keyFrameInterval(3f) + .frameRate(frameRate!!) // will be capped to the input frameRate + .addResizer(AtMostResizer(360)) + .build() + }else{ + DefaultVideoStrategy.Builder() + .keyFrameInterval(3f) + .bitRate(bitRate.toLong()) + .frameRate(frameRate!!) // will be capped to the input frameRate + .addResizer(AtMostResizer(360)) + .build() + } } 2 -> { - videoTrackStrategy = DefaultVideoStrategy.atMost(640).build() + + assert(value = frameRate != null) + videoTrackStrategy = if (bitRate==null){ + DefaultVideoStrategy.Builder() + .keyFrameInterval(3f) + .frameRate(frameRate!!) // will be capped to the input frameRate + .addResizer(AtMostResizer(640)) + .build() + }else{ + DefaultVideoStrategy.Builder() + .keyFrameInterval(3f) + .bitRate(bitRate.toLong()) + .frameRate(frameRate!!) // will be capped to the input frameRate + .addResizer(AtMostResizer(640)) + .build() + } } 3 -> { @@ -113,17 +163,112 @@ class VideoCompressPlugin : MethodCallHandler, FlutterPlugin { .build() } 4 -> { - videoTrackStrategy = DefaultVideoStrategy.atMost(480, 640).build() + + assert(value = frameRate != null) + videoTrackStrategy = if (bitRate==null){ + DefaultVideoStrategy.Builder() + .keyFrameInterval(3f) + .frameRate(frameRate!!) // will be capped to the input frameRate + .addResizer(AtMostResizer(480,640)) + .build() + }else{ + DefaultVideoStrategy.Builder() + .keyFrameInterval(3f) + .bitRate(bitRate.toLong()) + .frameRate(frameRate!!) // will be capped to the input frameRate + .addResizer(AtMostResizer(480,640)) + .build() + } } 5 -> { - videoTrackStrategy = DefaultVideoStrategy.atMost(540, 960).build() + + assert(value = frameRate != null) + videoTrackStrategy = if (bitRate==null){ + DefaultVideoStrategy.Builder() + .keyFrameInterval(3f) + .frameRate(frameRate!!) // will be capped to the input frameRate + .addResizer(AtMostResizer(540,960)) + .build() + }else{ + DefaultVideoStrategy.Builder() + .keyFrameInterval(3f) + .bitRate(bitRate.toLong()) + .frameRate(frameRate!!) // will be capped to the input frameRate + .addResizer(AtMostResizer(540,960)) + .build() + } } 6 -> { - videoTrackStrategy = DefaultVideoStrategy.atMost(720, 1280).build() + + assert(value = frameRate != null) + videoTrackStrategy = if (bitRate==null){ + DefaultVideoStrategy.Builder() + .keyFrameInterval(3f) + .frameRate(frameRate!!) // will be capped to the input frameRate + .addResizer(AtMostResizer(720, 1280)) + .build() + }else{ + DefaultVideoStrategy.Builder() + .keyFrameInterval(3f) + .bitRate(bitRate.toLong()) + .frameRate(frameRate!!) // will be capped to the input frameRate + .addResizer(AtMostResizer(720,1280)) + .build() + } } 7 -> { - videoTrackStrategy = DefaultVideoStrategy.atMost(1080, 1920).build() - } + + assert(value = frameRate != null) + videoTrackStrategy = if (bitRate==null){ + DefaultVideoStrategy.Builder() + .keyFrameInterval(3f) + .frameRate(frameRate!!) // will be capped to the input frameRate + .addResizer(AtMostResizer(1080,1920)) + .build() + }else{ + DefaultVideoStrategy.Builder() + .keyFrameInterval(3f) + .bitRate(bitRate.toLong()) + .frameRate(frameRate!!) // will be capped to the input frameRate + .addResizer(AtMostResizer(1080,1920)) + .build() + } + } + 8 -> { + + assert(value = frameRate != null) + if(outputWidth != null && outputHeight != null) { + videoTrackStrategy = if (bitRate == null) { + DefaultVideoStrategy.Builder() + .keyFrameInterval(3f) + .frameRate(frameRate!!) // will be capped to the input frameRate + .addResizer(ExactResizer(outputWidth, outputHeight)) + .build() + } else { + DefaultVideoStrategy.Builder() + .keyFrameInterval(3f) + .bitRate(bitRate.toLong()) + .frameRate(frameRate!!) // will be capped to the input frameRate + .addResizer(ExactResizer(outputWidth, outputHeight)) + .build() + } + }else{ + videoTrackStrategy = if (bitRate==null){ + DefaultVideoStrategy.Builder() + .keyFrameInterval(3f) + .frameRate(frameRate!!) // will be capped to the input frameRate + .addResizer(AtMostResizer(720, 1280)) + .build() + }else{ + DefaultVideoStrategy.Builder() + .keyFrameInterval(3f) + .bitRate(bitRate.toLong()) + .frameRate(frameRate!!) // will be capped to the input frameRate + .addResizer(AtMostResizer(720,1280)) + .build() + } + } + } } audioTrackStrategy = if (includeAudio) { diff --git a/lib/src/video_compress/video_compressor.dart b/lib/src/video_compress/video_compressor.dart index 3b7b38e3..ab332b5f 100644 --- a/lib/src/video_compress/video_compressor.dart +++ b/lib/src/video_compress/video_compressor.dart @@ -109,8 +109,16 @@ extension Compress on IVideoCompress { /// compress video from [path] return [Future] /// /// you can choose its quality by [quality], + /// + /// Note : VideoQuality.CustomQuality is available only in Android platform. + /// /// determine whether to delete his source file by [deleteOrigin] - /// optional parameters [startTime] [duration] [includeAudio] [frameRate] + /// + /// optional parameters : [startTime] , [duration] , [includeAudio] , [frameRate] + /// + /// Android specific parameters : [bitRate] , [outputWidth] , [outputHeight] + /// + /// Note : if you don't choose VideoQuality.CustomQuality , [outputWidth] and [outputHeight] will be ignored. /// /// ## example /// ```dart @@ -128,6 +136,9 @@ extension Compress on IVideoCompress { int? duration, bool? includeAudio, int frameRate = 30, + int? bitRate, + int? outputWidth, + int? outputHeight }) async { if (isCompressing) { throw StateError('''VideoCompress Error: @@ -150,6 +161,9 @@ extension Compress on IVideoCompress { 'duration': duration, 'includeAudio': includeAudio, 'frameRate': frameRate, + 'bitRate': bitRate, + 'outputWidth': outputWidth, + 'outputHeight': outputHeight, }); // ignore: invalid_use_of_protected_member diff --git a/lib/src/video_compress/video_quality.dart b/lib/src/video_compress/video_quality.dart index c24b6058..de723a16 100644 --- a/lib/src/video_compress/video_quality.dart +++ b/lib/src/video_compress/video_quality.dart @@ -6,5 +6,6 @@ enum VideoQuality { Res640x480Quality, Res960x540Quality, Res1280x720Quality, - Res1920x1080Quality + Res1920x1080Quality, + CustomQuality }