react-native-compressor 1.8.24 → 1.8.25

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.
@@ -111,6 +111,7 @@ dependencies {
111
111
  //noinspection GradleDynamicVersion
112
112
  implementation "com.facebook.react:react-native:+"
113
113
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
114
+ implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
114
115
 
115
116
  implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4"
116
117
  implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
@@ -42,7 +42,7 @@ class ImageMain(private val reactContext: ReactApplicationContext) {
42
42
  val srcPath = uri.path
43
43
  val params = Arguments.createMap()
44
44
  val file = File(srcPath)
45
- val sizeInKBs = (file.length() / 1024).toDouble()
45
+ val sizeInBytes = file.length().toDouble()
46
46
  val exif = ExifInterface(srcPath!!)
47
47
  for (tag in exifAttributes) {
48
48
  val value: String? = exif.getAttribute(tag)
@@ -53,7 +53,7 @@ class ImageMain(private val reactContext: ReactApplicationContext) {
53
53
 
54
54
  }
55
55
  val extension = filePath!!.substring(filePath.lastIndexOf(".") + 1)
56
- params.putDouble("size", sizeInKBs)
56
+ params.putDouble("size", sizeInBytes)
57
57
  params.putString("extension", extension)
58
58
  promise.resolve(params)
59
59
  } catch (e: Exception) {
@@ -13,6 +13,7 @@ import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.ESDescriptor
13
13
  import com.googlecode.mp4parser.boxes.mp4.objectdescriptors.SLConfigDescriptor
14
14
  import com.mp4parser.iso14496.part15.AvcConfigurationBox
15
15
  import java.util.*
16
+ import kotlin.reflect.jvm.isAccessible
16
17
 
17
18
  class Track(id: Int, format: MediaFormat, audio: Boolean) {
18
19
 
@@ -186,17 +187,41 @@ class Track(id: Int, format: MediaFormat, audio: Boolean) {
186
187
  val decoderConfigDescriptor = DecoderConfigDescriptor().setup()
187
188
 
188
189
  val audioSpecificConfig = AudioSpecificConfig()
189
- audioSpecificConfig.setAudioObjectType(2)
190
- audioSpecificConfig.setSamplingFrequencyIndex(
191
- samplingFrequencyIndexMap[audioSampleEntry.sampleRate.toInt()]!!
192
- )
193
- audioSpecificConfig.setChannelConfiguration(audioSampleEntry.channelCount)
194
- decoderConfigDescriptor.audioSpecificInfo = audioSpecificConfig
195
- descriptor.decoderConfigDescriptor = decoderConfigDescriptor
196
190
 
197
- val data = descriptor.serialize()
198
- esds.esDescriptor = descriptor
199
- esds.data = data
191
+ // Fix for com.googlecode.mp4parser:isoparser multiple version management
192
+ // Updates based on
193
+ // https://github.com/sannies/mp4parser/commit/9cf7f9185b294ac4fa1cd86be1915cd355d859eb#diff-5860894eeaba912c09de175e617d53d5beecebeadd2b64695ed736f9e598bf55
194
+ // and
195
+ // https://github.com/sannies/mp4parser/commit/b85f62274b56cc68d6c6e3dc2f9d4e23318e3341#diff-5860894eeaba912c09de175e617d53d5beecebeadd2b64695ed736f9e598bf55
196
+ //
197
+ val method = audioSpecificConfig::class.members.firstOrNull { it.name == "setOriginalAudioObjectType" }
198
+ if (method != null) {
199
+ // com.googlecode.mp4parser:isoparser is >= 1.1
200
+ method.isAccessible = true
201
+ method.call(audioSpecificConfig, 2)
202
+ audioSpecificConfig.setSamplingFrequencyIndex(
203
+ samplingFrequencyIndexMap[audioSampleEntry.sampleRate.toInt()]!!
204
+ )
205
+ audioSpecificConfig.setChannelConfiguration(audioSampleEntry.channelCount)
206
+ decoderConfigDescriptor.audioSpecificInfo = audioSpecificConfig
207
+ descriptor.decoderConfigDescriptor = decoderConfigDescriptor
208
+
209
+ esds.esDescriptor = descriptor
210
+ } else {
211
+ // com.googlecode.mp4parser:isoparser is < 1.1 (eg: 1.0.6)
212
+ audioSpecificConfig.setAudioObjectType(2)
213
+ audioSpecificConfig.setSamplingFrequencyIndex(
214
+ samplingFrequencyIndexMap[audioSampleEntry.sampleRate.toInt()]!!
215
+ )
216
+ audioSpecificConfig.setChannelConfiguration(audioSampleEntry.channelCount)
217
+ decoderConfigDescriptor.audioSpecificInfo = audioSpecificConfig
218
+ descriptor.decoderConfigDescriptor = decoderConfigDescriptor
219
+
220
+ val data = descriptor.serialize()
221
+ esds.esDescriptor = descriptor
222
+ esds.data = data
223
+ }
224
+
200
225
  audioSampleEntry.addBox(esds)
201
226
  sampleDescriptionBox.addBox(audioSampleEntry)
202
227
  }
@@ -65,14 +65,14 @@ class VideoMain(private val reactContext: ReactApplicationContext) {
65
65
  val metaRetriever = MediaMetadataRetriever()
66
66
  metaRetriever.setDataSource(srcPath)
67
67
  val file = File(srcPath)
68
- val sizeInKBs = (file.length() / 1024).toDouble()
68
+ val sizeInBytes = (file.length()).toDouble()
69
69
  val actualHeight = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)!!.toInt()
70
70
  val actualWidth = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)!!.toInt()
71
71
  val duration = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)!!.toDouble()
72
72
  val creationTime = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DATE)
73
73
  val extension = filePath!!.substring(filePath.lastIndexOf(".") + 1)
74
74
  val params = Arguments.createMap()
75
- params.putDouble("size", sizeInKBs)
75
+ params.putDouble("size", sizeInBytes)
76
76
  params.putInt("width", actualWidth)
77
77
  params.putInt("height", actualHeight)
78
78
  params.putDouble("duration", duration / 1000)
@@ -14,12 +14,7 @@ let AlAsset_Library_Scheme = "assets-library"
14
14
  class AudioMain{
15
15
  static func compress_audio(_ fileUrl: String, optionMap: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
16
16
  do {
17
- var fileUrl = fileUrl
18
-
19
- if fileUrl.hasPrefix("file://") {
20
- fileUrl = fileUrl.replacingOccurrences(of: "file://", with: "")
21
- }
22
-
17
+ let fileUrl = fileUrl.replacingOccurrences(of: "file://", with: "")
23
18
  let fileManager = FileManager.default
24
19
  var isDir: ObjCBool = false
25
20
  if !fileManager.fileExists(atPath: fileUrl, isDirectory: &isDir) || isDir.boolValue {
@@ -27,19 +22,19 @@ class AudioMain{
27
22
  reject(String(err.code), err.localizedDescription, err)
28
23
  return
29
24
  }
30
-
25
+
31
26
  let audioOptions = AudioOptions.fromDictionary((optionMap as! [String : Any]))
32
- let outputMp3Path = "file://\(Utils.generateCacheFilePath("m4a"))"
33
-
34
- let oldUfileUrlRL = URL(string: fileUrl)!
35
- let newURL = URL(string: outputMp3Path)!
36
-
27
+ let outputMp3Path = Utils.generateCacheFilePath("m4a")
28
+
29
+ let oldUfileUrlRL = URL(fileURLWithPath: fileUrl)
30
+ let newURL = URL(fileURLWithPath: outputMp3Path)
31
+
37
32
  var options = FormatConverter.Options()
38
-
33
+
39
34
  if(audioOptions.samplerate != -1){
40
35
  options.sampleRate = Double(audioOptions.samplerate)
41
36
  }
42
-
37
+
43
38
  if(audioOptions.bitrate != -1){
44
39
  options.bitRate = UInt32(audioOptions.bitrate)
45
40
  }
@@ -49,16 +44,16 @@ class AudioMain{
49
44
  print("output bitrate: \(bitrate)")
50
45
  options.bitRate = UInt32(bitrate)
51
46
  }
52
-
53
-
47
+
48
+
54
49
  if(audioOptions.channels != -1){
55
50
  options.channels = UInt32(audioOptions.channels)
56
51
  }
57
-
52
+
58
53
  options.format = .m4a
59
54
  options.eraseFile = false
60
55
  options.bitDepthRule = .any
61
-
56
+
62
57
  let converter = FormatConverter(inputURL: oldUfileUrlRL, outputURL: newURL, options: options)
63
58
  converter.start { error in
64
59
  // check to see if error isn't nil, otherwise you're good
@@ -68,10 +63,10 @@ class AudioMain{
68
63
  reject(error?.localizedDescription,error?.localizedDescription, error)
69
64
  return
70
65
  }
71
-
66
+
72
67
  resolve(newURL.absoluteString)
73
68
  }
74
-
69
+
75
70
  } catch {
76
71
  reject(error.localizedDescription, error.localizedDescription, nil)
77
72
  }
@@ -176,7 +176,7 @@ class ImageCompressor {
176
176
 
177
177
  }
178
178
 
179
- data=copyExifInfo(actualImagePath: actualImagePath, image: image, data: data)
179
+ data=copyExifInfo(actualImagePath: actualImagePath, image: UIImage(data: data) ?? image, data: data)
180
180
 
181
181
 
182
182
  if isBase64 {
@@ -14,7 +14,7 @@ class CreateVideoThumbnail: NSObject {
14
14
  func create(_ fileUrl:String, options: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
15
15
  let headers = options["headers"] as? [String: Any] ?? [:]
16
16
  let format = "jpeg"
17
-
17
+
18
18
  do {
19
19
  // Prepare cache folder
20
20
  var tempDirectory = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).last ?? ""
@@ -77,8 +77,14 @@ class CreateVideoThumbnail: NSObject {
77
77
  let cachePathDir: String = cacheDir.isEmpty ? "thumbnails/" : cacheDir
78
78
  var cacheDirectoryPath = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).last ?? ""
79
79
  cacheDirectoryPath = (cacheDirectoryPath as NSString).appendingPathComponent(cachePathDir)
80
-
80
+
81
81
  let fm = FileManager.default
82
+
83
+ if !fm.fileExists(atPath: cacheDirectoryPath) {
84
+ reject("Error", "Directory does not exist", nil)
85
+ return
86
+ }
87
+
82
88
  do {
83
89
  let files = try fm.contentsOfDirectory(atPath: cacheDirectoryPath)
84
90
  for file in files {
@@ -1,6 +1,6 @@
1
1
  import Foundation
2
2
  import AssetsLibrary
3
- import AVFoundation
3
+ import AVFoundation
4
4
  import Photos
5
5
  import MobileCoreServices
6
6
 
@@ -10,7 +10,7 @@ struct CompressionError: Error {
10
10
  var localizedDescription: String {
11
11
  return message
12
12
  }
13
-
13
+
14
14
  init(message: String) {
15
15
  self.message = message
16
16
  }
@@ -18,9 +18,9 @@ struct CompressionError: Error {
18
18
 
19
19
  class VideoCompressor {
20
20
  var backgroundTaskId: UIBackgroundTaskIdentifier = .invalid;
21
-
21
+
22
22
  var compressorExports: [String: NextLevelSessionExporter] = [:]
23
-
23
+
24
24
  let metadatas: [String] = [
25
25
  "albumName",
26
26
  "artist",
@@ -74,11 +74,11 @@ class VideoCompressor {
74
74
  reject("failed", "Compression Failed", error)
75
75
  })
76
76
  }
77
-
77
+
78
78
  func cancelCompression(uuid: String) -> Void {
79
79
  compressorExports[uuid]?.cancelExport()
80
80
  }
81
-
81
+
82
82
  func getfileSize(forURL url: Any) -> Double {
83
83
  var fileURL: URL?
84
84
  var fileSize: Double = 0.0
@@ -98,11 +98,11 @@ class VideoCompressor {
98
98
  }
99
99
  return fileSize
100
100
  }
101
-
102
-
101
+
102
+
103
103
  func compressVideo(url: URL, options: [String: Any], onProgress: @escaping (Float) -> Void, onCompletion: @escaping (URL) -> Void, onFailure: @escaping (Error) -> Void){
104
104
  let uuid:String = options["uuid"] as! String
105
-
105
+
106
106
  VideoCompressor.getAbsoluteVideoPath(url.absoluteString, options: options) { absoluteVideoPath in
107
107
  var minimumFileSizeForCompress:Double=0.0;
108
108
  let videoURL = URL(string: absoluteVideoPath)
@@ -135,8 +135,8 @@ class VideoCompressor {
135
135
  onFailure(error)
136
136
  }
137
137
  }
138
-
139
-
138
+
139
+
140
140
 
141
141
  }
142
142
  else
@@ -166,12 +166,12 @@ class VideoCompressor {
166
166
  func getVideoBitrateWithFactor(f:Float)->Int {
167
167
  return Int(f * 2000 * 1000 * 1.13);
168
168
  }
169
-
169
+
170
170
  func autoCompressionHelper(url: URL, options: [String: Any], onProgress: @escaping (Float) -> Void, onCompletion: @escaping (URL) -> Void, onFailure: @escaping (Error) -> Void){
171
171
  let maxSize:Float = options["maxSize"] as! Float;
172
172
  let uuid:String = options["uuid"] as! String
173
173
  let progressDivider=options["progressDivider"] as? Int ?? 0
174
-
174
+
175
175
  let asset = AVAsset(url: url)
176
176
  guard asset.tracks.count >= 1 else {
177
177
  let error = CompressionError(message: "Invalid video URL, no track found")
@@ -179,7 +179,7 @@ class VideoCompressor {
179
179
  return
180
180
  }
181
181
  let track = getVideoTrack(asset: asset);
182
-
182
+
183
183
  let videoSize = track.naturalSize.applying(track.preferredTransform);
184
184
  let actualWidth = Float(abs(videoSize.width))
185
185
  let actualHeight = Float(abs(videoSize.height))
@@ -194,7 +194,7 @@ class VideoCompressor {
194
194
  originalBitrate: Int(bitrate),
195
195
  height: Int(resultHeight), width: Int(resultWidth)
196
196
  );
197
-
197
+
198
198
  exportVideoHelper(url: url, asset: asset, bitRate: videoBitRate, resultWidth: resultWidth, resultHeight: resultHeight,uuid: uuid,progressDivider: progressDivider) { progress in
199
199
  onProgress(progress)
200
200
  } onCompletion: { outputURL in
@@ -206,7 +206,7 @@ class VideoCompressor {
206
206
 
207
207
  func manualCompressionHelper(url: URL, options: [String: Any], onProgress: @escaping (Float) -> Void, onCompletion: @escaping (URL) -> Void, onFailure: @escaping (Error) -> Void){
208
208
  let uuid:String = options["uuid"] as! String
209
- var bitRate=options["bitrate"] as! Float?;
209
+ var bitRate = (options["bitrate"] as? NSNumber)?.floatValue;
210
210
  let progressDivider=options["progressDivider"] as? Int ?? 0
211
211
  let asset = AVAsset(url: url)
212
212
  guard asset.tracks.count >= 1 else {
@@ -215,7 +215,7 @@ class VideoCompressor {
215
215
  return
216
216
  }
217
217
  let track = getVideoTrack(asset: asset);
218
-
218
+
219
219
  let videoSize = track.naturalSize.applying(track.preferredTransform);
220
220
  var width = Float(abs(videoSize.width))
221
221
  var height = Float(abs(videoSize.height))
@@ -243,19 +243,19 @@ class VideoCompressor {
243
243
  onFailure(error)
244
244
  }
245
245
  }
246
-
246
+
247
247
  func exportVideoHelper(url: URL,asset: AVAsset, bitRate: Int,resultWidth:Float,resultHeight:Float,uuid:String,progressDivider: Int, onProgress: @escaping (Float) -> Void, onCompletion: @escaping (URL) -> Void, onFailure: @escaping (Error) -> Void){
248
248
  var currentVideoCompression:Int=0
249
-
249
+
250
250
  var tmpURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
251
251
  .appendingPathComponent(ProcessInfo().globallyUniqueString)
252
252
  .appendingPathExtension("mp4")
253
253
  tmpURL = URL(string: Utils.makeValidUri(filePath: tmpURL.absoluteString))!
254
-
254
+
255
255
  let exporter = NextLevelSessionExporter(withAsset: asset)
256
256
  exporter.outputURL = tmpURL
257
257
  exporter.outputFileType = AVFileType.mp4
258
-
258
+
259
259
  let compressionDict: [String: Any] = [
260
260
  AVVideoAverageBitRateKey: bitRate,
261
261
  AVVideoProfileLevelKey: AVVideoProfileLevelH264HighAutoLevel,
@@ -274,7 +274,7 @@ class VideoCompressor {
274
274
  AVNumberOfChannelsKey: NSNumber(integerLiteral: 2),
275
275
  AVSampleRateKey: NSNumber(value: Float(44100))
276
276
  ]
277
-
277
+
278
278
  compressorExports[uuid] = exporter
279
279
  exporter.export(progressHandler: { (progress) in
280
280
  let roundProgress:Int=Int((progress*100).rounded());
@@ -299,33 +299,33 @@ class VideoCompressor {
299
299
  }
300
300
  })
301
301
  }
302
-
302
+
303
303
  func getVideoTrack(asset: AVAsset) -> AVAssetTrack {
304
304
  let tracks = asset.tracks(withMediaType: AVMediaType.video)
305
305
  return tracks[0];
306
306
  }
307
-
308
-
309
-
307
+
308
+
309
+
310
310
  func getVideoMetaData(_ filePath: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
311
311
  do {
312
312
  VideoCompressor.getAbsoluteVideoPath(filePath, options: [:]) { absoluteImagePath in
313
313
  if absoluteImagePath.hasPrefix("file://") {
314
-
314
+
315
315
  let absoluteImagePath = URL(string: absoluteImagePath)!.path
316
316
  let fileManager = FileManager.default
317
317
  var isDir: ObjCBool = false
318
-
318
+
319
319
  if !fileManager.fileExists(atPath: absoluteImagePath, isDirectory: &isDir) || isDir.boolValue {
320
320
  let err = NSError(domain: "file not found", code: -15, userInfo: nil)
321
321
  reject(String(err.code), err.localizedDescription, err)
322
322
  return
323
323
  }
324
-
324
+
325
325
  let attrs = try? fileManager.attributesOfItem(atPath: absoluteImagePath)
326
326
  if let fileSize = attrs?[FileAttributeKey.size] as? UInt64 {
327
327
  let fileSizeString = fileSize
328
-
328
+
329
329
  var result: [String: Any] = [:]
330
330
  let assetOptions: [String: Any] = [AVURLAssetPreferPreciseDurationAndTimingKey: true]
331
331
  let asset = AVURLAsset(url: URL(fileURLWithPath: absoluteImagePath), options: assetOptions)
@@ -334,25 +334,25 @@ class VideoCompressor {
334
334
  let _extension = (absoluteImagePath as NSString).pathExtension
335
335
  let time = asset.duration
336
336
  let seconds = Double(time.value) / Double(time.timescale)
337
-
337
+
338
338
  result["width"] = size.width
339
339
  result["height"] = size.height
340
340
  result["extension"] = _extension
341
341
  result["size"] = fileSizeString
342
342
  result["duration"] = seconds
343
-
343
+
344
344
  var commonMetadata: [AVMetadataItem] = []
345
345
  for key in self.metadatas {
346
346
  let items = AVMetadataItem.metadataItems(from: asset.commonMetadata, withKey: key, keySpace: AVMetadataKeySpace.common)
347
347
  commonMetadata.append(contentsOf: items)
348
348
  }
349
-
349
+
350
350
  for item in commonMetadata {
351
351
  if let value = item.value {
352
352
  result[item.commonKey!.rawValue] = value
353
353
  }
354
354
  }
355
-
355
+
356
356
  resolve(result)
357
357
  }
358
358
  }
@@ -362,7 +362,7 @@ class VideoCompressor {
362
362
  reject(error.localizedDescription, error.localizedDescription, nil)
363
363
  }
364
364
  }
365
-
365
+
366
366
  static func getAbsoluteVideoPath(_ videoPath: String, options: [String: Any], completionHandler: @escaping (String) -> Void) {
367
367
  if videoPath.hasPrefix("http://") || videoPath.hasPrefix("https://") {
368
368
  let uuid=options["uuid"] as? String ?? ""
@@ -434,5 +434,5 @@ class VideoCompressor {
434
434
  }
435
435
  }
436
436
  }
437
-
437
+
438
438
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-compressor",
3
- "version": "1.8.24",
3
+ "version": "1.8.25",
4
4
  "description": "Compress Image, Video, and Audio same like Whatsapp & Auto/Manual Compression | Background Upload | Download File | Create Video Thumbnail",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",