react-native-compressor 1.8.1 → 1.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/android/build.gradle +5 -2
- package/android/src/main/java/com/reactnativecompressor/Audio/AudioCompressor.kt +2 -2
- package/android/src/main/java/com/reactnativecompressor/CompressorModule.kt +3 -3
- package/android/src/main/java/com/reactnativecompressor/Utils/Uploader.kt +11 -11
- package/android/src/main/java/com/reactnativecompressor/Utils/Utils.kt +42 -36
- package/android/src/main/java/com/reactnativecompressor/Utils/createVideoThumbnail.kt +1 -1
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/CompressionInterface.kt +73 -0
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/VideoCompressorClass.kt +148 -0
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/compressor/Compressor.kt +562 -0
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/utils/Atoms.kt +55 -0
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/utils/CompressorUtils.kt +196 -0
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/utils/NumbersUtils.kt +47 -0
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/utils/StreamableVideo.kt +209 -0
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/videoHelpers/InputSurface.kt +128 -0
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/videoHelpers/MP4Builder.kt +388 -0
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/videoHelpers/Mdat.kt +74 -0
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/videoHelpers/Mp4Movie.kt +54 -0
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/videoHelpers/OutputSurface.kt +102 -0
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/videoHelpers/Result.kt +9 -0
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/videoHelpers/Sample.kt +3 -0
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/videoHelpers/TextureRenderer.kt +214 -0
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/videoHelpers/Track.kt +286 -0
- package/lib/commonjs/utils/index.js +2 -2
- package/lib/commonjs/utils/index.js.map +1 -1
- package/lib/module/utils/index.js +2 -2
- package/lib/module/utils/index.js.map +1 -1
- package/lib/typescript/index.d.ts +13 -3
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/utils/index.d.ts +16 -3
- package/lib/typescript/utils/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/utils/index.tsx +22 -8
package/README.md
CHANGED
|
@@ -68,6 +68,7 @@ We should use **react-native-compressor** instead of **FFmpeg** because **react-
|
|
|
68
68
|
- [Audio](#audio)
|
|
69
69
|
- [Background Upload](#background-upload)
|
|
70
70
|
- [Download File](#download)
|
|
71
|
+
- [Create Video Thumbnail and Clear Cache](#create-video-thumbnail-and-clear-cache)
|
|
71
72
|
|
|
72
73
|
* [Other Utilities](#api)
|
|
73
74
|
- [Background Upload](#background-upload-1)
|
|
@@ -431,7 +432,7 @@ type FileSystemUploadOptions = (
|
|
|
431
432
|
|
|
432
433
|
- ##### download: ( fileUrl: string, downloadProgress?: (progress: number) => void, progressDivider?: number ) => Promise< string >
|
|
433
434
|
|
|
434
|
-
### Create Video Thumbnail and
|
|
435
|
+
### Create Video Thumbnail and Clear Cache
|
|
435
436
|
|
|
436
437
|
- #### createVideoThumbnail( fileUrl: string, options: {header:Object} ): Promise<{ path: string;size: number; mime: string; width: number; height: number; }>
|
|
437
438
|
|
package/android/build.gradle
CHANGED
|
@@ -110,9 +110,12 @@ dependencies {
|
|
|
110
110
|
//noinspection GradleDynamicVersion
|
|
111
111
|
implementation "com.facebook.react:react-native:+"
|
|
112
112
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
113
|
-
|
|
113
|
+
|
|
114
|
+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4"
|
|
115
|
+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
|
|
116
|
+
implementation "com.googlecode.mp4parser:isoparser:1.0.6"
|
|
117
|
+
|
|
114
118
|
implementation 'io.github.lizhangqu:coreprogress:1.0.2'
|
|
115
|
-
implementation 'com.github.numandev1:VideoCompressor:1a262bba37'
|
|
116
119
|
}
|
|
117
120
|
|
|
118
121
|
if (isNewArchitectureEnabled()) {
|
|
@@ -11,7 +11,7 @@ import android.media.MediaMuxer
|
|
|
11
11
|
import android.os.Build
|
|
12
12
|
import android.util.Log
|
|
13
13
|
import androidx.annotation.RequiresApi
|
|
14
|
-
import
|
|
14
|
+
import com.reactnativecompressor.Video.VideoCompressor.video.OutputSurface
|
|
15
15
|
import java.io.File
|
|
16
16
|
import java.io.IOException
|
|
17
17
|
import java.nio.ByteBuffer
|
|
@@ -24,7 +24,7 @@ class AudioCompressor {
|
|
|
24
24
|
private var mEncoder: MediaCodec? = null
|
|
25
25
|
private var mDecoder: MediaCodec? = null
|
|
26
26
|
private var mTrackIndex = 0
|
|
27
|
-
private var mInputSurface:
|
|
27
|
+
private var mInputSurface: OutputSurface? = null
|
|
28
28
|
|
|
29
29
|
// bit rate, in bits per second
|
|
30
30
|
private var mBitRate = -1
|
|
@@ -8,7 +8,7 @@ import com.facebook.react.bridge.ReactMethod
|
|
|
8
8
|
import com.facebook.react.bridge.ReadableMap
|
|
9
9
|
import com.reactnativecompressor.Audio.AudioMain
|
|
10
10
|
import com.reactnativecompressor.Image.ImageMain
|
|
11
|
-
import com.reactnativecompressor.Utils.
|
|
11
|
+
import com.reactnativecompressor.Utils.CreateVideoThumbnailClass
|
|
12
12
|
import com.reactnativecompressor.Utils.Downloader
|
|
13
13
|
import com.reactnativecompressor.Utils.EventEmitterHandler
|
|
14
14
|
import com.reactnativecompressor.Utils.Uploader
|
|
@@ -21,7 +21,7 @@ class CompressorModule(private val reactContext: ReactApplicationContext) : Comp
|
|
|
21
21
|
private val imageMain: ImageMain = ImageMain(reactContext)
|
|
22
22
|
private val videoMain: VideoMain = VideoMain(reactContext)
|
|
23
23
|
private val audioMain: AudioMain = AudioMain(reactContext)
|
|
24
|
-
private val videoThumbnail:
|
|
24
|
+
private val videoThumbnail: CreateVideoThumbnailClass = CreateVideoThumbnailClass(reactContext)
|
|
25
25
|
|
|
26
26
|
override fun initialize() {
|
|
27
27
|
super.initialize()
|
|
@@ -156,7 +156,7 @@ class CompressorModule(private val reactContext: ReactApplicationContext) : Comp
|
|
|
156
156
|
|
|
157
157
|
@ReactMethod
|
|
158
158
|
override fun clearCache(cacheDir:String?, promise:Promise) {
|
|
159
|
-
|
|
159
|
+
CreateVideoThumbnailClass.clearCache(cacheDir, promise, reactContext)
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
@ReactMethod
|
|
@@ -32,17 +32,17 @@ object Uploader {
|
|
|
32
32
|
if (url != null) {
|
|
33
33
|
builder.url(url)
|
|
34
34
|
}
|
|
35
|
-
val headerIterator = options
|
|
36
|
-
while (headerIterator
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
35
|
+
val headerIterator = options?.headers?.keySetIterator()
|
|
36
|
+
while (headerIterator?.hasNextKey() == true) {
|
|
37
|
+
val key = headerIterator.nextKey()
|
|
38
|
+
val value = options.headers?.getString(key)
|
|
39
|
+
Log.d(TAG, "$key value: $value")
|
|
40
|
+
builder.addHeader(key, value.toString())
|
|
41
|
+
if (key.lowercase(Locale.getDefault()) == "content-type:") {
|
|
42
|
+
contentType = value
|
|
43
|
+
}
|
|
44
44
|
}
|
|
45
|
-
val mediaType: MediaType = contentType?.toMediaTypeOrNull()
|
|
45
|
+
val mediaType: MediaType? = contentType?.toMediaTypeOrNull();
|
|
46
46
|
val body = RequestBody.create(mediaType, uploadableFile)
|
|
47
47
|
val requestBody = ProgressHelper.withProgress(body, object : ProgressUIListener() {
|
|
48
48
|
//if you don't need this method, don't override this methd. It isn't an abstract method, just an empty method.
|
|
@@ -52,7 +52,7 @@ object Uploader {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
override fun onUIProgressChanged(numBytes: Long, totalBytes: Long, percent: Float, speed: Float) {
|
|
55
|
-
EventEmitterHandler.sendUploadProgressEvent(numBytes,totalBytes,options
|
|
55
|
+
EventEmitterHandler.sendUploadProgressEvent(numBytes,totalBytes,options?.uuid)
|
|
56
56
|
Log.d(TAG, "=============start===============")
|
|
57
57
|
Log.d(TAG, "numBytes:$numBytes")
|
|
58
58
|
Log.d(TAG, "totalBytes:$totalBytes")
|
|
@@ -7,8 +7,8 @@ import android.provider.OpenableColumns
|
|
|
7
7
|
import android.util.Log
|
|
8
8
|
import com.facebook.react.bridge.Promise
|
|
9
9
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
10
|
-
import
|
|
11
|
-
import
|
|
10
|
+
import com.reactnativecompressor.Video.VideoCompressor.CompressionListener
|
|
11
|
+
import com.reactnativecompressor.Video.VideoCompressor.VideoCompressorClass
|
|
12
12
|
import java.io.FileNotFoundException
|
|
13
13
|
import java.io.IOException
|
|
14
14
|
import java.net.HttpURLConnection
|
|
@@ -17,7 +17,7 @@ import java.util.UUID
|
|
|
17
17
|
|
|
18
18
|
object Utils {
|
|
19
19
|
private const val TAG = "react-native-compessor"
|
|
20
|
-
var compressorExports: MutableMap<String,
|
|
20
|
+
var compressorExports: MutableMap<String, VideoCompressorClass?> = HashMap()
|
|
21
21
|
@JvmStatic
|
|
22
22
|
fun generateCacheFilePath(extension: String, reactContext: ReactApplicationContext): String {
|
|
23
23
|
val outputDir = reactContext.cacheDir
|
|
@@ -26,48 +26,54 @@ object Utils {
|
|
|
26
26
|
|
|
27
27
|
@JvmStatic
|
|
28
28
|
fun compressVideo(srcPath: String, destinationPath: String, resultWidth: Int, resultHeight: Int, videoBitRate: Float, uuid: String,progressDivider:Int, promise: Promise, reactContext: ReactApplicationContext) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
val currentVideoCompression = intArrayOf(0)
|
|
30
|
+
val videoCompressorClass: VideoCompressorClass? = VideoCompressorClass(reactContext);
|
|
31
|
+
compressorExports[uuid] = videoCompressorClass
|
|
32
|
+
videoCompressorClass?.start(srcPath, destinationPath, resultWidth, resultHeight, videoBitRate.toInt(),
|
|
33
|
+
listener = object : CompressionListener {
|
|
34
|
+
override fun onProgress(index: Int, percent: Float) {
|
|
35
|
+
if (percent <= 100)
|
|
36
|
+
{
|
|
37
|
+
val roundProgress = Math.round(percent)
|
|
38
|
+
if (progressDivider==0||(roundProgress % progressDivider == 0 && roundProgress > currentVideoCompression[0])) {
|
|
39
|
+
EventEmitterHandler.emitVideoCompressProgress((percent / 100).toDouble(),uuid)
|
|
40
|
+
currentVideoCompression[0] = roundProgress
|
|
34
41
|
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
35
44
|
|
|
36
|
-
|
|
37
|
-
val fileUrl = "file://$destinationPath"
|
|
38
|
-
//convert finish,result(true is success,false is fail)
|
|
39
|
-
promise.resolve(fileUrl)
|
|
40
|
-
MediaCache.removeCompletedImagePath(fileUrl)
|
|
41
|
-
}
|
|
45
|
+
override fun onStart(index: Int) {
|
|
42
46
|
|
|
43
|
-
|
|
44
|
-
if (errorMessage == "class java.lang.AssertionError") {
|
|
45
|
-
promise.resolve("file://$srcPath")
|
|
46
|
-
} else {
|
|
47
|
-
promise.reject("Compression has canncelled")
|
|
48
|
-
}
|
|
49
|
-
}
|
|
47
|
+
}
|
|
50
48
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
49
|
+
override fun onSuccess(index: Int, size: Long, path: String?) {
|
|
50
|
+
val fileUrl = "file://$destinationPath"
|
|
51
|
+
//convert finish,result(true is success,false is fail)
|
|
52
|
+
promise.resolve(fileUrl)
|
|
53
|
+
MediaCache.removeCompletedImagePath(fileUrl)
|
|
54
|
+
currentVideoCompression[0] = 0
|
|
55
|
+
compressorExports[uuid]=null
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
override fun onFailure(index: Int, failureMessage: String) {
|
|
59
|
+
Log.wtf("failureMessage", failureMessage)
|
|
60
|
+
currentVideoCompression[0] = 0
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
override fun onCancelled(index: Int) {
|
|
64
|
+
Log.wtf("TAG", "compression has been cancelled")
|
|
65
|
+
// make UI changes, cleanup, etc
|
|
66
|
+
currentVideoCompression[0] = 0
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
)
|
|
65
70
|
}
|
|
66
71
|
|
|
67
72
|
fun cancelCompressionHelper(uuid: String) {
|
|
68
73
|
try {
|
|
69
74
|
val export = compressorExports[uuid]
|
|
70
|
-
export
|
|
75
|
+
export?.cancel()
|
|
76
|
+
compressorExports[uuid]=null
|
|
71
77
|
} catch (ex: Exception) {
|
|
72
78
|
}
|
|
73
79
|
}
|
|
@@ -26,7 +26,7 @@ import java.net.URLDecoder
|
|
|
26
26
|
import java.util.UUID
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
class
|
|
29
|
+
class CreateVideoThumbnailClass(private val reactContext: ReactApplicationContext) {
|
|
30
30
|
@ReactMethod
|
|
31
31
|
fun create(fileUrl:String,options: ReadableMap, promise: Promise) {
|
|
32
32
|
ProcessDataTask(reactContext,fileUrl, promise, options).execute()
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
package com.reactnativecompressor.Video.VideoCompressor
|
|
2
|
+
|
|
3
|
+
import androidx.annotation.MainThread
|
|
4
|
+
import androidx.annotation.WorkerThread
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Interface for listening to video compression events.
|
|
8
|
+
*/
|
|
9
|
+
interface CompressionListener {
|
|
10
|
+
/**
|
|
11
|
+
* Called when video compression starts.
|
|
12
|
+
*
|
|
13
|
+
* @param index The index of the video being compressed.
|
|
14
|
+
*/
|
|
15
|
+
@MainThread
|
|
16
|
+
fun onStart(index: Int)
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Called when video compression succeeds.
|
|
20
|
+
*
|
|
21
|
+
* @param index The index of the video that was compressed.
|
|
22
|
+
* @param size The size of the compressed video.
|
|
23
|
+
* @param path The path to the compressed video file (nullable).
|
|
24
|
+
*/
|
|
25
|
+
@MainThread
|
|
26
|
+
fun onSuccess(index: Int, size: Long, path: String?)
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Called when video compression fails.
|
|
30
|
+
*
|
|
31
|
+
* @param index The index of the video that failed to compress.
|
|
32
|
+
* @param failureMessage A message describing the reason for the failure.
|
|
33
|
+
*/
|
|
34
|
+
@MainThread
|
|
35
|
+
fun onFailure(index: Int, failureMessage: String)
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Called to report the progress of video compression.
|
|
39
|
+
*
|
|
40
|
+
* @param index The index of the video being compressed.
|
|
41
|
+
* @param percent The progress percentage (0.0 to 100.0).
|
|
42
|
+
*/
|
|
43
|
+
@WorkerThread
|
|
44
|
+
fun onProgress(index: Int, percent: Float)
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Called when video compression is canceled.
|
|
48
|
+
*
|
|
49
|
+
* @param index The index of the video that was canceled.
|
|
50
|
+
*/
|
|
51
|
+
@WorkerThread
|
|
52
|
+
fun onCancelled(index: Int)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Interface for tracking the progress of video compression.
|
|
57
|
+
*/
|
|
58
|
+
interface CompressionProgressListener {
|
|
59
|
+
/**
|
|
60
|
+
* Called when the progress of video compression changes.
|
|
61
|
+
*
|
|
62
|
+
* @param index The index of the video being compressed.
|
|
63
|
+
* @param percent The current progress percentage (0.0 to 100.0).
|
|
64
|
+
*/
|
|
65
|
+
fun onProgressChanged(index: Int, percent: Float)
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Called when the compression progress is canceled.
|
|
69
|
+
*
|
|
70
|
+
* @param index The index of the video compression that was canceled.
|
|
71
|
+
*/
|
|
72
|
+
fun onProgressCancelled(index: Int)
|
|
73
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
package com.reactnativecompressor.Video.VideoCompressor
|
|
2
|
+
|
|
3
|
+
import android.database.Cursor
|
|
4
|
+
import android.net.Uri
|
|
5
|
+
import android.provider.MediaStore
|
|
6
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
7
|
+
import com.reactnativecompressor.Video.VideoCompressor.compressor.Compressor.compressVideo
|
|
8
|
+
import com.reactnativecompressor.Video.VideoCompressor.compressor.Compressor.isRunning
|
|
9
|
+
import com.reactnativecompressor.Video.VideoCompressor.video.Result
|
|
10
|
+
import kotlinx.coroutines.CoroutineScope
|
|
11
|
+
import kotlinx.coroutines.Dispatchers
|
|
12
|
+
import kotlinx.coroutines.Job
|
|
13
|
+
import kotlinx.coroutines.launch
|
|
14
|
+
import kotlinx.coroutines.withContext
|
|
15
|
+
import java.io.File
|
|
16
|
+
|
|
17
|
+
class VideoCompressorClass(private val context: ReactApplicationContext) {
|
|
18
|
+
private var job: Job? = null
|
|
19
|
+
|
|
20
|
+
@JvmOverloads
|
|
21
|
+
fun start(
|
|
22
|
+
srcPath: String,
|
|
23
|
+
destPath: String,
|
|
24
|
+
outputWidth: Int,
|
|
25
|
+
outputHeight: Int,
|
|
26
|
+
bitrate: Int,
|
|
27
|
+
listener: CompressionListener,
|
|
28
|
+
) {
|
|
29
|
+
val uris = mutableListOf<Uri>()
|
|
30
|
+
val uri = Uri.parse(srcPath)
|
|
31
|
+
uris.add(uri)
|
|
32
|
+
val isStreamable: Boolean = false
|
|
33
|
+
doVideoCompression(
|
|
34
|
+
uris,
|
|
35
|
+
isStreamable,
|
|
36
|
+
outputWidth,
|
|
37
|
+
outputHeight,
|
|
38
|
+
bitrate,
|
|
39
|
+
listener,
|
|
40
|
+
destPath
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
fun cancel() {
|
|
45
|
+
job?.cancel()
|
|
46
|
+
isRunning = false
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private fun doVideoCompression(
|
|
50
|
+
uris: List<Uri>,
|
|
51
|
+
isStreamable: Boolean,
|
|
52
|
+
outputWidth: Int,
|
|
53
|
+
outputHeight: Int,
|
|
54
|
+
bitrate: Int,
|
|
55
|
+
listener: CompressionListener,
|
|
56
|
+
destPath: String
|
|
57
|
+
) {
|
|
58
|
+
var streamableFile: File? = null
|
|
59
|
+
for (i in uris.indices) {
|
|
60
|
+
job = CoroutineScope(Dispatchers.Main).launch {
|
|
61
|
+
val desFile = File(destPath)
|
|
62
|
+
|
|
63
|
+
if (isStreamable)
|
|
64
|
+
streamableFile = File(destPath)
|
|
65
|
+
|
|
66
|
+
desFile?.let {
|
|
67
|
+
isRunning = true
|
|
68
|
+
listener.onStart(i)
|
|
69
|
+
val result = startCompression(
|
|
70
|
+
i,
|
|
71
|
+
uris[i],
|
|
72
|
+
desFile.path,
|
|
73
|
+
streamableFile?.path,
|
|
74
|
+
outputWidth,
|
|
75
|
+
outputHeight,
|
|
76
|
+
bitrate,
|
|
77
|
+
listener,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
// Runs in Main(UI) Thread
|
|
81
|
+
if (result.success) {
|
|
82
|
+
listener.onSuccess(i, result.size, result.path)
|
|
83
|
+
} else {
|
|
84
|
+
listener.onFailure(i, result.failureMessage ?: "An error has occurred!")
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private suspend fun startCompression(
|
|
92
|
+
index: Int,
|
|
93
|
+
srcUri: Uri,
|
|
94
|
+
destPath: String,
|
|
95
|
+
streamableFile: String? = null,
|
|
96
|
+
outputWidth: Int,
|
|
97
|
+
outputHeight: Int,
|
|
98
|
+
bitrate: Int,
|
|
99
|
+
listener: CompressionListener,
|
|
100
|
+
): Result = withContext(Dispatchers.Default) {
|
|
101
|
+
return@withContext compressVideo(
|
|
102
|
+
index,
|
|
103
|
+
context,
|
|
104
|
+
srcUri,
|
|
105
|
+
destPath,
|
|
106
|
+
streamableFile,
|
|
107
|
+
outputWidth,
|
|
108
|
+
outputHeight,
|
|
109
|
+
bitrate,
|
|
110
|
+
object : CompressionProgressListener {
|
|
111
|
+
override fun onProgressChanged(index: Int, percent: Float) {
|
|
112
|
+
listener.onProgress(index, percent)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
override fun onProgressCancelled(index: Int) {
|
|
116
|
+
listener.onCancelled(index)
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
private fun getMediaPath(uri: Uri): String {
|
|
123
|
+
val scheme = uri.scheme
|
|
124
|
+
if (scheme == null || scheme == "file") {
|
|
125
|
+
// The URI is a file URI, so use the path directly.
|
|
126
|
+
return uri.path ?: ""
|
|
127
|
+
} else {
|
|
128
|
+
// The URI is not a file URI, so try to copy the content to a file.
|
|
129
|
+
val resolver = context.contentResolver
|
|
130
|
+
val projection = arrayOf(MediaStore.Video.Media.DATA)
|
|
131
|
+
var cursor: Cursor? = null
|
|
132
|
+
try {
|
|
133
|
+
cursor = resolver.query(uri, projection, null, null, null)
|
|
134
|
+
if (cursor != null && cursor.moveToFirst()) {
|
|
135
|
+
val columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA)
|
|
136
|
+
return cursor.getString(columnIndex)
|
|
137
|
+
}
|
|
138
|
+
} catch (e: Exception) {
|
|
139
|
+
// Handle the exception as needed.
|
|
140
|
+
} finally {
|
|
141
|
+
cursor?.close()
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// If all else fails, return an empty string or handle the error accordingly.
|
|
146
|
+
return ""
|
|
147
|
+
}
|
|
148
|
+
}
|