react-native-compressor 1.8.6 → 1.8.7

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 CHANGED
@@ -267,7 +267,7 @@ Video.cancelCompression(cancellationVideoId);
267
267
  import { Audio } from 'react-native-compressor';
268
268
 
269
269
  const result = await Audio.compress(
270
- 'file://path_of_file/file_example_MP3_2MG.mp3',
270
+ 'file://path_of_file/file_example_MP3_2MG.wav', // recommended wav file but can be use mp3 file
271
271
  { quality: 'medium' }
272
272
  );
273
273
  ```
@@ -395,6 +395,7 @@ await clearCache(); // this will clear cache of thumbnails cache directory
395
395
  ## Audio
396
396
 
397
397
  - ###### `compress(url: string, options?: audioCompresssionType): Promise<string>`
398
+ Android: recommended to use `wav` file as we convert mp3 to wav then apply bitrate
398
399
 
399
400
  ### audioCompresssionType
400
401
 
@@ -116,7 +116,6 @@ dependencies {
116
116
  implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
117
117
  implementation "com.googlecode.mp4parser:isoparser:1.0.6"
118
118
 
119
- implementation 'io.github.lizhangqu:coreprogress:1.0.2'
120
119
  implementation 'com.github.banketree:AndroidLame-kotlin:v0.0.1'
121
120
  implementation 'javazoom:jlayer:1.0.1'
122
121
  }
@@ -10,6 +10,7 @@ import com.reactnativecompressor.Utils.MediaCache
10
10
  import com.reactnativecompressor.Utils.Utils
11
11
  import com.reactnativecompressor.Utils.Utils.addLog
12
12
  import javazoom.jl.converter.Converter
13
+ import javazoom.jl.decoder.JavaLayerException
13
14
  import java.io.BufferedOutputStream
14
15
  import java.io.File
15
16
  import java.io.FileNotFoundException
@@ -30,16 +31,38 @@ class AudioCompressor {
30
31
  context: ReactApplicationContext,
31
32
  promise: Promise,
32
33
  ) {
34
+ var _fileUrl=fileUrl
33
35
  try {
34
36
  val filePath = fileUrl.replace("file://", "")
35
37
  var wavPath=filePath;
36
38
  var isNonWav:Boolean=false
37
- if (!fileUrl.endsWith(".waw", ignoreCase = true))
39
+ if (fileUrl.endsWith(".mp4", ignoreCase = true))
38
40
  {
39
- addLog("mp3 file found")
41
+ addLog("mp4 file found")
42
+ val mp3Path= Utils.generateCacheFilePath("mp3", context)
43
+ AudioExtractor().genVideoUsingMuxer(fileUrl, mp3Path, -1, -1, true, false)
44
+ _fileUrl="file:/"+mp3Path
40
45
  wavPath= Utils.generateCacheFilePath("wav", context)
46
+ try {
47
+ val converter = Converter()
48
+ converter.convert(mp3Path, wavPath)
49
+ } catch (e: JavaLayerException) {
50
+ addLog("JavaLayerException error"+e.localizedMessage)
51
+ e.printStackTrace();
52
+ }
53
+ isNonWav=true
54
+ }
55
+ else if (!fileUrl.endsWith(".wav", ignoreCase = true))
56
+ {
57
+ addLog("non wav file found")
58
+ wavPath= Utils.generateCacheFilePath("wav", context)
59
+ try {
41
60
  val converter = Converter()
42
61
  converter.convert(filePath, wavPath)
62
+ } catch (e: JavaLayerException) {
63
+ addLog("JavaLayerException error"+e.localizedMessage)
64
+ e.printStackTrace();
65
+ }
43
66
  isNonWav=true
44
67
  }
45
68
 
@@ -56,11 +79,11 @@ class AudioCompressor {
56
79
  promise.resolve(returnableFilePath)
57
80
  } else {
58
81
  addLog("error: "+mp3Path)
59
- promise.resolve(fileUrl)
82
+ promise.resolve(_fileUrl)
60
83
  }
61
84
  }
62
85
  } catch (e: Exception) {
63
- promise.resolve(fileUrl)
86
+ promise.resolve(_fileUrl)
64
87
  }
65
88
  }
66
89
 
@@ -80,6 +103,7 @@ class AudioCompressor {
80
103
  context: ReactApplicationContext,
81
104
  completeCallback: (String, Boolean) -> Unit
82
105
  ) {
106
+ var isCompletedCallbackTriggered:Boolean=false
83
107
  try {
84
108
  var mp3Path = Utils.generateCacheFilePath("mp3", context)
85
109
  val input = File(fileUrl)
@@ -180,7 +204,6 @@ class AudioCompressor {
180
204
  addLog("flushing final mp3buffer")
181
205
  val outputMp3buf = androidLame.flush(mp3Buf)
182
206
  addLog("flushed $outputMp3buf bytes")
183
-
184
207
  if (outputMp3buf > 0) {
185
208
  try {
186
209
  addLog("writing final mp3buffer to outputstream")
@@ -188,6 +211,7 @@ class AudioCompressor {
188
211
  addLog("closing output stream")
189
212
  outputStream!!.close()
190
213
  completeCallback(output.absolutePath, true)
214
+ isCompletedCallbackTriggered=true
191
215
  } catch (e: IOException) {
192
216
  completeCallback(e.localizedMessage, false)
193
217
  e.printStackTrace()
@@ -197,6 +221,10 @@ class AudioCompressor {
197
221
  } catch (e: IOException) {
198
222
  completeCallback(e.localizedMessage, false)
199
223
  }
224
+ if(!isCompletedCallbackTriggered)
225
+ {
226
+ completeCallback("something went wrong", false)
227
+ }
200
228
  }
201
229
 
202
230
 
@@ -0,0 +1,112 @@
1
+ package com.reactnativecompressor.Audio
2
+
3
+ import android.annotation.SuppressLint
4
+ import android.media.MediaCodec
5
+ import android.media.MediaExtractor
6
+ import android.media.MediaFormat
7
+ import android.media.MediaMetadataRetriever
8
+ import android.media.MediaMuxer
9
+ import android.util.Log
10
+ import java.io.IOException
11
+ import java.nio.ByteBuffer
12
+
13
+
14
+ class AudioExtractor {
15
+ /**
16
+ * @param srcPath the path of source video file.
17
+ * @param dstPath the path of destination video file.
18
+ * @param startMs starting time in milliseconds for trimming. Set to
19
+ * negative if starting from beginning.
20
+ * @param endMs end time for trimming in milliseconds. Set to negative if
21
+ * no trimming at the end.
22
+ * @param useAudio true if keep the audio track from the source.
23
+ * @param useVideo true if keep the video track from the source.
24
+ * @throws IOException
25
+ */
26
+ @SuppressLint("NewApi", "WrongConstant")
27
+ @Throws(IOException::class)
28
+ fun genVideoUsingMuxer(srcPath: String?, dstPath: String?, startMs: Int, endMs: Int, useAudio: Boolean, useVideo: Boolean) {
29
+ // Set up MediaExtractor to read from the source.
30
+ val extractor = MediaExtractor()
31
+ extractor.setDataSource(srcPath!!)
32
+ val trackCount = extractor.trackCount
33
+ // Set up MediaMuxer for the destination.
34
+ val muxer: MediaMuxer
35
+ muxer = MediaMuxer(dstPath!!, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
36
+ // Set up the tracks and retrieve the max buffer size for selected
37
+ // tracks.
38
+ val indexMap = HashMap<Int, Int>(trackCount)
39
+ var bufferSize = -1
40
+ for (i in 0 until trackCount) {
41
+ val format = extractor.getTrackFormat(i)
42
+ val mime = format.getString(MediaFormat.KEY_MIME)
43
+ var selectCurrentTrack = false
44
+ if (mime!!.startsWith("audio/") && useAudio) {
45
+ selectCurrentTrack = true
46
+ } else if (mime.startsWith("video/") && useVideo) {
47
+ selectCurrentTrack = true
48
+ }
49
+ if (selectCurrentTrack) {
50
+ extractor.selectTrack(i)
51
+ val dstIndex = muxer.addTrack(format)
52
+ indexMap[i] = dstIndex
53
+ if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
54
+ val newSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE)
55
+ bufferSize = if (newSize > bufferSize) newSize else bufferSize
56
+ }
57
+ }
58
+ }
59
+ if (bufferSize < 0) {
60
+ bufferSize = DEFAULT_BUFFER_SIZE
61
+ }
62
+ // Set up the orientation and starting time for extractor.
63
+ val retrieverSrc = MediaMetadataRetriever()
64
+ retrieverSrc.setDataSource(srcPath)
65
+ val degreesString = retrieverSrc.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION)
66
+ if (degreesString != null) {
67
+ val degrees = degreesString.toInt()
68
+ if (degrees >= 0) {
69
+ muxer.setOrientationHint(degrees)
70
+ }
71
+ }
72
+ if (startMs > 0) {
73
+ extractor.seekTo((startMs * 1000).toLong(), MediaExtractor.SEEK_TO_CLOSEST_SYNC)
74
+ }
75
+ // Copy the samples from MediaExtractor to MediaMuxer. We will loop
76
+ // for copying each sample and stop when we get to the end of the source
77
+ // file or exceed the end time of the trimming.
78
+ val offset = 0
79
+ var trackIndex = -1
80
+ val dstBuf = ByteBuffer.allocate(bufferSize)
81
+ val bufferInfo = MediaCodec.BufferInfo()
82
+ muxer.start()
83
+ while (true) {
84
+ bufferInfo.offset = offset
85
+ bufferInfo.size = extractor.readSampleData(dstBuf, offset)
86
+ if (bufferInfo.size < 0) {
87
+ Log.d(TAG, "Saw input EOS.")
88
+ bufferInfo.size = 0
89
+ break
90
+ } else {
91
+ bufferInfo.presentationTimeUs = extractor.sampleTime
92
+ if (endMs > 0 && bufferInfo.presentationTimeUs > endMs * 1000) {
93
+ Log.d(TAG, "The current sample is over the trim end time.")
94
+ break
95
+ } else {
96
+ bufferInfo.flags = extractor.sampleFlags
97
+ trackIndex = extractor.sampleTrackIndex
98
+ muxer.writeSampleData(indexMap[trackIndex]!!, dstBuf, bufferInfo)
99
+ extractor.advance()
100
+ }
101
+ }
102
+ }
103
+ muxer.stop()
104
+ muxer.release()
105
+ return
106
+ }
107
+
108
+ companion object {
109
+ private const val DEFAULT_BUFFER_SIZE = 1 * 1024 * 1024
110
+ private const val TAG = "AudioExtractorDecoder"
111
+ }
112
+ }
@@ -14,7 +14,7 @@ class AudioMain(private val reactContext: ReactApplicationContext) {
14
14
  val options = AudioHelper.fromMap(optionMap)
15
15
  val quality = options.quality
16
16
  val realPath = Utils.getRealPath(fileUrl, reactContext)
17
- Utils.addLog(fileUrl + "testPath" + realPath)
17
+ Utils.addLog(fileUrl + "\n realPath= " + realPath)
18
18
  AudioCompressor.CompressAudio(realPath!!, quality!!,reactContext,promise)
19
19
  } catch (ex: Exception) {
20
20
  promise.reject(ex)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-compressor",
3
- "version": "1.8.6",
3
+ "version": "1.8.7",
4
4
  "description": "This library compress image, video and audio",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",