react-native-video-trim 2.2.3 → 2.2.5
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.
|
@@ -56,6 +56,11 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
|
|
|
56
56
|
|
|
57
57
|
private ReactApplicationContext mContext;
|
|
58
58
|
private VideoView mVideoView;
|
|
59
|
+
|
|
60
|
+
// mediaPlayer is used for both video/audio
|
|
61
|
+
// the reason we use mediaPlayer for Video: https://stackoverflow.com/a/73361868/7569705
|
|
62
|
+
// the videoPlayer is to solve the issue after manually seek -> hit play -> it starts from a position slightly before with the one we just sought to
|
|
63
|
+
private MediaPlayer mediaPlayer;
|
|
59
64
|
private ImageView mPlayView;
|
|
60
65
|
private LinearLayout mThumbnailContainer;
|
|
61
66
|
private Uri mSourceUri;
|
|
@@ -96,7 +101,6 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
|
|
|
96
101
|
private TextView cancelBtn;
|
|
97
102
|
private FrameLayout audioBannerView;
|
|
98
103
|
private boolean isVideoType = true;
|
|
99
|
-
private MediaPlayer audioPlayer;
|
|
100
104
|
private ImageView failToLoadBtn;
|
|
101
105
|
|
|
102
106
|
private String mOutputExt = "mp4";
|
|
@@ -110,6 +114,7 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
|
|
|
110
114
|
private String alertOnFailTitle = "Error";
|
|
111
115
|
private String alertOnFailMessage = "Fail to load media. Possibly invalid file or no network connection";
|
|
112
116
|
private String alertOnFailCloseText = "Close";
|
|
117
|
+
private View currentSelectedhandle;
|
|
113
118
|
|
|
114
119
|
public VideoTrimmerView(ReactApplicationContext context, ReadableMap config, AttributeSet attrs) {
|
|
115
120
|
this(context, attrs, 0, config);
|
|
@@ -171,11 +176,11 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
|
|
|
171
176
|
|
|
172
177
|
mVideoView.setOnPreparedListener(mp -> {
|
|
173
178
|
mp.setVideoScalingMode(MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT);
|
|
179
|
+
mediaPlayer = mp;
|
|
174
180
|
mediaPrepared();
|
|
175
181
|
});
|
|
176
182
|
|
|
177
183
|
mVideoView.setOnErrorListener(this::onFailToLoadMedia);
|
|
178
|
-
|
|
179
184
|
mVideoView.setOnCompletionListener(mp -> mediaCompleted());
|
|
180
185
|
} else {
|
|
181
186
|
mVideoView.setVisibility(View.GONE);
|
|
@@ -183,16 +188,16 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
|
|
|
183
188
|
audioBannerView.setVisibility(View.VISIBLE);
|
|
184
189
|
audioBannerView.animate().alpha(1f).setDuration(500).start();
|
|
185
190
|
|
|
186
|
-
|
|
191
|
+
mediaPlayer = new MediaPlayer();
|
|
187
192
|
try {
|
|
188
|
-
|
|
189
|
-
|
|
193
|
+
mediaPlayer.setDataSource(videoURI.toString());
|
|
194
|
+
mediaPlayer.setOnPreparedListener(mp -> {
|
|
190
195
|
mediaPrepared();
|
|
191
196
|
});
|
|
192
|
-
|
|
193
|
-
|
|
197
|
+
mediaPlayer.setOnCompletionListener(mp -> mediaCompleted());
|
|
198
|
+
mediaPlayer.setOnErrorListener(this::onFailToLoadMedia);
|
|
194
199
|
|
|
195
|
-
|
|
200
|
+
mediaPlayer.prepareAsync(); // use prepareAsync to avoid blocking the main thread
|
|
196
201
|
} catch (IOException e) {
|
|
197
202
|
e.printStackTrace();
|
|
198
203
|
mediaFailed();
|
|
@@ -239,7 +244,7 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
|
|
|
239
244
|
}
|
|
240
245
|
|
|
241
246
|
private void mediaPrepared() {
|
|
242
|
-
mDuration =
|
|
247
|
+
mDuration = mediaPlayer.getDuration();
|
|
243
248
|
mMaxDuration = Math.min(mMaxDuration, mDuration);
|
|
244
249
|
|
|
245
250
|
if (isVideoType) {
|
|
@@ -327,46 +332,23 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
|
|
|
327
332
|
}
|
|
328
333
|
|
|
329
334
|
private void playOrPause() {
|
|
330
|
-
if (
|
|
331
|
-
|
|
332
|
-
onMediaPause();
|
|
333
|
-
} else {
|
|
334
|
-
// if current video time >= end time, seek to start time
|
|
335
|
-
if (mVideoView.getCurrentPosition() >= endTime) {
|
|
336
|
-
seekTo(startTime, true);
|
|
337
|
-
}
|
|
338
|
-
mVideoView.start();
|
|
339
|
-
startTimingRunnable();
|
|
340
|
-
}
|
|
341
|
-
setPlayPauseViewIcon(mVideoView.isPlaying());
|
|
342
|
-
|
|
335
|
+
if (mediaPlayer.isPlaying()) {
|
|
336
|
+
onMediaPause();
|
|
343
337
|
} else {
|
|
344
|
-
if (
|
|
345
|
-
|
|
346
|
-
} else {
|
|
347
|
-
if (audioPlayer.getCurrentPosition() >= endTime) {
|
|
348
|
-
seekTo(startTime, true);
|
|
349
|
-
}
|
|
350
|
-
audioPlayer.start();
|
|
351
|
-
startTimingRunnable();
|
|
338
|
+
if (mediaPlayer.getCurrentPosition() >= endTime) {
|
|
339
|
+
seekTo(startTime, true);
|
|
352
340
|
}
|
|
353
|
-
|
|
341
|
+
mediaPlayer.start();
|
|
342
|
+
startTimingRunnable();
|
|
354
343
|
}
|
|
344
|
+
setPlayPauseViewIcon(mediaPlayer.isPlaying());
|
|
355
345
|
}
|
|
356
346
|
|
|
357
347
|
public void onMediaPause() {
|
|
358
|
-
if (
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
setPlayPauseViewIcon(false);
|
|
363
|
-
}
|
|
364
|
-
} else {
|
|
365
|
-
if (audioPlayer.isPlaying()) {
|
|
366
|
-
mTimingHandler.removeCallbacks(mTimingRunnable);
|
|
367
|
-
audioPlayer.pause();
|
|
368
|
-
setPlayPauseViewIcon(false);
|
|
369
|
-
}
|
|
348
|
+
if (mediaPlayer.isPlaying()) {
|
|
349
|
+
mTimingHandler.removeCallbacks(mTimingRunnable);
|
|
350
|
+
mediaPlayer.pause();
|
|
351
|
+
setPlayPauseViewIcon(false);
|
|
370
352
|
}
|
|
371
353
|
}
|
|
372
354
|
|
|
@@ -402,10 +384,10 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
|
|
|
402
384
|
}
|
|
403
385
|
|
|
404
386
|
private void seekTo(long msec, boolean needUpdateProgress) {
|
|
405
|
-
if (
|
|
406
|
-
|
|
387
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
388
|
+
mediaPlayer.seekTo((int) msec, MediaPlayer.SEEK_CLOSEST);
|
|
407
389
|
} else {
|
|
408
|
-
|
|
390
|
+
mediaPlayer.seekTo((int) msec);
|
|
409
391
|
}
|
|
410
392
|
|
|
411
393
|
updateCurrentTime(needUpdateProgress);
|
|
@@ -438,9 +420,15 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
|
|
|
438
420
|
e.printStackTrace();
|
|
439
421
|
}
|
|
440
422
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
423
|
+
try {
|
|
424
|
+
if (mediaPlayer != null) {
|
|
425
|
+
mediaPlayer.stop();
|
|
426
|
+
mediaPlayer.release();
|
|
427
|
+
}
|
|
428
|
+
} catch (IllegalStateException e) {
|
|
429
|
+
// if it's video, resource is released with the view, and here we also call .release which will throw exception
|
|
430
|
+
e.printStackTrace();
|
|
431
|
+
Log.d(TAG, "onDestroy mediaPlayer is already released");
|
|
444
432
|
}
|
|
445
433
|
}
|
|
446
434
|
|
|
@@ -533,13 +521,21 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
|
|
|
533
521
|
mTimingRunnable = new Runnable() {
|
|
534
522
|
@Override
|
|
535
523
|
public void run() {
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
524
|
+
// prevent crashing when video is playing and we close editor
|
|
525
|
+
try {
|
|
526
|
+
if (mediaPlayer == null || !mediaPlayer.isPlaying()) {
|
|
527
|
+
mTimingHandler.removeCallbacks(mTimingRunnable);
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
} catch (IllegalStateException e) {
|
|
531
|
+
e.printStackTrace();
|
|
532
|
+
mTimingHandler.removeCallbacks(mTimingRunnable);
|
|
533
|
+
Log.d(TAG, "startTimingRunnable mediaPlayer is already released");
|
|
534
|
+
return;
|
|
541
535
|
}
|
|
542
536
|
|
|
537
|
+
int currentPosition = mediaPlayer.getCurrentPosition();
|
|
538
|
+
|
|
543
539
|
if (currentPosition >= endTime) {
|
|
544
540
|
onMediaPause();
|
|
545
541
|
seekTo(endTime, true); // Ensure exact end time display
|
|
@@ -555,12 +551,7 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
|
|
|
555
551
|
private void updateCurrentTime(boolean needUpdateProgress) {
|
|
556
552
|
// TODO: check the case after drag the progress indicator and hit play, it'll play a little bit earlier than the progress indicator
|
|
557
553
|
|
|
558
|
-
int currentPosition;
|
|
559
|
-
if (isVideoType) {
|
|
560
|
-
currentPosition = mVideoView.getCurrentPosition();
|
|
561
|
-
} else {
|
|
562
|
-
currentPosition = audioPlayer.getCurrentPosition();
|
|
563
|
-
}
|
|
554
|
+
int currentPosition = mediaPlayer.getCurrentPosition();
|
|
564
555
|
|
|
565
556
|
int duration = mDuration;
|
|
566
557
|
|
|
@@ -568,6 +559,8 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
|
|
|
568
559
|
currentPosition = duration;
|
|
569
560
|
} else if (currentPosition >= endTime - 100) {
|
|
570
561
|
currentPosition = (int) endTime;
|
|
562
|
+
} else if (currentPosition <= startTime + 100) {
|
|
563
|
+
currentPosition = (int) startTime;
|
|
571
564
|
}
|
|
572
565
|
|
|
573
566
|
String currentTime = formatTime(currentPosition);
|
|
@@ -583,9 +576,13 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
|
|
|
583
576
|
// Update progressIndicator position
|
|
584
577
|
float indicatorPosition = (float) currentPosition / duration * (trimmerContainerBg.getWidth() - progressIndicator.getWidth()) + leadingHandle.getWidth();
|
|
585
578
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
579
|
+
if (currentSelectedhandle == leadingHandle) {
|
|
580
|
+
float leftBoundary = trimmerContainer.getX();
|
|
581
|
+
progressIndicator.setX(Math.max(leftBoundary, indicatorPosition));
|
|
582
|
+
} else {
|
|
583
|
+
float rightBoundary = trimmerContainer.getX() + trimmerContainer.getWidth() - progressIndicator.getWidth();
|
|
584
|
+
progressIndicator.setX(Math.min(rightBoundary, indicatorPosition));
|
|
585
|
+
}
|
|
589
586
|
}
|
|
590
587
|
}
|
|
591
588
|
|
|
@@ -655,6 +652,7 @@ public class VideoTrimmerView extends FrameLayout implements IVideoTrimmerView {
|
|
|
655
652
|
handle.setOnTouchListener((view, event) -> {
|
|
656
653
|
switch (event.getAction()) {
|
|
657
654
|
case MotionEvent.ACTION_DOWN:
|
|
655
|
+
currentSelectedhandle = handle;
|
|
658
656
|
didClampWhilePanning = false;
|
|
659
657
|
onMediaPause();
|
|
660
658
|
fadeOutProgressIndicator();
|