react-native-video-trim 7.1.1 → 8.0.0

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
@@ -5,6 +5,12 @@
5
5
  - [API Reference](#api-reference)
6
6
  * [showEditor()](#showeditor)
7
7
  * [trim()](#trim)
8
+ * [getFrameAt()](#getframeat)
9
+ * [extractAudio()](#extractaudio)
10
+ * [compress()](#compress)
11
+ * [toGif()](#togif)
12
+ * [merge()](#merge)
13
+ * [Utility Functions](#utility-functions)
8
14
  * [File Management](#file-management)
9
15
  - [Configuration Options](#configuration-options)
10
16
  * [Basic Options](#basic-options)
@@ -12,6 +18,8 @@
12
18
  * [Behavior Options](#behavior-options)
13
19
  - [Platform Setup](#platform-setup)
14
20
  - [Advanced Features](#advanced-features)
21
+ * [Mute Audio / Remove Audio](#mute-audio--remove-audio)
22
+ * [Speed Adjustment](#speed-adjustment)
15
23
  * [Theming](#theming)
16
24
  * [Audio Trimming](#audio-trimming)
17
25
  * [Remote Files (HTTPS)](#remote-files-https)
@@ -43,6 +51,13 @@ A powerful, easy-to-use video and audio trimming library for React Native applic
43
51
  - **📹 Video & Audio Support** - Trim both video and audio files with waveform visualization
44
52
  - **🔄 Flip, Rotate & Crop** - Built-in video transforms with undo/redo support
45
53
  - **🎯 Precise Trimming** - Optional frame-accurate cuts via hardware-accelerated re-encoding
54
+ - **🔇 Mute / Remove Audio** - Strip audio track via editor toggle or headless option
55
+ - **⏩ Speed Adjustment** - Change playback speed (0.25x–4x) in editor or headless
56
+ - **🗜️ Video Compression** - Reduce file size with quality presets or custom bitrate/resolution
57
+ - **🖼️ Frame Extraction** - Extract a single frame as JPEG/PNG at any timestamp
58
+ - **🎵 Extract Audio** - Pull the audio track out of a video file
59
+ - **🎞️ GIF Conversion** - Convert a video segment to an animated GIF
60
+ - **🔗 Video Merge** - Concatenate multiple clips into a single file (headless)
46
61
  - **🌐 Local & Remote Files** - Support for local storage and HTTPS URLs
47
62
  - **💾 Multiple Save Options** - Photos, Documents, or Share to other apps
48
63
  - **✅ File Validation** - Built-in validation for media files
@@ -57,6 +72,13 @@ A powerful, easy-to-use video and audio trimming library for React Native applic
57
72
  | **Trimming** | Video/audio trimming with visual timeline controls and audio waveform |
58
73
  | **Transforms** | Horizontal flip, 90° rotation, and freeform crop with undo/redo |
59
74
  | **Precise Trimming** | Frame-accurate cuts using hardware re-encoding (opt-in) |
75
+ | **Mute Audio** | Strip audio track from output — editor toggle + headless option |
76
+ | **Speed Control** | 0.25x–4x playback speed — editor selector + headless option |
77
+ | **Compression** | Reduce file size via quality presets or custom bitrate/resolution |
78
+ | **Frame Extraction** | Extract a single frame as JPEG/PNG at a given timestamp |
79
+ | **Audio Extraction** | Extract the audio track from a video into a separate file |
80
+ | **GIF Conversion** | Convert a video segment to an animated GIF with palette optimization |
81
+ | **Video Merge** | Concatenate multiple clips into one file (headless API) |
60
82
  | **Validation** | Check if files are valid video/audio before processing |
61
83
  | **Save Options** | Photos, Documents, Share sheet integration |
62
84
  | **File Management** | Complete file lifecycle management |
@@ -125,6 +147,7 @@ Create `android/app/src/main/res/xml/file_paths.xml`:
125
147
  <?xml version="1.0" encoding="utf-8"?>
126
148
  <paths xmlns:android="http://schemas.android.com/apk/res/android">
127
149
  <files-path name="internal_files" path="." />
150
+ <cache-path name="cache_files" path="." />
128
151
  <external-path name="external_files" path="." />
129
152
  </paths>
130
153
  ```
@@ -227,6 +250,184 @@ const outputPath = await trim('/path/to/video.mp4', {
227
250
  });
228
251
  ```
229
252
 
253
+ ### getFrameAt()
254
+
255
+ Extract a single video frame as a JPEG or PNG image.
256
+
257
+ ```typescript
258
+ getFrameAt(url: string, options?: Partial<FrameExtractionOptions>): Promise<FrameResult>
259
+ ```
260
+
261
+ **Options:**
262
+
263
+ | Option | Type | Default | Description |
264
+ |--------|------|---------|-------------|
265
+ | `time` | `number` | `0` | Timestamp in milliseconds |
266
+ | `format` | `string` | `"jpeg"` | Output format: `"jpeg"` or `"png"` |
267
+ | `quality` | `number` | `80` | JPEG quality (0–100). Ignored for PNG |
268
+ | `maxWidth` | `number` | `-1` | Max width in pixels (`-1` for original) |
269
+ | `maxHeight` | `number` | `-1` | Max height in pixels (`-1` for original) |
270
+
271
+ **Example:**
272
+ ```javascript
273
+ import { getFrameAt } from 'react-native-video-trim';
274
+
275
+ const { outputPath } = await getFrameAt('/path/to/video.mp4', {
276
+ time: 5000, // 5 seconds
277
+ format: 'jpeg',
278
+ quality: 90,
279
+ maxWidth: 640,
280
+ });
281
+ ```
282
+
283
+ ### extractAudio()
284
+
285
+ Extract the audio track from a video file into a separate audio file.
286
+
287
+ ```typescript
288
+ extractAudio(url: string, options?: Partial<ExtractAudioOptions>): Promise<ExtractAudioResult>
289
+ ```
290
+
291
+ **Options:**
292
+
293
+ | Option | Type | Default | Description |
294
+ |--------|------|---------|-------------|
295
+ | `outputExt` | `string` | `"m4a"` | Output format: `"m4a"`, `"wav"`, `"mp3"` (requires FFmpegKit with libmp3lame), etc. |
296
+
297
+ **Returns:** `{ outputPath: string, duration: number }` (duration in milliseconds)
298
+
299
+ **Example:**
300
+ ```javascript
301
+ import { extractAudio } from 'react-native-video-trim';
302
+
303
+ const { outputPath, duration } = await extractAudio('/path/to/video.mp4', {
304
+ outputExt: 'm4a',
305
+ });
306
+ ```
307
+
308
+ ### compress()
309
+
310
+ Compress a video file to reduce its size.
311
+
312
+ ```typescript
313
+ compress(url: string, options?: Partial<CompressOptions>): Promise<CompressResult>
314
+ ```
315
+
316
+ **Options:**
317
+
318
+ | Option | Type | Default | Description |
319
+ |--------|------|---------|-------------|
320
+ | `quality` | `string` | `"medium"` | Preset: `"low"`, `"medium"`, or `"high"` |
321
+ | `bitrate` | `number` | `-1` | Explicit bitrate in bps. Overrides `quality` when set |
322
+ | `width` | `number` | `-1` | Target width (`-1` to keep original) |
323
+ | `height` | `number` | `-1` | Target height (`-1` to keep original) |
324
+ | `frameRate` | `number` | `-1` | Target frame rate (`-1` to keep original) |
325
+ | `outputExt` | `string` | `"mp4"` | Output file extension |
326
+ | `removeAudio` | `boolean` | `false` | Strip audio from the output |
327
+
328
+ **Example:**
329
+ ```javascript
330
+ import { compress } from 'react-native-video-trim';
331
+
332
+ // Quality preset
333
+ const { outputPath } = await compress('/path/to/video.mp4', {
334
+ quality: 'medium',
335
+ });
336
+
337
+ // Custom settings
338
+ const { outputPath } = await compress('/path/to/video.mp4', {
339
+ width: 720,
340
+ bitrate: 2_000_000,
341
+ removeAudio: true,
342
+ });
343
+ ```
344
+
345
+ ### toGif()
346
+
347
+ Convert a video segment to an animated GIF using FFmpeg's palette-based encoding for good quality.
348
+
349
+ ```typescript
350
+ toGif(url: string, options?: Partial<GifOptions>): Promise<GifResult>
351
+ ```
352
+
353
+ **Options:**
354
+
355
+ | Option | Type | Default | Description |
356
+ |--------|------|---------|-------------|
357
+ | `startTime` | `number` | `0` | Start time in milliseconds |
358
+ | `endTime` | `number` | `-1` | End time in milliseconds (`-1` for end of video) |
359
+ | `fps` | `number` | `10` | Frame rate of the GIF |
360
+ | `width` | `number` | `-1` | Width in pixels (`-1` for original). Height auto-scales |
361
+
362
+ **Example:**
363
+ ```javascript
364
+ import { toGif } from 'react-native-video-trim';
365
+
366
+ const { outputPath } = await toGif('/path/to/video.mp4', {
367
+ startTime: 2000,
368
+ endTime: 7000,
369
+ fps: 15,
370
+ width: 320,
371
+ });
372
+ ```
373
+
374
+ ### merge()
375
+
376
+ Concatenate multiple media files into a single file. Headless only (no editor UI).
377
+
378
+ ```typescript
379
+ merge(urls: string[], options?: Partial<MergeOptions>): Promise<MergeResult>
380
+ ```
381
+
382
+ **Options:**
383
+
384
+ | Option | Type | Default | Description |
385
+ |--------|------|---------|-------------|
386
+ | `outputExt` | `string` | `"mp4"` | Output file extension |
387
+
388
+ **Returns:** `{ outputPath: string, duration: number }` (duration in milliseconds)
389
+
390
+ > **Note:** Merge uses FFmpeg's concat filter with hardware-accelerated re-encoding (h264_videotoolbox on iOS, h264_mediacodec on Android). Input clips can have different codecs, resolutions, or frame rates — each input is automatically scaled, padded (letterboxed/pillarboxed), and frame-rate-normalized to match the first clip's dimensions and fps (capped at 30 fps). The output bitrate matches the highest-quality input to preserve quality.
391
+ >
392
+ > **Limitation:** Only **local file paths** are supported. Remote URLs are not supported because the default FFmpegKit build does not include OpenSSL.
393
+
394
+ **Example:**
395
+ ```javascript
396
+ import { merge } from 'react-native-video-trim';
397
+
398
+ const { outputPath, duration } = await merge([
399
+ '/path/to/clip1.mp4',
400
+ '/path/to/clip2.mp4',
401
+ '/path/to/clip3.mp4',
402
+ ]);
403
+ ```
404
+
405
+ ### Utility Functions
406
+
407
+ Standalone functions for saving, sharing, or exporting any output file. These work with output from any API (`compress`, `toGif`, `merge`, `trim`, etc.).
408
+
409
+ | Method | Description | Returns |
410
+ |--------|-------------|---------|
411
+ | `saveToPhoto(filePath)` | Save a file to the device's photo library (requires permission) | `Promise<SaveToPhotoResult>` |
412
+ | `saveToDocuments(filePath)` | Open the system document picker to save a file | `Promise<SaveToDocumentsResult>` |
413
+ | `share(filePath)` | Open the system share sheet for a file | `Promise<ShareResult>` |
414
+
415
+ **Examples:**
416
+ ```javascript
417
+ import { compress, saveToPhoto, share, deleteFile } from 'react-native-video-trim';
418
+
419
+ // Compress then save to photo library
420
+ const { outputPath } = await compress('/path/to/video.mp4', { quality: 'medium' });
421
+ await saveToPhoto(outputPath);
422
+ await deleteFile(outputPath);
423
+
424
+ // Merge then share
425
+ const { outputPath: merged } = await merge(['/clip1.mp4', '/clip2.mp4']);
426
+ await share(merged);
427
+ ```
428
+
429
+ > **Note:** Headless API outputs (`getFrameAt`, `extractAudio`, `compress`, `toGif`, `merge`) are written to the **cache directory**, which the OS may purge under storage pressure when your app is not running. Files from `showEditor` and `trim` are written to the persistent documents directory. For all outputs, call `deleteFile(outputPath)` when you are done with the file, or use `cleanFiles()` periodically to free space.
430
+
230
431
  ### File Management
231
432
 
232
433
  | Method | Description | Returns |
@@ -265,6 +466,8 @@ All configuration options are optional. Here are the most commonly used ones:
265
466
  | `minDuration` | `number` | `1000` | Minimum duration in milliseconds |
266
467
  | `autoplay` | `boolean` | `false` | Auto-play media on load |
267
468
  | `jumpToPositionOnLoad` | `number` | - | Initial position in milliseconds |
469
+ | `removeAudio` | `boolean` | `false` | Strip the audio track from the output (see [Mute Audio](#mute-audio--remove-audio)) |
470
+ | `speed` | `number` | `1.0` | Playback speed multiplier (0.25–4.0). Forces re-encoding when ≠ 1.0 (see [Speed Adjustment](#speed-adjustment)) |
268
471
 
269
472
  ### Save & Share Options
270
473
 
@@ -381,6 +584,10 @@ showEditor(videoPath, {
381
584
  openShareSheetOnFinish: true,
382
585
  removeAfterSavedToPhoto: true,
383
586
 
587
+ // Audio & speed
588
+ removeAudio: false,
589
+ speed: 1.0,
590
+
384
591
  // UI customization
385
592
  theme: 'light',
386
593
  headerText: "Trim Your Video",
@@ -414,6 +621,52 @@ buildscript {
414
621
 
415
622
  ## Advanced Features
416
623
 
624
+ ### Mute Audio / Remove Audio
625
+
626
+ Strip the audio track from the output. Available in both the editor UI and headless APIs.
627
+
628
+ **Editor UI:** A mute toggle button appears in the toolbar (speaker icon). Tap to toggle audio on/off. The mute state carries over to the exported file.
629
+
630
+ **Headless / Config:** Set `removeAudio: true` on `showEditor()`, `trim()`, or `compress()`.
631
+
632
+ ```javascript
633
+ // Editor with audio muted by default
634
+ showEditor(videoUrl, {
635
+ removeAudio: true,
636
+ });
637
+
638
+ // Headless trim without audio
639
+ const result = await trim(videoUrl, {
640
+ startTime: 0,
641
+ endTime: 10000,
642
+ removeAudio: true,
643
+ });
644
+ ```
645
+
646
+ ### Speed Adjustment
647
+
648
+ Change the playback speed of the output (0.25x to 4x). Available in both the editor UI and headless APIs.
649
+
650
+ **Editor UI:** A speed button appears in the toolbar showing the current speed (e.g. "1x"). Tap to open a native speed menu — `UIMenu` on iOS 14+ (with `UIAlertController` fallback on older versions), `PopupMenu` on Android. Choose from: 0.25x, 0.5x, 1x, 1.5x, 2x, 3x, 4x. The preview updates in real time, and the selected speed is applied during export.
651
+
652
+ **Headless / Config:** Set the `speed` option. When speed ≠ 1.0, re-encoding is automatically forced (video via `setpts` filter, audio via `atempo` chain).
653
+
654
+ ```javascript
655
+ // Editor starting at 2x speed
656
+ showEditor(videoUrl, {
657
+ speed: 2.0,
658
+ });
659
+
660
+ // Headless trim at half speed
661
+ const result = await trim(videoUrl, {
662
+ startTime: 0,
663
+ endTime: 30000,
664
+ speed: 0.5,
665
+ });
666
+ ```
667
+
668
+ > **Note:** Speed adjustment forces re-encoding regardless of the `enablePreciseTrimming` flag, since FFmpeg filters are required to alter the tempo.
669
+
417
670
  ### Theming
418
671
 
419
672
  The editor supports dark and light themes. Set the `theme` option to switch between them:
@@ -704,7 +957,9 @@ export default function VideoTrimmer() {
704
957
 
705
958
  - Use `trim()` for batch processing without UI
706
959
  - Clean up generated files regularly with `cleanFiles()`
707
- - Consider file compression for large videos
960
+ - Use `compress()` to reduce large videos before upload
961
+ - `merge()` always re-encodes via the concat filter — expect longer processing for large files or many clips
962
+ - Speed adjustment, compression, and merge force re-encoding — expect longer processing for large files
708
963
 
709
964
  ## Credits
710
965