react-native-video-trim 7.1.0 → 7.1.1

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
@@ -40,7 +40,7 @@ A powerful, easy-to-use video and audio trimming library for React Native applic
40
40
 
41
41
  ### ✨ Key Features
42
42
 
43
- - **📹 Video & Audio Support** - Trim both video and audio files
43
+ - **📹 Video & Audio Support** - Trim both video and audio files with waveform visualization
44
44
  - **🔄 Flip, Rotate & Crop** - Built-in video transforms with undo/redo support
45
45
  - **🎯 Precise Trimming** - Optional frame-accurate cuts via hardware-accelerated re-encoding
46
46
  - **🌐 Local & Remote Files** - Support for local storage and HTTPS URLs
@@ -54,7 +54,7 @@ A powerful, easy-to-use video and audio trimming library for React Native applic
54
54
 
55
55
  | Feature | Description |
56
56
  |---------|-------------|
57
- | **Trimming** | Video/audio trimming with visual timeline controls |
57
+ | **Trimming** | Video/audio trimming with visual timeline controls and audio waveform |
58
58
  | **Transforms** | Horizontal flip, 90° rotation, and freeform crop with undo/redo |
59
59
  | **Precise Trimming** | Frame-accurate cuts using hardware re-encoding (opt-in) |
60
60
  | **Validation** | Check if files are valid video/audio before processing |
@@ -295,6 +295,18 @@ All configuration options are optional. Here are the most commonly used ones:
295
295
  | `handleIconColor` | `string` | - | Trimmer left/right handles color (defaults to black in light theme, white in dark theme) |
296
296
  | `fullScreenModalIOS` | `boolean` | `false` | Use fullscreen modal on iOS |
297
297
 
298
+ ### Audio Waveform Options
299
+
300
+ These options only apply when `type: 'audio'`. The waveform replaces the thumbnail track with a bar visualization of the audio amplitude.
301
+
302
+ | Option | Type | Default | Description |
303
+ |--------|------|---------|-------------|
304
+ | `waveformColor` | `string` | `"white"` | Fill color of the waveform bars |
305
+ | `waveformBackgroundColor` | `string` | `"#3478F6"` | Background color behind the bars |
306
+ | `waveformBarWidth` | `number` | `3` | Width of each bar in dp/pt |
307
+ | `waveformBarGap` | `number` | `2` | Gap between bars in dp/pt |
308
+ | `waveformBarCornerRadius` | `number` | `1.5` | Corner radius of each bar in dp/pt |
309
+
298
310
  ### Dialog Options
299
311
 
300
312
  <details>
@@ -433,11 +445,11 @@ The `headerTextColor` and `handleIconColor` options automatically adapt to the a
433
445
  ### Audio Trimming
434
446
 
435
447
  <div align="center">
436
- <img src="images/audio_android.jpg" width="200" />
437
- <img src="images/audio_ios.jpg" width="200" />
448
+ <img src="images/audio_android.png" width="200" />
449
+ <img src="images/audio_ios.png" width="200" />
438
450
  </div>
439
451
 
440
- For audio-only trimming, specify the media type and output format:
452
+ For audio-only trimming, specify the media type and output format. The editor automatically displays an audio waveform visualization in place of the thumbnail track. The waveform updates on zoom for higher resolution.
441
453
 
442
454
  ```javascript
443
455
  showEditor(audioUrl, {
@@ -447,6 +459,20 @@ showEditor(audioUrl, {
447
459
  });
448
460
  ```
449
461
 
462
+ Customize the waveform appearance:
463
+
464
+ ```javascript
465
+ showEditor(audioUrl, {
466
+ type: 'audio',
467
+ outputExt: 'mp3',
468
+ waveformColor: '#FFFFFF',
469
+ waveformBackgroundColor: '#3478F6',
470
+ waveformBarWidth: 3,
471
+ waveformBarGap: 2,
472
+ waveformBarCornerRadius: 1.5,
473
+ });
474
+ ```
475
+
450
476
  ### Remote Files (HTTPS)
451
477
 
452
478
  To trim remote files, you need the HTTPS-enabled version of FFmpeg:
@@ -204,7 +204,7 @@ object VideoTrimmerUtil {
204
204
  endPosition: Long,
205
205
  callback: SingleCallback<Bitmap, Int>
206
206
  ) {
207
- BackgroundExecutor.execute(object : BackgroundExecutor.Task("", 0L, "") {
207
+ BackgroundExecutor.execute(object : BackgroundExecutor.Task("initial_thumbs", 0L, "") {
208
208
  override fun execute() {
209
209
  try {
210
210
  val interval = (endPosition - startPosition) / (totalThumbsCount - 1)
@@ -0,0 +1,92 @@
1
+ package com.videotrim.widgets
2
+
3
+ import android.content.Context
4
+ import android.graphics.Canvas
5
+ import android.graphics.Color
6
+ import android.graphics.Paint
7
+ import android.graphics.RectF
8
+ import android.util.AttributeSet
9
+ import android.view.View
10
+
11
+ /**
12
+ * Custom View that draws an audio waveform as a row of vertical rounded-rect bars.
13
+ *
14
+ * Each bar's height is driven by a normalized amplitude value in [0, 1].
15
+ * The view recalculates bar count from its own width and maps the amplitudes
16
+ * array proportionally, so it works correctly regardless of whether the
17
+ * amplitudes array has more or fewer entries than the visible bar count.
18
+ *
19
+ * The background color (set via [View.setBackgroundColor]) provides the
20
+ * waveform track color; the bars are drawn on top with [barColor].
21
+ */
22
+ class AudioWaveformView @JvmOverloads constructor(
23
+ context: Context,
24
+ attrs: AttributeSet? = null,
25
+ defStyleAttr: Int = 0
26
+ ) : View(context, attrs, defStyleAttr) {
27
+
28
+ var amplitudes: FloatArray = FloatArray(0)
29
+ private set
30
+ private val barPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
31
+ color = Color.WHITE
32
+ style = Paint.Style.FILL
33
+ }
34
+ private val barRect = RectF()
35
+
36
+ var barColor: Int
37
+ get() = barPaint.color
38
+ set(value) {
39
+ barPaint.color = value
40
+ invalidate()
41
+ }
42
+
43
+ var barWidthPx: Float = 0f
44
+ set(value) {
45
+ field = value
46
+ invalidate()
47
+ }
48
+
49
+ var barGapPx: Float = 0f
50
+ set(value) {
51
+ field = value
52
+ invalidate()
53
+ }
54
+
55
+ var barCornerRadiusPx: Float = 0f
56
+ set(value) {
57
+ field = value
58
+ invalidate()
59
+ }
60
+
61
+ fun setAmplitudes(data: FloatArray) {
62
+ amplitudes = data
63
+ invalidate()
64
+ }
65
+
66
+ override fun onDraw(canvas: Canvas) {
67
+ super.onDraw(canvas)
68
+ if (amplitudes.isEmpty()) return
69
+
70
+ val totalHeight = height.toFloat()
71
+ val step = barWidthPx + barGapPx
72
+ if (step <= 0f) return
73
+ val barCount = (width.toFloat() / step).toInt()
74
+ if (barCount <= 0) return
75
+
76
+ // Keep bars from touching the container edges
77
+ val verticalPadding = barWidthPx * 1.5f
78
+ val drawableHeight = totalHeight - verticalPadding * 2f
79
+ if (drawableHeight <= 0f) return
80
+ val minBarHeight = barWidthPx
81
+
82
+ for (i in 0 until barCount) {
83
+ val ampIndex = (i * amplitudes.size / barCount).coerceIn(0, amplitudes.size - 1)
84
+ val amp = amplitudes[ampIndex]
85
+ val barHeight = (amp * drawableHeight).coerceAtLeast(minBarHeight)
86
+ val x = i * step
87
+ val y = verticalPadding + (drawableHeight - barHeight) / 2f
88
+ barRect.set(x, y, x + barWidthPx, y + barHeight)
89
+ canvas.drawRoundRect(barRect, barCornerRadiusPx, barCornerRadiusPx, barPaint)
90
+ }
91
+ }
92
+ }