react-native-compressor 1.18.2 → 2.0.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.
Files changed (141) hide show
  1. package/android/CMakeLists.txt +27 -0
  2. package/android/build.gradle +56 -58
  3. package/android/gradle.properties +5 -5
  4. package/android/src/main/AndroidManifestNew.xml +3 -0
  5. package/android/src/main/cpp/cpp-adapter.cpp +8 -0
  6. package/android/src/main/java/com/margelo/nitro/compressor/HybridCompressor.kt +213 -0
  7. package/android/src/main/java/com/reactnativecompressor/Image/ImageCompressor.kt +41 -21
  8. package/android/src/main/java/com/reactnativecompressor/NitroCompressorPackage.kt +30 -0
  9. package/android/src/main/java/com/reactnativecompressor/NitroPromiseAdapter.kt +55 -0
  10. package/android/src/main/java/com/reactnativecompressor/Utils/EventEmitterHandler.kt +49 -45
  11. package/android/src/main/java/com/reactnativecompressor/Utils/Utils.kt +1 -1
  12. package/android/src/main/java/com/reactnativecompressor/Video/AutoVideoCompression.kt +1 -1
  13. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressionProfile.kt +21 -11
  14. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/compressor/Compressor.kt +311 -76
  15. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/utils/CompressorUtils.kt +96 -5
  16. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/utils/LocationExtractor.kt +397 -0
  17. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/videoHelpers/LocationBox.kt +47 -0
  18. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/videoHelpers/MP4Builder.kt +39 -7
  19. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/videoHelpers/Mp4Movie.kt +7 -0
  20. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressor/videoHelpers/OutputSurface.kt +30 -4
  21. package/android/src/main/java/com/reactnativecompressor/Video/VideoCompressorHelper.kt +28 -2
  22. package/ios/Audio/FormatConverter/FormatConverter+Compressed.swift +1 -1
  23. package/ios/Audio/FormatConverter/FormatConverter+Utilities.swift +1 -1
  24. package/ios/Audio/FormatConverter/FormatConverter.swift +5 -3
  25. package/ios/HybridCompressor.swift +247 -0
  26. package/ios/Image/ImageCompressor.swift +8 -2
  27. package/ios/Utils/EventEmitterHandler.swift +56 -34
  28. package/ios/Video/NextLevelSessionExporter.swift +43 -8
  29. package/ios/Video/VideoMain.swift +44 -14
  30. package/lib/commonjs/Audio/index.js +1 -1
  31. package/lib/commonjs/Audio/index.js.map +1 -1
  32. package/lib/commonjs/Image/index.js +2 -22
  33. package/lib/commonjs/Image/index.js.map +1 -1
  34. package/lib/commonjs/Main.js +8 -8
  35. package/lib/commonjs/Main.js.map +1 -1
  36. package/lib/commonjs/Video/index.js +25 -65
  37. package/lib/commonjs/Video/index.js.map +1 -1
  38. package/lib/commonjs/specs/Compressor.nitro.js +6 -0
  39. package/lib/commonjs/specs/Compressor.nitro.js.map +1 -0
  40. package/lib/commonjs/utils/Downloader.js +8 -24
  41. package/lib/commonjs/utils/Downloader.js.map +1 -1
  42. package/lib/commonjs/utils/Uploader.js +3 -18
  43. package/lib/commonjs/utils/Uploader.js.map +1 -1
  44. package/lib/commonjs/utils/helpers.js +18 -1
  45. package/lib/commonjs/utils/helpers.js.map +1 -1
  46. package/lib/commonjs/utils/index.js +13 -13
  47. package/lib/commonjs/utils/index.js.map +1 -1
  48. package/lib/module/Audio/index.js +2 -2
  49. package/lib/module/Audio/index.js.map +1 -1
  50. package/lib/module/Image/index.js +3 -23
  51. package/lib/module/Image/index.js.map +1 -1
  52. package/lib/module/Main.js +9 -9
  53. package/lib/module/Main.js.map +1 -1
  54. package/lib/module/Video/index.js +26 -66
  55. package/lib/module/Video/index.js.map +1 -1
  56. package/lib/module/specs/Compressor.nitro.js +4 -0
  57. package/lib/module/specs/Compressor.nitro.js.map +1 -0
  58. package/lib/module/utils/Downloader.js +10 -26
  59. package/lib/module/utils/Downloader.js.map +1 -1
  60. package/lib/module/utils/Uploader.js +5 -20
  61. package/lib/module/utils/Uploader.js.map +1 -1
  62. package/lib/module/utils/helpers.js +16 -0
  63. package/lib/module/utils/helpers.js.map +1 -1
  64. package/lib/module/utils/index.js +2 -1
  65. package/lib/module/utils/index.js.map +1 -1
  66. package/lib/typescript/src/Image/index.d.ts.map +1 -1
  67. package/lib/typescript/src/Main.d.ts +2 -1
  68. package/lib/typescript/src/Main.d.ts.map +1 -1
  69. package/lib/typescript/src/Video/index.d.ts +1 -1
  70. package/lib/typescript/src/Video/index.d.ts.map +1 -1
  71. package/lib/typescript/src/index.d.ts.map +1 -1
  72. package/lib/typescript/src/specs/Compressor.nitro.d.ts +44 -0
  73. package/lib/typescript/src/specs/Compressor.nitro.d.ts.map +1 -0
  74. package/lib/typescript/src/utils/Downloader.d.ts.map +1 -1
  75. package/lib/typescript/src/utils/Uploader.d.ts.map +1 -1
  76. package/lib/typescript/src/utils/helpers.d.ts +7 -0
  77. package/lib/typescript/src/utils/helpers.d.ts.map +1 -1
  78. package/lib/typescript/src/utils/index.d.ts.map +1 -1
  79. package/nitrogen/generated/android/NitroCompressor+autolinking.cmake +81 -0
  80. package/nitrogen/generated/android/NitroCompressor+autolinking.gradle +27 -0
  81. package/nitrogen/generated/android/NitroCompressorOnLoad.cpp +60 -0
  82. package/nitrogen/generated/android/NitroCompressorOnLoad.hpp +34 -0
  83. package/nitrogen/generated/android/c++/JFunc_void.hpp +75 -0
  84. package/nitrogen/generated/android/c++/JFunc_void_double.hpp +75 -0
  85. package/nitrogen/generated/android/c++/JFunc_void_double_double.hpp +75 -0
  86. package/nitrogen/generated/android/c++/JHybridCompressorSpec.cpp +293 -0
  87. package/nitrogen/generated/android/c++/JHybridCompressorSpec.hpp +78 -0
  88. package/nitrogen/generated/android/c++/JVideoThumbnailResult.hpp +73 -0
  89. package/nitrogen/generated/android/kotlin/com/margelo/nitro/compressor/Func_void.kt +80 -0
  90. package/nitrogen/generated/android/kotlin/com/margelo/nitro/compressor/Func_void_double.kt +80 -0
  91. package/nitrogen/generated/android/kotlin/com/margelo/nitro/compressor/Func_void_double_double.kt +80 -0
  92. package/nitrogen/generated/android/kotlin/com/margelo/nitro/compressor/HybridCompressorSpec.kt +141 -0
  93. package/nitrogen/generated/android/kotlin/com/margelo/nitro/compressor/NitroCompressorOnLoad.kt +35 -0
  94. package/nitrogen/generated/android/kotlin/com/margelo/nitro/compressor/VideoThumbnailResult.kt +71 -0
  95. package/nitrogen/generated/ios/c++/HybridCompressorSpecSwift.cpp +11 -0
  96. package/nitrogen/generated/ios/c++/HybridCompressorSpecSwift.hpp +204 -0
  97. package/nitrogen/generated/ios/react_native_compressor+autolinking.rb +62 -0
  98. package/nitrogen/generated/ios/react_native_compressor-Swift-Cxx-Bridge.cpp +89 -0
  99. package/nitrogen/generated/ios/react_native_compressor-Swift-Cxx-Bridge.hpp +337 -0
  100. package/nitrogen/generated/ios/react_native_compressor-Swift-Cxx-Umbrella.hpp +51 -0
  101. package/nitrogen/generated/ios/react_native_compressorAutolinking.mm +33 -0
  102. package/nitrogen/generated/ios/react_native_compressorAutolinking.swift +26 -0
  103. package/nitrogen/generated/ios/swift/Func_void.swift +46 -0
  104. package/nitrogen/generated/ios/swift/Func_void_VideoThumbnailResult.swift +46 -0
  105. package/nitrogen/generated/ios/swift/Func_void_double.swift +46 -0
  106. package/nitrogen/generated/ios/swift/Func_void_double_double.swift +46 -0
  107. package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +46 -0
  108. package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_AnyMap_.swift +46 -0
  109. package/nitrogen/generated/ios/swift/Func_void_std__string.swift +46 -0
  110. package/nitrogen/generated/ios/swift/HybridCompressorSpec.swift +70 -0
  111. package/nitrogen/generated/ios/swift/HybridCompressorSpec_cxx.swift +493 -0
  112. package/nitrogen/generated/ios/swift/VideoThumbnailResult.swift +49 -0
  113. package/nitrogen/generated/shared/c++/HybridCompressorSpec.cpp +36 -0
  114. package/nitrogen/generated/shared/c++/HybridCompressorSpec.hpp +83 -0
  115. package/nitrogen/generated/shared/c++/VideoThumbnailResult.hpp +99 -0
  116. package/package.json +8 -12
  117. package/react-native-compressor.podspec +6 -24
  118. package/src/Audio/index.tsx +2 -2
  119. package/src/Image/index.tsx +3 -26
  120. package/src/Main.tsx +14 -16
  121. package/src/Video/index.tsx +25 -77
  122. package/src/specs/Compressor.nitro.ts +56 -0
  123. package/src/utils/Downloader.tsx +8 -27
  124. package/src/utils/Uploader.tsx +12 -24
  125. package/src/utils/helpers.ts +18 -0
  126. package/src/utils/index.tsx +3 -2
  127. package/android/src/main/java/com/reactnativecompressor/CompressorModule.kt +0 -180
  128. package/android/src/main/java/com/reactnativecompressor/CompressorPackage.kt +0 -34
  129. package/android/src/newarch/CompressorSpec.kt +0 -5
  130. package/android/src/oldarch/CompressorSpec.kt +0 -36
  131. package/ios/Compressor-Bridging-Header.h +0 -6
  132. package/ios/Compressor.h +0 -5
  133. package/ios/Compressor.mm +0 -82
  134. package/ios/CompressorManager.swift +0 -117
  135. package/lib/commonjs/Spec/NativeCompressor.js +0 -9
  136. package/lib/commonjs/Spec/NativeCompressor.js.map +0 -1
  137. package/lib/module/Spec/NativeCompressor.js +0 -5
  138. package/lib/module/Spec/NativeCompressor.js.map +0 -1
  139. package/lib/typescript/src/Spec/NativeCompressor.d.ts +0 -30
  140. package/lib/typescript/src/Spec/NativeCompressor.d.ts.map +0 -1
  141. package/src/Spec/NativeCompressor.ts +0 -41
@@ -1,66 +1,70 @@
1
1
  package com.reactnativecompressor.Utils
2
2
 
3
- import com.facebook.react.bridge.Arguments
4
- import com.facebook.react.bridge.ReactApplicationContext
5
- import com.facebook.react.modules.core.DeviceEventManagerModule
3
+ import java.util.concurrent.ConcurrentHashMap
6
4
 
5
+ /**
6
+ * Routes native progress emissions to the per-call JS callbacks that
7
+ * `HybridCompressor` registers. This replaces the old `RCTDeviceEventEmitter`
8
+ * bridge: Nitro delivers progress through callback parameters, so the domain
9
+ * layer's `emit*` calls (unchanged) are dispatched to the callback registered
10
+ * under the same `uuid` that the JS layer threads through the options map.
11
+ */
7
12
  class EventEmitterHandler {
8
13
  companion object {
9
- public var reactContext: ReactApplicationContext?=null
14
+ private val videoCompressProgressCallbacks = ConcurrentHashMap<String, (Double) -> Unit>()
15
+ private val downloadProgressCallbacks = ConcurrentHashMap<String, (Double) -> Unit>()
16
+ private val uploadProgressCallbacks = ConcurrentHashMap<String, (Double, Double) -> Unit>()
10
17
 
11
- private fun sendEvent(eventName: String,
12
- params: Any?) {
13
- reactContext
14
- ?.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
15
- ?.emit(eventName, params)
18
+ @Volatile
19
+ private var backgroundTaskExpiredCallback: (() -> Unit)? = null
20
+
21
+ // Registration (called by HybridCompressor)
22
+
23
+ fun registerVideoCompressProgress(uuid: String, callback: ((Double) -> Unit)?) {
24
+ if (callback != null) videoCompressProgressCallbacks[uuid] = callback
16
25
  }
17
26
 
18
- fun emitBackgroundTaskExpired(backgroundId: String?){
19
- sendEvent("backgroundTaskExpired",backgroundId)
27
+ fun registerDownloadProgress(uuid: String, callback: ((Double) -> Unit)?) {
28
+ if (callback != null) downloadProgressCallbacks[uuid] = callback
20
29
  }
21
30
 
22
- fun emitVideoCompressProgress(progress:Double,uuid:String){
23
- val params = Arguments.createMap()
24
- val data = Arguments.createMap()
25
- params.putString("uuid", uuid)
26
- data.putDouble("progress", progress)
27
- params.putMap("data", data)
28
- sendEvent("videoCompressProgress", params)
31
+ fun registerUploadProgress(uuid: String, callback: ((Double, Double) -> Unit)?) {
32
+ if (callback != null) uploadProgressCallbacks[uuid] = callback
29
33
  }
30
34
 
31
- fun emitDownloadProgress(progress:Double,uuid:String){
32
- val params = Arguments.createMap()
33
- val data = Arguments.createMap()
34
- params.putString("uuid", uuid)
35
- data.putDouble("progress", progress)
36
- params.putMap("data", data)
37
- sendEvent("downloadProgress", params)
35
+ fun unregister(uuid: String) {
36
+ videoCompressProgressCallbacks.remove(uuid)
37
+ downloadProgressCallbacks.remove(uuid)
38
+ uploadProgressCallbacks.remove(uuid)
38
39
  }
39
40
 
40
- fun emitDownloadProgressError(uuid:String?, error:String?){
41
- if (uuid != null && error != null) {
42
- val params = Arguments.createMap()
43
- val data = Arguments.createMap()
44
- params.putString("uuid", uuid)
45
- params.putString("error", error)
46
- params.putMap("data", data)
47
- sendEvent("downloadProgressError", params)
48
- }
41
+ fun setBackgroundTaskExpiredCallback(callback: (() -> Unit)?) {
42
+ backgroundTaskExpiredCallback = callback
49
43
  }
50
44
 
51
- fun sendUploadProgressEvent(numBytes: Long, totalBytes: Long, uuid:String?) {
52
- if(uuid!=null) {
53
- val _params = Arguments.createMap()
54
- val _data = Arguments.createMap()
55
- _params.putString("uuid", uuid)
56
- _data.putDouble("written", numBytes.toDouble())
57
- _data.putDouble("total", totalBytes.toDouble())
58
- _params.putMap("data", _data)
59
- sendEvent("uploadProgress", _params)
60
- }
45
+ // Emission (called by the domain layer — method names preserved)
46
+
47
+ fun emitBackgroundTaskExpired(backgroundId: String?) {
48
+ backgroundTaskExpiredCallback?.invoke()
61
49
  }
62
50
 
51
+ fun emitVideoCompressProgress(progress: Double, uuid: String) {
52
+ videoCompressProgressCallbacks[uuid]?.invoke(progress)
53
+ }
63
54
 
64
- }
55
+ fun emitDownloadProgress(progress: Double, uuid: String) {
56
+ downloadProgressCallbacks[uuid]?.invoke(progress)
57
+ }
58
+
59
+ fun emitDownloadProgressError(uuid: String?, error: String?) {
60
+ // No JS consumer for `downloadProgressError`; download failures surface
61
+ // through the rejected Promise instead. Kept so domain call sites compile.
62
+ }
65
63
 
64
+ fun sendUploadProgressEvent(numBytes: Long, totalBytes: Long, uuid: String?) {
65
+ if (uuid != null) {
66
+ uploadProgressCallbacks[uuid]?.invoke(numBytes.toDouble(), totalBytes.toDouble())
67
+ }
68
+ }
69
+ }
66
70
  }
@@ -134,7 +134,7 @@ object Utils {
134
134
  if (fileSize >= 0) {
135
135
  promise.resolve(fileSize.toString())
136
136
  } else {
137
- promise.resolve("")
137
+ promise.reject("FILE_SIZE_ERROR", "Failed to get file size for path: $filePath")
138
138
  }
139
139
  }
140
140
  }
@@ -24,7 +24,7 @@ object AutoVideoCompression {
24
24
  val actualHeight = VideoCompressorHelper.getMetadataInt(metaRetriever, MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)
25
25
  val actualWidth = VideoCompressorHelper.getMetadataInt(metaRetriever, MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)
26
26
  val bitrate = VideoCompressorHelper.getMetadataInt(metaRetriever, MediaMetadataRetriever.METADATA_KEY_BITRATE)
27
- val frameRate = VideoCompressorHelper.getMetadataInt(metaRetriever, MediaMetadataRetriever.METADATA_KEY_CAPTURE_FRAMERATE)
27
+ val frameRate = VideoCompressorHelper.getSourceFrameRate(metaRetriever)
28
28
  if (actualHeight <= 0 || actualWidth <= 0) {
29
29
  promise.reject(Throwable("Failed to read the input video dimensions"))
30
30
  return
@@ -12,7 +12,12 @@ data class VideoCompressionProfile(
12
12
  )
13
13
 
14
14
  object VideoCompressionProfileFactory {
15
+ // Fallback when the source frame rate cannot be detected.
15
16
  private const val DEFAULT_FRAME_RATE = 30
17
+ // Hard upper bound. 60 fps covers every modern phone capture (24/25/30/
18
+ // 50/60). Capping at 30 — the previous behaviour — silently halved 60
19
+ // fps recordings and made the output look choppy.
20
+ private const val MAX_FRAME_RATE = 60
16
21
 
17
22
  fun createAuto(
18
23
  sourceWidth: Int,
@@ -99,7 +104,7 @@ object VideoCompressionProfileFactory {
99
104
  return DEFAULT_FRAME_RATE
100
105
  }
101
106
 
102
- return sourceFrameRate.coerceIn(1, DEFAULT_FRAME_RATE)
107
+ return sourceFrameRate.coerceIn(1, MAX_FRAME_RATE)
103
108
  }
104
109
 
105
110
  private fun estimateBitrate(
@@ -111,20 +116,25 @@ object VideoCompressionProfileFactory {
111
116
  targetHeight: Int,
112
117
  targetFrameRate: Int,
113
118
  ): Int {
119
+ // WhatsApp-style bitrate envelope. The previous floors/ceilings
120
+ // were ~2-3x larger and produced "compressed" outputs that were
121
+ // still 20-40 MB for short clips. These bands target ~1.5 Mbps at
122
+ // 720p, which matches WhatsApp's typical output size while keeping
123
+ // visual quality acceptable for chat playback.
114
124
  val targetLongSide = max(targetWidth, targetHeight)
115
125
  val floor = when {
116
- targetLongSide >= 1920 -> 4_000_000
117
- targetLongSide >= 1280 -> 2_200_000
118
- targetLongSide >= 960 -> 1_600_000
119
- targetLongSide >= 720 -> 1_200_000
120
- else -> 850_000
126
+ targetLongSide >= 1920 -> 2_000_000
127
+ targetLongSide >= 1280 -> 1_200_000
128
+ targetLongSide >= 960 -> 900_000
129
+ targetLongSide >= 720 -> 700_000
130
+ else -> 500_000
121
131
  }
122
132
  val ceiling = when {
123
- targetLongSide >= 1920 -> 8_000_000
124
- targetLongSide >= 1280 -> 5_000_000
125
- targetLongSide >= 960 -> 3_500_000
126
- targetLongSide >= 720 -> 2_500_000
127
- else -> 1_500_000
133
+ targetLongSide >= 1920 -> 3_500_000
134
+ targetLongSide >= 1280 -> 2_000_000
135
+ targetLongSide >= 960 -> 1_500_000
136
+ targetLongSide >= 720 -> 1_200_000
137
+ else -> 900_000
128
138
  }
129
139
 
130
140
  if (sourceBitrate <= 0) {