+516
patches/react-native-compressor+1.13.0.patch
+516
patches/react-native-compressor+1.13.0.patch
···
1
+
diff --git a/node_modules/react-native-compressor/android/build.gradle b/node_modules/react-native-compressor/android/build.gradle
2
+
index 5071139..84bee34 100644
3
+
--- a/node_modules/react-native-compressor/android/build.gradle
4
+
+++ b/node_modules/react-native-compressor/android/build.gradle
5
+
@@ -115,7 +115,6 @@ dependencies {
6
+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4"
7
+
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
8
+
implementation 'org.mp4parser:isoparser:1.9.56'
9
+
- implementation 'com.github.banketree:AndroidLame-kotlin:v0.0.1'
10
+
implementation 'javazoom:jlayer:1.0.1'
11
+
}
12
+
13
+
diff --git a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioCompressor.kt b/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioCompressor.kt
14
+
deleted file mode 100644
15
+
index 9292d3e..0000000
16
+
--- a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioCompressor.kt
17
+
+++ /dev/null
18
+
@@ -1,264 +0,0 @@
19
+
-package com.reactnativecompressor.Audio
20
+
-
21
+
-
22
+
-import android.annotation.SuppressLint
23
+
-import com.facebook.react.bridge.Promise
24
+
-import com.facebook.react.bridge.ReactApplicationContext
25
+
-import com.facebook.react.bridge.ReadableMap
26
+
-import com.naman14.androidlame.LameBuilder
27
+
-import com.naman14.androidlame.WaveReader
28
+
-import com.reactnativecompressor.Utils.MediaCache
29
+
-import com.reactnativecompressor.Utils.Utils
30
+
-import com.reactnativecompressor.Utils.Utils.addLog
31
+
-import javazoom.jl.converter.Converter
32
+
-import javazoom.jl.decoder.JavaLayerException
33
+
-import java.io.BufferedOutputStream
34
+
-import java.io.File
35
+
-import java.io.FileNotFoundException
36
+
-import java.io.FileOutputStream
37
+
-import java.io.IOException
38
+
-
39
+
-class AudioCompressor {
40
+
- companion object {
41
+
- val TAG="AudioMain"
42
+
- private const val OUTPUT_STREAM_BUFFER = 8192
43
+
-
44
+
- var outputStream: BufferedOutputStream? = null
45
+
- var waveReader: WaveReader? = null
46
+
- @JvmStatic
47
+
- fun CompressAudio(
48
+
- fileUrl: String,
49
+
- optionMap: ReadableMap,
50
+
- context: ReactApplicationContext,
51
+
- promise: Promise,
52
+
- ) {
53
+
- val realPath = Utils.getRealPath(fileUrl, context)
54
+
- var _fileUrl=realPath
55
+
- val filePathWithoutFileUri = realPath!!.replace("file://", "")
56
+
- try {
57
+
- var wavPath=filePathWithoutFileUri;
58
+
- var isNonWav:Boolean=false
59
+
- if (fileUrl.endsWith(".mp4", ignoreCase = true))
60
+
- {
61
+
- addLog("mp4 file found")
62
+
- val mp3Path= Utils.generateCacheFilePath("mp3", context)
63
+
- AudioExtractor().genVideoUsingMuxer(fileUrl, mp3Path, -1, -1, true, false)
64
+
- _fileUrl=Utils.slashifyFilePath(mp3Path)
65
+
- wavPath= Utils.generateCacheFilePath("wav", context)
66
+
- try {
67
+
- val converter = Converter()
68
+
- converter.convert(mp3Path, wavPath)
69
+
- } catch (e: JavaLayerException) {
70
+
- addLog("JavaLayerException error"+e.localizedMessage)
71
+
- e.printStackTrace();
72
+
- }
73
+
- isNonWav=true
74
+
- }
75
+
- else if (!fileUrl.endsWith(".wav", ignoreCase = true))
76
+
- {
77
+
- addLog("non wav file found")
78
+
- wavPath= Utils.generateCacheFilePath("wav", context)
79
+
- try {
80
+
- val converter = Converter()
81
+
- converter.convert(filePathWithoutFileUri, wavPath)
82
+
- } catch (e: JavaLayerException) {
83
+
- addLog("JavaLayerException error"+e.localizedMessage)
84
+
- e.printStackTrace();
85
+
- }
86
+
- isNonWav=true
87
+
- }
88
+
-
89
+
-
90
+
- autoCompressHelper(wavPath,filePathWithoutFileUri, optionMap,context) { mp3Path, finished ->
91
+
- if (finished) {
92
+
- val returnableFilePath:String="file://$mp3Path"
93
+
- addLog("finished: " + returnableFilePath)
94
+
- MediaCache.removeCompletedImagePath(fileUrl)
95
+
- if(isNonWav)
96
+
- {
97
+
- File(wavPath).delete()
98
+
- }
99
+
- promise.resolve(returnableFilePath)
100
+
- } else {
101
+
- addLog("error: "+mp3Path)
102
+
- promise.resolve(_fileUrl)
103
+
- }
104
+
- }
105
+
- } catch (e: Exception) {
106
+
- promise.resolve(_fileUrl)
107
+
- }
108
+
- }
109
+
-
110
+
- @SuppressLint("WrongConstant")
111
+
- private fun autoCompressHelper(
112
+
- fileUrl: String,
113
+
- actualFileUrl: String,
114
+
- optionMap: ReadableMap,
115
+
- context: ReactApplicationContext,
116
+
- completeCallback: (String, Boolean) -> Unit
117
+
- ) {
118
+
-
119
+
- val options = AudioHelper.fromMap(optionMap)
120
+
- val quality = options.quality
121
+
-
122
+
- var isCompletedCallbackTriggered:Boolean=false
123
+
- try {
124
+
- var mp3Path = Utils.generateCacheFilePath("mp3", context)
125
+
- val input = File(fileUrl)
126
+
- val output = File(mp3Path)
127
+
-
128
+
- val CHUNK_SIZE = 8192
129
+
- addLog("Initialising wav reader")
130
+
-
131
+
- waveReader = WaveReader(input)
132
+
-
133
+
- try {
134
+
- waveReader!!.openWave()
135
+
- } catch (e: IOException) {
136
+
- e.printStackTrace()
137
+
- }
138
+
-
139
+
- addLog("Intitialising encoder")
140
+
-
141
+
-
142
+
- // for bitrate
143
+
- var audioBitrate:Int
144
+
- if(options.bitrate != -1)
145
+
- {
146
+
- audioBitrate= options.bitrate/1000
147
+
- }
148
+
- else
149
+
- {
150
+
- audioBitrate=AudioHelper.getDestinationBitrateByQuality(actualFileUrl, quality!!)
151
+
- Utils.addLog("dest bitrate: $audioBitrate")
152
+
- }
153
+
-
154
+
- var androidLame = LameBuilder();
155
+
- androidLame.setOutBitrate(audioBitrate)
156
+
-
157
+
- // for channels
158
+
- var audioChannels:Int
159
+
- if(options.channels != -1){
160
+
- audioChannels= options.channels!!
161
+
- }
162
+
- else
163
+
- {
164
+
- audioChannels=waveReader!!.channels
165
+
- }
166
+
- androidLame.setOutChannels(audioChannels)
167
+
-
168
+
- // for sample rate
169
+
- androidLame.setInSampleRate(waveReader!!.sampleRate)
170
+
- var audioSampleRate:Int
171
+
- if(options.samplerate != -1){
172
+
- audioSampleRate= options.samplerate!!
173
+
- }
174
+
- else
175
+
- {
176
+
- audioSampleRate=waveReader!!.sampleRate
177
+
- }
178
+
- androidLame.setOutSampleRate(audioSampleRate)
179
+
- val androidLameBuild=androidLame.build()
180
+
-
181
+
- try {
182
+
- outputStream = BufferedOutputStream(FileOutputStream(output), OUTPUT_STREAM_BUFFER)
183
+
- } catch (e: FileNotFoundException) {
184
+
- e.printStackTrace()
185
+
- }
186
+
-
187
+
- var bytesRead = 0
188
+
-
189
+
- val buffer_l = ShortArray(CHUNK_SIZE)
190
+
- val buffer_r = ShortArray(CHUNK_SIZE)
191
+
- val mp3Buf = ByteArray(CHUNK_SIZE)
192
+
-
193
+
- val channels = waveReader!!.channels
194
+
-
195
+
- addLog("started encoding")
196
+
- while (true) {
197
+
- try {
198
+
- if (channels == 2) {
199
+
-
200
+
- bytesRead = waveReader!!.read(buffer_l, buffer_r, CHUNK_SIZE)
201
+
- addLog("bytes read=$bytesRead")
202
+
-
203
+
- if (bytesRead > 0) {
204
+
-
205
+
- var bytesEncoded = 0
206
+
- bytesEncoded = androidLameBuild.encode(buffer_l, buffer_r, bytesRead, mp3Buf)
207
+
- addLog("bytes encoded=$bytesEncoded")
208
+
-
209
+
- if (bytesEncoded > 0) {
210
+
- try {
211
+
- addLog("writing mp3 buffer to outputstream with $bytesEncoded bytes")
212
+
- outputStream!!.write(mp3Buf, 0, bytesEncoded)
213
+
- } catch (e: IOException) {
214
+
- e.printStackTrace()
215
+
- }
216
+
-
217
+
- }
218
+
-
219
+
- } else
220
+
- break
221
+
- } else {
222
+
-
223
+
- bytesRead = waveReader!!.read(buffer_l, CHUNK_SIZE)
224
+
- addLog("bytes read=$bytesRead")
225
+
-
226
+
- if (bytesRead > 0) {
227
+
- var bytesEncoded = 0
228
+
-
229
+
- bytesEncoded = androidLameBuild.encode(buffer_l, buffer_l, bytesRead, mp3Buf)
230
+
- addLog("bytes encoded=$bytesEncoded")
231
+
-
232
+
- if (bytesEncoded > 0) {
233
+
- try {
234
+
- addLog("writing mp3 buffer to outputstream with $bytesEncoded bytes")
235
+
- outputStream!!.write(mp3Buf, 0, bytesEncoded)
236
+
- } catch (e: IOException) {
237
+
- e.printStackTrace()
238
+
- }
239
+
-
240
+
- }
241
+
-
242
+
- } else
243
+
- break
244
+
- }
245
+
-
246
+
-
247
+
- } catch (e: IOException) {
248
+
- e.printStackTrace()
249
+
- }
250
+
-
251
+
- }
252
+
-
253
+
- addLog("flushing final mp3buffer")
254
+
- val outputMp3buf = androidLameBuild.flush(mp3Buf)
255
+
- addLog("flushed $outputMp3buf bytes")
256
+
- if (outputMp3buf > 0) {
257
+
- try {
258
+
- addLog("writing final mp3buffer to outputstream")
259
+
- outputStream!!.write(mp3Buf, 0, outputMp3buf)
260
+
- addLog("closing output stream")
261
+
- outputStream!!.close()
262
+
- completeCallback(output.absolutePath, true)
263
+
- isCompletedCallbackTriggered=true
264
+
- } catch (e: IOException) {
265
+
- completeCallback(e.localizedMessage, false)
266
+
- e.printStackTrace()
267
+
- }
268
+
- }
269
+
-
270
+
- } catch (e: IOException) {
271
+
- completeCallback(e.localizedMessage, false)
272
+
- }
273
+
- if(!isCompletedCallbackTriggered)
274
+
- {
275
+
- completeCallback("something went wrong", false)
276
+
- }
277
+
- }
278
+
-
279
+
-
280
+
-
281
+
- }
282
+
-}
283
+
diff --git a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioExtractor.kt b/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioExtractor.kt
284
+
deleted file mode 100644
285
+
index c655182..0000000
286
+
--- a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioExtractor.kt
287
+
+++ /dev/null
288
+
@@ -1,112 +0,0 @@
289
+
-package com.reactnativecompressor.Audio
290
+
-
291
+
-import android.annotation.SuppressLint
292
+
-import android.media.MediaCodec
293
+
-import android.media.MediaExtractor
294
+
-import android.media.MediaFormat
295
+
-import android.media.MediaMetadataRetriever
296
+
-import android.media.MediaMuxer
297
+
-import android.util.Log
298
+
-import java.io.IOException
299
+
-import java.nio.ByteBuffer
300
+
-
301
+
-
302
+
-class AudioExtractor {
303
+
- /**
304
+
- * @param srcPath the path of source video file.
305
+
- * @param dstPath the path of destination video file.
306
+
- * @param startMs starting time in milliseconds for trimming. Set to
307
+
- * negative if starting from beginning.
308
+
- * @param endMs end time for trimming in milliseconds. Set to negative if
309
+
- * no trimming at the end.
310
+
- * @param useAudio true if keep the audio track from the source.
311
+
- * @param useVideo true if keep the video track from the source.
312
+
- * @throws IOException
313
+
- */
314
+
- @SuppressLint("NewApi", "WrongConstant")
315
+
- @Throws(IOException::class)
316
+
- fun genVideoUsingMuxer(srcPath: String?, dstPath: String?, startMs: Int, endMs: Int, useAudio: Boolean, useVideo: Boolean) {
317
+
- // Set up MediaExtractor to read from the source.
318
+
- val extractor = MediaExtractor()
319
+
- extractor.setDataSource(srcPath!!)
320
+
- val trackCount = extractor.trackCount
321
+
- // Set up MediaMuxer for the destination.
322
+
- val muxer: MediaMuxer
323
+
- muxer = MediaMuxer(dstPath!!, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
324
+
- // Set up the tracks and retrieve the max buffer size for selected
325
+
- // tracks.
326
+
- val indexMap = HashMap<Int, Int>(trackCount)
327
+
- var bufferSize = -1
328
+
- for (i in 0 until trackCount) {
329
+
- val format = extractor.getTrackFormat(i)
330
+
- val mime = format.getString(MediaFormat.KEY_MIME)
331
+
- var selectCurrentTrack = false
332
+
- if (mime!!.startsWith("audio/") && useAudio) {
333
+
- selectCurrentTrack = true
334
+
- } else if (mime.startsWith("video/") && useVideo) {
335
+
- selectCurrentTrack = true
336
+
- }
337
+
- if (selectCurrentTrack) {
338
+
- extractor.selectTrack(i)
339
+
- val dstIndex = muxer.addTrack(format)
340
+
- indexMap[i] = dstIndex
341
+
- if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
342
+
- val newSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE)
343
+
- bufferSize = if (newSize > bufferSize) newSize else bufferSize
344
+
- }
345
+
- }
346
+
- }
347
+
- if (bufferSize < 0) {
348
+
- bufferSize = DEFAULT_BUFFER_SIZE
349
+
- }
350
+
- // Set up the orientation and starting time for extractor.
351
+
- val retrieverSrc = MediaMetadataRetriever()
352
+
- retrieverSrc.setDataSource(srcPath)
353
+
- val degreesString = retrieverSrc.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION)
354
+
- if (degreesString != null) {
355
+
- val degrees = degreesString.toInt()
356
+
- if (degrees >= 0) {
357
+
- muxer.setOrientationHint(degrees)
358
+
- }
359
+
- }
360
+
- if (startMs > 0) {
361
+
- extractor.seekTo((startMs * 1000).toLong(), MediaExtractor.SEEK_TO_CLOSEST_SYNC)
362
+
- }
363
+
- // Copy the samples from MediaExtractor to MediaMuxer. We will loop
364
+
- // for copying each sample and stop when we get to the end of the source
365
+
- // file or exceed the end time of the trimming.
366
+
- val offset = 0
367
+
- var trackIndex = -1
368
+
- val dstBuf = ByteBuffer.allocate(bufferSize)
369
+
- val bufferInfo = MediaCodec.BufferInfo()
370
+
- muxer.start()
371
+
- while (true) {
372
+
- bufferInfo.offset = offset
373
+
- bufferInfo.size = extractor.readSampleData(dstBuf, offset)
374
+
- if (bufferInfo.size < 0) {
375
+
- Log.d(TAG, "Saw input EOS.")
376
+
- bufferInfo.size = 0
377
+
- break
378
+
- } else {
379
+
- bufferInfo.presentationTimeUs = extractor.sampleTime
380
+
- if (endMs > 0 && bufferInfo.presentationTimeUs > endMs * 1000) {
381
+
- Log.d(TAG, "The current sample is over the trim end time.")
382
+
- break
383
+
- } else {
384
+
- bufferInfo.flags = extractor.sampleFlags
385
+
- trackIndex = extractor.sampleTrackIndex
386
+
- muxer.writeSampleData(indexMap[trackIndex]!!, dstBuf, bufferInfo)
387
+
- extractor.advance()
388
+
- }
389
+
- }
390
+
- }
391
+
- muxer.stop()
392
+
- muxer.release()
393
+
- return
394
+
- }
395
+
-
396
+
- companion object {
397
+
- private const val DEFAULT_BUFFER_SIZE = 1 * 1024 * 1024
398
+
- private const val TAG = "AudioExtractorDecoder"
399
+
- }
400
+
-}
401
+
diff --git a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioHelper.kt b/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioHelper.kt
402
+
deleted file mode 100644
403
+
index 42040b4..0000000
404
+
--- a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioHelper.kt
405
+
+++ /dev/null
406
+
@@ -1,72 +0,0 @@
407
+
-package com.reactnativecompressor.Audio
408
+
-
409
+
-import android.media.MediaExtractor
410
+
-import android.media.MediaFormat
411
+
-import com.facebook.react.bridge.ReadableMap
412
+
-import com.reactnativecompressor.Utils.Utils
413
+
-import java.io.File
414
+
-import java.io.IOException
415
+
-
416
+
-
417
+
-class AudioHelper {
418
+
-
419
+
- var quality: String? = "medium"
420
+
- var bitrate: Int = -1
421
+
- var samplerate: Int = -1
422
+
- var channels: Int = -1
423
+
- var progressDivider: Int? = 0
424
+
-
425
+
- companion object {
426
+
- fun fromMap(map: ReadableMap): AudioHelper {
427
+
- val options = AudioHelper()
428
+
- val iterator = map.keySetIterator()
429
+
- while (iterator.hasNextKey()) {
430
+
- val key = iterator.nextKey()
431
+
- when (key) {
432
+
- "quality" -> options.quality = map.getString(key)
433
+
- "bitrate" -> {
434
+
- val bitrate = map.getInt(key)
435
+
- options.bitrate = if (bitrate > 320000 || bitrate < 64000) 64000 else bitrate
436
+
- }
437
+
- "samplerate" -> options.samplerate = map.getInt(key)
438
+
- "channels" -> options.channels = map.getInt(key)
439
+
- }
440
+
- }
441
+
- return options
442
+
- }
443
+
-
444
+
-
445
+
- fun getAudioBitrate(path: String): Int {
446
+
- val file = File(path)
447
+
- val fileSize = file.length() * 8 // size in bits
448
+
-
449
+
- val mex = MediaExtractor()
450
+
- try {
451
+
- mex.setDataSource(path)
452
+
- } catch (e: IOException) {
453
+
- e.printStackTrace()
454
+
- }
455
+
-
456
+
- val mf = mex.getTrackFormat(0)
457
+
- val durationUs = mf.getLong(MediaFormat.KEY_DURATION)
458
+
- val durationSec = durationUs / 1_000_000.0 // convert duration to seconds
459
+
-
460
+
- return (fileSize / durationSec).toInt()/1000 // bitrate in bits per second
461
+
- }
462
+
- fun getDestinationBitrateByQuality(path: String, quality: String): Int {
463
+
- val originalBitrate = getAudioBitrate(path)
464
+
- var destinationBitrate = originalBitrate
465
+
- Utils.addLog("source bitrate: $originalBitrate")
466
+
-
467
+
- when (quality.lowercase()) {
468
+
- "low" -> destinationBitrate = maxOf(64, (originalBitrate * 0.3).toInt())
469
+
- "medium" -> destinationBitrate = (originalBitrate * 0.5).toInt()
470
+
- "high" -> destinationBitrate = minOf(320, (originalBitrate * 0.7).toInt())
471
+
- else -> Utils.addLog("Invalid quality level. Please enter 'low', 'medium', or 'high'.")
472
+
- }
473
+
-
474
+
- return destinationBitrate
475
+
- }
476
+
-
477
+
- }
478
+
-}
479
+
diff --git a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioMain.kt b/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioMain.kt
480
+
index 446d4fb..f021909 100644
481
+
--- a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioMain.kt
482
+
+++ b/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioMain.kt
483
+
@@ -11,7 +11,9 @@ class AudioMain(private val reactContext: ReactApplicationContext) {
484
+
promise: Promise) {
485
+
try {
486
+
487
+
- AudioCompressor.CompressAudio(fileUrl,optionMap,reactContext,promise)
488
+
+ // Skip compression on Android to avoid libandroidlame dependency
489
+
+ // Return the original file URL without compression
490
+
+ promise.resolve(fileUrl)
491
+
} catch (ex: Exception) {
492
+
promise.reject(ex)
493
+
}
494
+
diff --git a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Utils/Utils.kt b/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Utils/Utils.kt
495
+
index c14b727..1198908 100644
496
+
--- a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Utils/Utils.kt
497
+
+++ b/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Utils/Utils.kt
498
+
@@ -7,7 +7,6 @@ import android.provider.OpenableColumns
499
+
import android.util.Log
500
+
import com.facebook.react.bridge.Promise
501
+
import com.facebook.react.bridge.ReactApplicationContext
502
+
-import com.reactnativecompressor.Audio.AudioCompressor
503
+
import com.reactnativecompressor.Video.VideoCompressor.CompressionListener
504
+
import com.reactnativecompressor.Video.VideoCompressor.VideoCompressorClass
505
+
import java.io.FileNotFoundException
506
+
@@ -152,10 +151,6 @@ object Utils {
507
+
}
508
+
}
509
+
510
+
- fun addLog(log: String) {
511
+
- Log.d(AudioCompressor.TAG, log)
512
+
- }
513
+
-
514
+
val exifAttributes = arrayOf(
515
+
"FNumber",
516
+
"ApertureValue",
+5
patches/react-native-compressor+1.13.0.patch.md
+5
patches/react-native-compressor+1.13.0.patch.md
···
1
+
# react-native-compressor
2
+
3
+
Patch file taken from https://github.com/numandev1/react-native-compressor/pull/355#issuecomment-3180870738
4
+
5
+
This patch removes the audio compression feature on Android from the library. This is because `libandroidlame.so`, the native dependency, does not support 16kb page sizes, and the Play Store has made this mandatory as of 1st Nov 2025.