react-native-compressor 1.7.1 → 1.8.0
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 +40 -15
- package/android/build.gradle +8 -0
- package/android/src/main/java/com/reactnativecompressor/Audio/AudioCompressor.kt +527 -0
- package/android/src/main/java/com/reactnativecompressor/Audio/AudioMain.kt +31 -0
- package/android/src/main/java/com/reactnativecompressor/CompressorModule.kt +157 -0
- package/android/src/main/java/com/reactnativecompressor/CompressorPackage.kt +34 -0
- package/android/src/main/java/com/reactnativecompressor/Image/ImageCompressor.kt +199 -0
- package/android/src/main/java/com/reactnativecompressor/Image/ImageCompressorOptions.kt +57 -0
- package/android/src/main/java/com/reactnativecompressor/Image/ImageMain.kt +31 -0
- package/android/src/main/java/com/reactnativecompressor/Image/ImageSize.kt +3 -0
- package/android/src/main/java/com/reactnativecompressor/Utils/Downloader.kt +119 -0
- package/android/src/main/java/com/reactnativecompressor/Utils/EventEmitterHandler.kt +66 -0
- package/android/src/main/java/com/reactnativecompressor/Utils/MediaCache.kt +61 -0
- package/android/src/main/java/com/reactnativecompressor/Utils/RealPathUtil.kt +177 -0
- package/android/src/main/java/com/reactnativecompressor/Utils/Uploader.kt +117 -0
- package/android/src/main/java/com/reactnativecompressor/Utils/Utils.kt +162 -0
- package/android/src/main/java/com/reactnativecompressor/Video/AutoVideoCompression.kt +63 -0
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressorHelper.kt +125 -0
- package/android/src/main/java/com/reactnativecompressor/Video/VideoMain.kt +86 -0
- package/android/src/newarch/CompressorSpec.kt +5 -0
- package/android/src/oldarch/CompressorSpec.kt +32 -0
- package/ios/Audio/AudioMain.swift +115 -0
- package/ios/Compressor-Bridging-Header.h +1 -2
- package/ios/Compressor.h +0 -8
- package/ios/Compressor.mm +28 -389
- package/ios/CompressorManager.swift +96 -0
- package/ios/Image/ImageCompressor.swift +354 -0
- package/ios/Image/ImageCompressorOptions.swift +93 -0
- package/ios/Image/ImageMain.swift +27 -0
- package/ios/Utils/Downloader.swift +157 -0
- package/ios/Utils/EventEmitterHandler.swift +54 -0
- package/ios/Utils/MediaCache.swift +48 -0
- package/ios/Utils/Uploader.swift +99 -0
- package/ios/Utils/Utils.swift +110 -0
- package/ios/Video/{VideoCompressor.swift → VideoMain.swift} +168 -147
- package/lib/commonjs/Image/index.js +1 -1
- package/lib/commonjs/Image/index.js.map +1 -1
- package/lib/commonjs/Main.js +1 -8
- package/lib/commonjs/Main.js.map +1 -1
- package/lib/commonjs/Spec/NativeCompressor.js.map +1 -1
- package/lib/commonjs/Video/index.js +4 -33
- package/lib/commonjs/Video/index.js.map +1 -1
- package/lib/commonjs/expo-plugin/compressor.js.map +1 -1
- package/lib/commonjs/index.js +11 -6
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/utils/Downloader.js +38 -0
- package/lib/commonjs/utils/Downloader.js.map +1 -0
- package/lib/commonjs/utils/Uploader.js +40 -0
- package/lib/commonjs/utils/Uploader.js.map +1 -0
- package/lib/commonjs/utils/index.js +35 -0
- package/lib/commonjs/utils/index.js.map +1 -1
- package/lib/module/Image/index.js +1 -1
- package/lib/module/Image/index.js.map +1 -1
- package/lib/module/Main.js +1 -7
- package/lib/module/Main.js.map +1 -1
- package/lib/module/Spec/NativeCompressor.js.map +1 -1
- package/lib/module/Video/index.js +5 -33
- package/lib/module/Video/index.js.map +1 -1
- package/lib/module/expo-plugin/compressor.js.map +1 -1
- package/lib/module/index.js +6 -6
- package/lib/module/index.js.map +1 -1
- package/lib/module/utils/Downloader.js +31 -0
- package/lib/module/utils/Downloader.js.map +1 -0
- package/lib/module/utils/Uploader.js +33 -0
- package/lib/module/utils/Uploader.js.map +1 -0
- package/lib/module/utils/index.js +2 -0
- package/lib/module/utils/index.js.map +1 -1
- package/lib/typescript/Image/index.d.ts +4 -0
- package/lib/typescript/Image/index.d.ts.map +1 -1
- package/lib/typescript/Main.d.ts +1 -2
- package/lib/typescript/Main.d.ts.map +1 -1
- package/lib/typescript/Spec/NativeCompressor.d.ts +8 -2
- package/lib/typescript/Spec/NativeCompressor.d.ts.map +1 -1
- package/lib/typescript/Video/index.d.ts +4 -28
- package/lib/typescript/Video/index.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +5 -4
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/utils/Downloader.d.ts +2 -0
- package/lib/typescript/utils/Downloader.d.ts.map +1 -0
- package/lib/typescript/utils/Uploader.d.ts +28 -0
- package/lib/typescript/utils/Uploader.d.ts.map +1 -0
- package/lib/typescript/utils/index.d.ts +2 -1
- package/lib/typescript/utils/index.d.ts.map +1 -1
- package/package.json +6 -4
- package/src/Image/index.tsx +5 -1
- package/src/Main.tsx +1 -15
- package/src/Spec/NativeCompressor.ts +14 -2
- package/src/Video/index.tsx +11 -84
- package/src/expo-plugin/compressor.ts +1 -1
- package/src/index.tsx +6 -3
- package/src/utils/Downloader.tsx +38 -0
- package/src/utils/Uploader.tsx +78 -0
- package/src/utils/index.tsx +2 -0
- package/android/src/main/java/com/reactnativecompressor/Audio/AudioCompressor.java +0 -605
- package/android/src/main/java/com/reactnativecompressor/CompressorModule.java +0 -220
- package/android/src/main/java/com/reactnativecompressor/CompressorPackage.java +0 -58
- package/android/src/main/java/com/reactnativecompressor/Image/ImageCompressor.java +0 -257
- package/android/src/main/java/com/reactnativecompressor/Image/utils/ImageCompressorOptions.java +0 -69
- package/android/src/main/java/com/reactnativecompressor/Image/utils/ImageSize.java +0 -13
- package/android/src/main/java/com/reactnativecompressor/Utils/FileUplaoder/FileUploadHelper.java +0 -39
- package/android/src/main/java/com/reactnativecompressor/Utils/FileUplaoder/FileUploader.java +0 -129
- package/android/src/main/java/com/reactnativecompressor/Utils/MediaCache.java +0 -65
- package/android/src/main/java/com/reactnativecompressor/Utils/RealPathUtil.java +0 -210
- package/android/src/main/java/com/reactnativecompressor/Utils/Utils.java +0 -272
- package/android/src/main/java/com/reactnativecompressor/Video/AutoVideoCompression/AutoVideoCompression.java +0 -87
- package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressorHelper.java +0 -182
- package/android/src/main/java/com/reactnativecompressor/Video/VideoModule.java +0 -112
- package/android/src/newarch/CompressorSpec.java +0 -9
- package/android/src/newarch/VideoCompressorSpec.java +0 -9
- package/android/src/oldarch/CompressorSpec.java +0 -34
- package/android/src/oldarch/VideoCompressorSpec.java +0 -26
- package/ios/Image/ImageCompressor.h +0 -22
- package/ios/Image/ImageCompressor.m +0 -540
- package/ios/Image/ImageCompressorOptions.h +0 -28
- package/ios/Image/ImageCompressorOptions.m +0 -97
- package/ios/Utils/Downloader.h +0 -16
- package/ios/Utils/Downloader.m +0 -150
- package/ios/Utils/MediaCache.h +0 -11
- package/ios/Utils/MediaCache.m +0 -51
- package/ios/Video/VideoCompressor.h +0 -5
- package/ios/Video/VideoCompressor.m +0 -1
- package/lib/commonjs/Spec/NativeVideoCompressor.js +0 -10
- package/lib/commonjs/Spec/NativeVideoCompressor.js.map +0 -1
- package/lib/module/Spec/NativeVideoCompressor.js +0 -3
- package/lib/module/Spec/NativeVideoCompressor.js.map +0 -1
- package/lib/typescript/Spec/NativeVideoCompressor.d.ts +0 -13
- package/lib/typescript/Spec/NativeVideoCompressor.d.ts.map +0 -1
- package/src/Spec/NativeVideoCompressor.ts +0 -14
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
package com.reactnativecompressor.Video
|
|
2
|
+
|
|
3
|
+
import android.annotation.SuppressLint
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.media.MediaMetadataRetriever
|
|
6
|
+
import android.net.Uri
|
|
7
|
+
import android.os.Handler
|
|
8
|
+
import android.os.PowerManager
|
|
9
|
+
import android.os.PowerManager.WakeLock
|
|
10
|
+
import com.facebook.react.bridge.LifecycleEventListener
|
|
11
|
+
import com.facebook.react.bridge.Promise
|
|
12
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
13
|
+
import com.facebook.react.bridge.ReadableMap
|
|
14
|
+
import com.reactnativecompressor.Utils.EventEmitterHandler
|
|
15
|
+
import com.reactnativecompressor.Utils.Utils
|
|
16
|
+
import java.util.UUID
|
|
17
|
+
|
|
18
|
+
class VideoCompressorHelper {
|
|
19
|
+
enum class CompressionMethod {
|
|
20
|
+
auto,
|
|
21
|
+
manual
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
var compressionMethod = CompressionMethod.auto
|
|
25
|
+
var bitrate = 0f
|
|
26
|
+
var uuid: String? = ""
|
|
27
|
+
var maxSize = 640.0f
|
|
28
|
+
var progressDivider: Int? = 0
|
|
29
|
+
var minimumFileSizeForCompress = 0.0f
|
|
30
|
+
|
|
31
|
+
companion object {
|
|
32
|
+
private var _reactContext: ReactApplicationContext? = null
|
|
33
|
+
private var backgroundId: String? = null
|
|
34
|
+
private var handler: Handler? = null
|
|
35
|
+
private var runnable: Runnable? = null
|
|
36
|
+
private var powerManager: PowerManager? = null
|
|
37
|
+
private var wakeLock: WakeLock? = null
|
|
38
|
+
private val listener: LifecycleEventListener = object : LifecycleEventListener {
|
|
39
|
+
override fun onHostResume() {}
|
|
40
|
+
override fun onHostPause() {}
|
|
41
|
+
override fun onHostDestroy() {
|
|
42
|
+
if (wakeLock!!.isHeld) {
|
|
43
|
+
wakeLock!!.release()
|
|
44
|
+
EventEmitterHandler.emitBackgroundTaskExpired(backgroundId)
|
|
45
|
+
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@SuppressLint("InvalidWakeLockTag")
|
|
51
|
+
fun video_activateBackgroundTask_helper(options: ReadableMap?, reactContext: ReactApplicationContext): String {
|
|
52
|
+
_reactContext = reactContext
|
|
53
|
+
backgroundId = UUID.randomUUID().toString()
|
|
54
|
+
powerManager = reactContext.getSystemService(Context.POWER_SERVICE) as PowerManager
|
|
55
|
+
wakeLock = powerManager!!.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "bg_wakelock")
|
|
56
|
+
reactContext.addLifecycleEventListener(listener)
|
|
57
|
+
if (!wakeLock!!.isHeld()) {
|
|
58
|
+
wakeLock!!.acquire()
|
|
59
|
+
}
|
|
60
|
+
handler = Handler()
|
|
61
|
+
runnable = Runnable { }
|
|
62
|
+
handler!!.post(runnable!!)
|
|
63
|
+
return ""
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
fun video_deactivateBackgroundTask_helper(options: ReadableMap?, reactContext: ReactApplicationContext?): String {
|
|
67
|
+
if (wakeLock!!.isHeld) wakeLock!!.release()
|
|
68
|
+
|
|
69
|
+
// avoid null pointer exceptio when stop is called without start
|
|
70
|
+
if (handler != null) handler!!.removeCallbacks(runnable!!)
|
|
71
|
+
backgroundId = ""
|
|
72
|
+
return ""
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
fun fromMap(map: ReadableMap): VideoCompressorHelper {
|
|
76
|
+
val options = VideoCompressorHelper()
|
|
77
|
+
val iterator = map.keySetIterator()
|
|
78
|
+
while (iterator.hasNextKey()) {
|
|
79
|
+
val key = iterator.nextKey()
|
|
80
|
+
when (key) {
|
|
81
|
+
"compressionMethod" -> options.compressionMethod = CompressionMethod.valueOf(map.getString(key)!!)
|
|
82
|
+
"maxSize" -> options.maxSize = map.getDouble(key).toFloat()
|
|
83
|
+
"uuid" -> options.uuid = map.getString(key)
|
|
84
|
+
"minimumFileSizeForCompress" -> options.minimumFileSizeForCompress = map.getDouble(key).toFloat()
|
|
85
|
+
"bitrate" -> options.bitrate = map.getDouble(key).toFloat()
|
|
86
|
+
"progressDivider" -> options.progressDivider = map.getInt(key)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return options
|
|
90
|
+
}
|
|
91
|
+
fun VideoCompressManual(fileUrl: String?, options: VideoCompressorHelper, promise: Promise, reactContext: ReactApplicationContext?) {
|
|
92
|
+
try {
|
|
93
|
+
val uri = Uri.parse(fileUrl)
|
|
94
|
+
val srcPath = uri.path
|
|
95
|
+
val destinationPath = Utils.generateCacheFilePath("mp4", reactContext!!)
|
|
96
|
+
val metaRetriever = MediaMetadataRetriever()
|
|
97
|
+
metaRetriever.setDataSource(srcPath)
|
|
98
|
+
var height = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)!!.toInt()
|
|
99
|
+
var width = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)!!.toInt()
|
|
100
|
+
val bitrate = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE)!!.toInt()
|
|
101
|
+
val isPortrait = height > width
|
|
102
|
+
val maxSize = options.maxSize.toInt()
|
|
103
|
+
if (isPortrait && height > maxSize) {
|
|
104
|
+
width = (maxSize.toFloat() / height * width).toInt()
|
|
105
|
+
height = maxSize
|
|
106
|
+
} else if (width > maxSize) {
|
|
107
|
+
height = (maxSize.toFloat() / width * height).toInt()
|
|
108
|
+
width = maxSize
|
|
109
|
+
} else {
|
|
110
|
+
if (options.bitrate == 0f) {
|
|
111
|
+
options.bitrate = (bitrate * 0.8).toInt().toFloat()
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
val videoBitRate = if (options.bitrate > 0) options.bitrate else (height * width * 1.5).toFloat()
|
|
115
|
+
Utils.compressVideo(srcPath!!, destinationPath, width, height, videoBitRate, options.uuid!!,options.progressDivider!!, promise, reactContext)
|
|
116
|
+
} catch (ex: Exception) {
|
|
117
|
+
promise.reject(ex)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
fun VideoCompressAuto(fileUrl: String?, options: VideoCompressorHelper?, promise: Promise?, reactContext: ReactApplicationContext?) {
|
|
122
|
+
AutoVideoCompression.createCompressionSettings(fileUrl, options!!, promise!!, reactContext)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
package com.reactnativecompressor.Video
|
|
2
|
+
|
|
3
|
+
import android.media.MediaMetadataRetriever
|
|
4
|
+
import android.net.Uri
|
|
5
|
+
import android.util.Log
|
|
6
|
+
import com.facebook.react.bridge.Arguments
|
|
7
|
+
import com.facebook.react.bridge.Promise
|
|
8
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
9
|
+
import com.facebook.react.bridge.ReadableMap
|
|
10
|
+
import com.reactnativecompressor.Utils.Utils
|
|
11
|
+
import com.reactnativecompressor.Video.VideoCompressorHelper.Companion.video_activateBackgroundTask_helper
|
|
12
|
+
import com.reactnativecompressor.Video.VideoCompressorHelper.Companion.video_deactivateBackgroundTask_helper
|
|
13
|
+
import java.io.File
|
|
14
|
+
|
|
15
|
+
class VideoMain(private val reactContext: ReactApplicationContext) {
|
|
16
|
+
//Video
|
|
17
|
+
fun compress(
|
|
18
|
+
fileUrl: String,
|
|
19
|
+
optionMap: ReadableMap,
|
|
20
|
+
promise: Promise) {
|
|
21
|
+
var fileUrl: String? = fileUrl
|
|
22
|
+
val options = VideoCompressorHelper.fromMap(optionMap)
|
|
23
|
+
fileUrl = Utils.getRealPath(fileUrl, reactContext, options.uuid,options.progressDivider)
|
|
24
|
+
if (options.compressionMethod === VideoCompressorHelper.CompressionMethod.auto) {
|
|
25
|
+
VideoCompressorHelper.VideoCompressAuto(fileUrl, options, promise, reactContext)
|
|
26
|
+
} else {
|
|
27
|
+
VideoCompressorHelper.VideoCompressManual(fileUrl, options, promise, reactContext)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
fun cancelCompression(
|
|
32
|
+
uuid: String) {
|
|
33
|
+
Utils.cancelCompressionHelper(uuid)
|
|
34
|
+
Log.d("cancelCompression", uuid)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
fun activateBackgroundTask(
|
|
38
|
+
options: ReadableMap,
|
|
39
|
+
promise: Promise) {
|
|
40
|
+
try {
|
|
41
|
+
val response: String = video_activateBackgroundTask_helper(options, reactContext)
|
|
42
|
+
promise.resolve(response)
|
|
43
|
+
} catch (ex: Exception) {
|
|
44
|
+
promise.reject(ex)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
fun deactivateBackgroundTask(
|
|
49
|
+
options: ReadableMap,
|
|
50
|
+
promise: Promise) {
|
|
51
|
+
try {
|
|
52
|
+
val response: String = video_deactivateBackgroundTask_helper(options, reactContext)
|
|
53
|
+
promise.resolve(response)
|
|
54
|
+
} catch (ex: Exception) {
|
|
55
|
+
promise.reject(ex)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
fun getVideoMetaData(filePath: String, promise: Promise) {
|
|
60
|
+
var filePath: String? = filePath
|
|
61
|
+
try {
|
|
62
|
+
filePath = Utils.getRealPath(filePath, reactContext)
|
|
63
|
+
val uri = Uri.parse(filePath)
|
|
64
|
+
val srcPath = uri.path
|
|
65
|
+
val metaRetriever = MediaMetadataRetriever()
|
|
66
|
+
metaRetriever.setDataSource(srcPath)
|
|
67
|
+
val file = File(srcPath)
|
|
68
|
+
val sizeInKBs = (file.length() / 1024).toFloat()
|
|
69
|
+
val actualHeight = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)!!.toInt()
|
|
70
|
+
val actualWidth = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)!!.toInt()
|
|
71
|
+
val duration = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)!!.toLong()
|
|
72
|
+
val creationTime = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE)
|
|
73
|
+
val extension = filePath!!.substring(filePath.lastIndexOf(".") + 1)
|
|
74
|
+
val params = Arguments.createMap()
|
|
75
|
+
params.putString("size", sizeInKBs.toString())
|
|
76
|
+
params.putString("width", actualWidth.toString())
|
|
77
|
+
params.putString("height", actualHeight.toString())
|
|
78
|
+
params.putString("duration", (duration / 1000).toString())
|
|
79
|
+
params.putString("extension", extension)
|
|
80
|
+
params.putString("creationTime", creationTime.toString())
|
|
81
|
+
promise.resolve(params)
|
|
82
|
+
} catch (e: Exception) {
|
|
83
|
+
promise.reject(e)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
package com.reactnativecompressor
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Promise
|
|
4
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
5
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
6
|
+
import com.facebook.react.bridge.ReadableMap
|
|
7
|
+
|
|
8
|
+
abstract class CompressorSpec(context: ReactApplicationContext?) : ReactContextBaseJavaModule(context) {
|
|
9
|
+
abstract fun image_compress(
|
|
10
|
+
imagePath: String,
|
|
11
|
+
optionMap: ReadableMap,
|
|
12
|
+
promise: Promise)
|
|
13
|
+
|
|
14
|
+
abstract fun compress_audio(
|
|
15
|
+
fileUrl: String,
|
|
16
|
+
optionMap: ReadableMap,
|
|
17
|
+
promise: Promise)
|
|
18
|
+
|
|
19
|
+
abstract fun generateFilePath(_extension: String, promise: Promise)
|
|
20
|
+
abstract fun getRealPath(path: String, type: String, promise: Promise)
|
|
21
|
+
abstract fun getVideoMetaData(filePath: String, promise: Promise)
|
|
22
|
+
abstract fun getFileSize(filePath: String, promise: Promise)
|
|
23
|
+
abstract fun compress(fileUrl: String, optionMap: ReadableMap, promise: Promise)
|
|
24
|
+
abstract fun cancelCompression(uuid: String)
|
|
25
|
+
abstract fun upload(fileUrl: String, options: ReadableMap, promise: Promise)
|
|
26
|
+
|
|
27
|
+
abstract fun download(fileUrl: String, options: ReadableMap, promise: Promise)
|
|
28
|
+
abstract fun activateBackgroundTask(options: ReadableMap, promise: Promise)
|
|
29
|
+
abstract fun deactivateBackgroundTask(options: ReadableMap, promise: Promise)
|
|
30
|
+
abstract fun addListener(eventName: String)
|
|
31
|
+
abstract fun removeListeners(count: Double)
|
|
32
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
//
|
|
2
|
+
// AudioMain.swift
|
|
3
|
+
// react-native-compressor
|
|
4
|
+
//
|
|
5
|
+
// Created by Numan on 10/09/2023.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import AVFoundation
|
|
10
|
+
let AlAsset_Library_Scheme = "assets-library"
|
|
11
|
+
class AudioMain{
|
|
12
|
+
static func compress_audio(_ fileUrl: String, optionMap: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
13
|
+
do {
|
|
14
|
+
var fileUrl = fileUrl
|
|
15
|
+
if fileUrl.hasPrefix("file://") {
|
|
16
|
+
fileUrl = fileUrl.replacingOccurrences(of: "file://", with: "")
|
|
17
|
+
}
|
|
18
|
+
let fileManager = FileManager.default
|
|
19
|
+
var isDir: ObjCBool = false
|
|
20
|
+
if !fileManager.fileExists(atPath: fileUrl, isDirectory: &isDir) || isDir.boolValue {
|
|
21
|
+
let err = NSError(domain: "file not found", code: -15, userInfo: nil)
|
|
22
|
+
reject(String(err.code), err.localizedDescription, err)
|
|
23
|
+
return
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let assetOptions: [String: Any] = [AVURLAssetPreferPreciseDurationAndTimingKey: true]
|
|
27
|
+
let asset = AVURLAsset(url: URL(fileURLWithPath: fileUrl), options: assetOptions)
|
|
28
|
+
let quality = optionMap["quality"] as? String ?? ""
|
|
29
|
+
let qualityConstant = getAudioQualityConstant(quality)
|
|
30
|
+
auto_compress_helper(asset, qualityConstant: qualityConstant) { mp3Path, finished in
|
|
31
|
+
if finished {
|
|
32
|
+
resolve("file://\(mp3Path ?? "")")
|
|
33
|
+
} else {
|
|
34
|
+
reject("Error", "Something went wrong", nil)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
} catch {
|
|
38
|
+
reject(error.localizedDescription, error.localizedDescription, nil)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
static func getAudioQualityConstant(_ quality: String) -> String {
|
|
43
|
+
let audioQualityArray = ["low", "medium", "high"]
|
|
44
|
+
if let index = audioQualityArray.firstIndex(of: quality) {
|
|
45
|
+
switch index {
|
|
46
|
+
case 0:
|
|
47
|
+
return AVAssetExportPresetLowQuality
|
|
48
|
+
case 1:
|
|
49
|
+
return AVAssetExportPresetMediumQuality
|
|
50
|
+
case 2:
|
|
51
|
+
return AVAssetExportPresetHighestQuality
|
|
52
|
+
default:
|
|
53
|
+
return AVAssetExportPresetMediumQuality
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return AVAssetExportPresetMediumQuality
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
static func auto_compress_helper(_ avAsset: AVURLAsset, qualityConstant: String, complete completeCallback: @escaping (_ mp3Path: String?, _ finished: Bool) -> Void) {
|
|
60
|
+
var path: String
|
|
61
|
+
if avAsset.url.scheme == AlAsset_Library_Scheme {
|
|
62
|
+
path = avAsset.url.query ?? ""
|
|
63
|
+
if path.isEmpty {
|
|
64
|
+
completeCallback(nil, false)
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
} else {
|
|
68
|
+
path = avAsset.url.path
|
|
69
|
+
if path.isEmpty || !FileManager.default.fileExists(atPath: path) {
|
|
70
|
+
completeCallback(nil, false)
|
|
71
|
+
return
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
let mp3Path = Utils.generateCacheFilePath("m4a")
|
|
76
|
+
|
|
77
|
+
if FileManager.default.fileExists(atPath: mp3Path) {
|
|
78
|
+
completeCallback(mp3Path, true)
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let compatiblePresets = AVAssetExportSession.exportPresets(compatibleWith: avAsset)
|
|
83
|
+
|
|
84
|
+
if compatiblePresets.contains(qualityConstant) {
|
|
85
|
+
let exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetAppleM4A)
|
|
86
|
+
|
|
87
|
+
let mp3Url = URL(fileURLWithPath: mp3Path)
|
|
88
|
+
exportSession?.outputURL = mp3Url
|
|
89
|
+
exportSession?.shouldOptimizeForNetworkUse = true
|
|
90
|
+
exportSession?.outputFileType = .m4a
|
|
91
|
+
|
|
92
|
+
exportSession?.exportAsynchronously(completionHandler: {
|
|
93
|
+
var finished = false
|
|
94
|
+
switch exportSession?.status {
|
|
95
|
+
case .failed:
|
|
96
|
+
print("AVAssetExportSessionStatusFailed, error: \(exportSession?.error?.localizedDescription ?? "").")
|
|
97
|
+
case .cancelled:
|
|
98
|
+
print("AVAssetExportSessionStatusCancelled.")
|
|
99
|
+
case .completed:
|
|
100
|
+
print("AVAssetExportSessionStatusCompleted.")
|
|
101
|
+
finished = true
|
|
102
|
+
case .unknown:
|
|
103
|
+
print("AVAssetExportSessionStatusUnknown")
|
|
104
|
+
case .waiting:
|
|
105
|
+
print("AVAssetExportSessionStatusWaiting")
|
|
106
|
+
case .exporting:
|
|
107
|
+
print("AVAssetExportSessionStatusExporting")
|
|
108
|
+
default:
|
|
109
|
+
break
|
|
110
|
+
}
|
|
111
|
+
completeCallback(mp3Path, finished)
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
package/ios/Compressor.h
CHANGED