react-native-video-trim 1.0.11 → 1.0.13

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
@@ -97,6 +97,7 @@ export default function App() {
97
97
  onPress={async () => {
98
98
  const result = await launchImageLibrary({
99
99
  mediaType: 'video',
100
+ assetRepresentationMode: 'current',
100
101
  });
101
102
 
102
103
  isValidVideo(result.assets![0]?.uri || '').then((res) =>
@@ -181,9 +181,9 @@ public class VideoTrimModule extends ReactContextBaseJavaModule implements Video
181
181
  });
182
182
  }
183
183
 
184
- @Override public void onError() {
184
+ @Override public void onError(String errorMessage) {
185
185
  WritableMap map = Arguments.createMap();
186
- map.putString("message", "Error when trimming, please try again");
186
+ map.putString("message", errorMessage);
187
187
  sendEvent(getReactApplicationContext(), "onError", map);
188
188
  this.hideDialog();
189
189
  }
@@ -4,7 +4,7 @@ public interface VideoTrimListener {
4
4
  void onStartTrim();
5
5
  void onTrimmingProgress(int percentage);
6
6
  void onFinishTrim(String url);
7
- void onError();
7
+ void onError(String errorMessage);
8
8
  void onCancel();
9
9
  void onSave();
10
10
  }
@@ -18,7 +18,6 @@ import java.io.OutputStream;
18
18
  import java.util.ArrayList;
19
19
  import java.util.List;
20
20
 
21
- @SuppressWarnings({ "ResultOfMethodCallIgnored", "FieldCanBeLocal" })
22
21
  public class StorageUtil {
23
22
  public static String getOutputPath(Context context) { // use same extension as inputFile
24
23
  long timestamp = System.currentTimeMillis() / 1000;
@@ -4,17 +4,10 @@ import android.content.Context;
4
4
  import android.graphics.Bitmap;
5
5
  import android.media.MediaMetadataRetriever;
6
6
  import android.net.Uri;
7
- import android.util.Log;
8
-
9
7
  import com.arthenica.ffmpegkit.FFmpegKit;
10
8
  import com.arthenica.ffmpegkit.ReturnCode;
11
9
  import com.arthenica.ffmpegkit.SessionState;
12
10
  import com.videotrim.interfaces.VideoTrimListener;
13
-
14
- import java.text.SimpleDateFormat;
15
- import java.util.Date;
16
- import java.util.Locale;
17
-
18
11
  import iknow.android.utils.DeviceUtil;
19
12
  import iknow.android.utils.UnitConverter;
20
13
  import iknow.android.utils.callback.SingleCallback;
@@ -37,16 +30,21 @@ public class VideoTrimmerUtil {
37
30
  public static final int THUMB_HEIGHT = UnitConverter.dpToPx(50); // x2 for better resolution
38
31
  private static final int THUMB_RESOLUTION_RES = 2; // double thumb resolution for better quality
39
32
 
40
- public static void trim(Context context, String inputFile, String outputFile, int videoDuration, long startMs, long endMs, final VideoTrimListener callback) {
33
+ public static void trim(String inputFile, String outputFile, int videoDuration, long startMs, long endMs, final VideoTrimListener callback) {
41
34
  String cmd = "-i " + inputFile + " -ss " + startMs + "ms" + " -to " + endMs + "ms -c copy " + outputFile;
42
35
  callback.onStartTrim();
43
36
  FFmpegKit.executeAsync(cmd, session -> {
44
37
  SessionState state = session.getState();
38
+ ReturnCode returnCode = session.getReturnCode();
45
39
 
46
- if (state.equals(SessionState.COMPLETED)) {
40
+ if (ReturnCode.isSuccess(returnCode)) {
41
+ // SUCCESS
47
42
  callback.onFinishTrim(outputFile);
48
- } else {
49
- callback.onError();
43
+ }
44
+ else {
45
+ // CANCEL + FAILURE
46
+ String errorMessage = String.format("Command failed with state %s and rc %s.%s", state, returnCode, session.getFailStackTrace());
47
+ callback.onError(errorMessage);
50
48
  }
51
49
  }, log -> {
52
50
 
@@ -271,7 +271,7 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
271
271
  Toast.makeText(mContext, "Video shorter than 3s, can't proceed", Toast.LENGTH_SHORT).show();
272
272
  } else {
273
273
  mVideoView.pause();
274
- VideoTrimmerUtil.trim(mContext,
274
+ VideoTrimmerUtil.trim(
275
275
  mSourceUri.getPath(),
276
276
  StorageUtil.getOutputPath(mContext),
277
277
  mDuration,
@@ -95,6 +95,7 @@ class VideoTrim: RCTEventEmitter {
95
95
 
96
96
  vc.cancelBtnClicked = {
97
97
  if !self.enableCancelDialog {
98
+ let _ = self.deleteFile(url: destPath) // remove the file we just copied to document directory
98
99
  self.emitEventToJS("onCancelTrimming", eventData: nil)
99
100
 
100
101
  vc.dismiss(animated: true, completion: {
@@ -109,6 +110,7 @@ class VideoTrim: RCTEventEmitter {
109
110
 
110
111
  // Create OK button with action handler
111
112
  let ok = UIAlertAction(title: self.cancelDialogConfirmText, style: .destructive, handler: { (action) -> Void in
113
+ let _ = self.deleteFile(url: destPath) // remove the file we just copied to document directory
112
114
  self.emitEventToJS("onCancelTrimming", eventData: nil)
113
115
 
114
116
  vc.dismiss(animated: true, completion: {
@@ -304,8 +306,9 @@ class VideoTrim: RCTEventEmitter {
304
306
  let _ = self.deleteFile(url: inputFile) // remove the file we just copied to document directory
305
307
 
306
308
  let state = session?.getState()
309
+ let returnCode = session?.getReturnCode()
307
310
 
308
- if state == .completed {
311
+ if ReturnCode.isSuccess(returnCode) {
309
312
  let eventPayload: [String: Any] = ["outputPath": outputFile]
310
313
  self.emitEventToJS("onFinishTrimming", eventData: eventPayload)
311
314
 
@@ -335,11 +338,15 @@ class VideoTrim: RCTEventEmitter {
335
338
  }
336
339
  }
337
340
  } else {
338
- let eventPayload: [String: Any] = ["message": "Some error occured"]
341
+ // CANCEL + FAILURE
342
+ let eventPayload: [String: Any] = ["message": "Command failed with state \(String(describing: FFmpegKitConfig.sessionState(toString: state ?? .failed))) and rc \(String(describing: returnCode)).\(String(describing: session?.getFailStackTrace()))"]
339
343
  self.emitEventToJS("onError", eventData: eventPayload)
340
344
  }
341
345
 
342
- DispatchQueue.main.async {
346
+ // some how in case we trim a very short video the view controller is still visible after first .dismiss call
347
+ // even the file is successfully saved
348
+ // that's why we need a small delay here to ensure vc will be dismissed
349
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
343
350
  dialogMessage.dismiss(animated: false)
344
351
  viewController.dismiss(animated: true, completion: {
345
352
  self.emitEventToJS("onHide", eventData: nil)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-video-trim",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "Video trimmer for your React Native app",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",