react-native-video-trim
v6.1.0
Published
Video trimmer for your React Native app
Maintainers
Readme
Table of Contents
- Overview
- Installation
- Quick Start
- API Reference
- Configuration Options
- Platform Setup
- Advanced Features
- Examples
- Troubleshooting
React Native Video Trim
Overview
A powerful, easy-to-use video and audio trimming library for React Native applications.
✨ Key Features
- 📹 Video & Audio Support - Trim both video and audio files
- 🌐 Local & Remote Files - Support for local storage and HTTPS URLs
- 💾 Multiple Save Options - Photos, Documents, or Share to other apps
- ✅ File Validation - Built-in validation for media files
- 🗂️ File Management - List, clean up, and delete specific files
- 🔄 Universal Architecture - Works with both New and Old React Native architectures
🎛️ Core Capabilities
| Feature | Description | |---------|-------------| | Trimming | Precise video/audio trimming with visual controls | | Validation | Check if files are valid video/audio before processing | | Save Options | Photos, Documents, Share sheet integration | | File Management | Complete file lifecycle management | | Customization | Extensive UI and behavior customization |
Installation
npm install react-native-video-trim
# or
yarn add react-native-video-trimPlatform Setup
npx pod-install iosPermissions Required:
- For saving to Photos: Add
NSPhotoLibraryUsageDescriptiontoInfo.plist
For New Architecture:
cd android && ./gradlew generateCodegenArtifactsFromSchemaPermissions Required:
- For saving to Photos: Add to
AndroidManifest.xml:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />For Share Sheet functionality, add to AndroidManifest.xml:
<application>
<!-- your other configs -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>Create android/app/src/main/res/xml/file_paths.xml:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="internal_files" path="." />
<external-path name="external_files" path="." />
</paths>npx expo prebuildThen rebuild your app. Note: Expo Go may not work due to native dependencies - use development builds or expo run:ios/expo run:android.
Quick Start
Get up and running in 3 simple steps:
import { showEditor } from 'react-native-video-trim';
// 1. Basic usage - open video editor
showEditor(videoUrl);
// 2. With duration limit
showEditor(videoUrl, {
maxDuration: 20,
});
// 3. With save options
showEditor(videoUrl, {
maxDuration: 30,
saveToPhoto: true,
openShareSheetOnFinish: true,
});Complete Example with File Picker
import { showEditor } from 'react-native-video-trim';
import { launchImageLibrary } from 'react-native-image-picker';
const trimVideo = () => {
// Pick a video
launchImageLibrary({ mediaType: 'video' }, (response) => {
if (response.assets && response.assets[0]) {
const videoUri = response.assets[0].uri;
// Open editor
showEditor(videoUri, {
maxDuration: 60, // 60 seconds max
saveToPhoto: true,
});
}
});
};💡 More Examples: Check the example folder for complete implementation details with event listeners for both New and Old architectures.
API Reference
showEditor()
Opens the video trimmer interface.
showEditor(videoPath: string, config?: EditorConfig): voidParameters:
videoPath(string): Path to video file (local or remote HTTPS URL)config(EditorConfig, optional): Configuration options (see Configuration Options)
Example:
showEditor('/path/to/video.mp4', {
maxDuration: 30,
saveToPhoto: true,
});trim()
Programmatically trim a video without showing the UI.
trim(url: string, options: TrimOptions): Promise<TrimResult>Returns: Promise resolving to the TrimResult interface
Example:
const outputPath = await trim('/path/to/video.mp4', {
startTime: 5000, // 5 seconds
endTime: 25000, // 25 seconds
});File Management
| Method | Description | Returns |
|--------|-------------|---------|
| isValidFile(videoPath) | Check if file is valid video/audio | Promise<boolean> |
| listFiles() | List all generated output files | Promise<string[]> |
| cleanFiles() | Delete all generated files | Promise<number> |
| deleteFile(filePath) | Delete specific file | Promise<boolean> |
| closeEditor() | Close the editor interface | void |
Examples:
// Validate file before processing
const isValid = await isValidFile('/path/to/video.mp4');
if (!isValid) {
console.log('Invalid video file');
return;
}
// Clean up generated files
const deletedCount = await cleanFiles();
console.log(`Deleted ${deletedCount} files`);Configuration Options
All configuration options are optional. Here are the most commonly used ones:
Basic Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| type | 'video' \| 'audio' | 'video' | Media type to trim |
| outputExt | string | 'mp4' | Output file extension |
| maxDuration | number | video duration | Maximum duration in milliseconds |
| minDuration | number | 1000 | Minimum duration in milliseconds |
| autoplay | boolean | false | Auto-play media on load |
| jumpToPositionOnLoad | number | - | Initial position in milliseconds |
Save & Share Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| saveToPhoto | boolean | false | Save to photo gallery (requires permissions) |
| openDocumentsOnFinish | boolean | false | Open document picker when done |
| openShareSheetOnFinish | boolean | false | Open share sheet when done |
| removeAfterSavedToPhoto | boolean | false | Delete file after saving to photos |
| removeAfterFailedToSavePhoto | boolean | false | Delete file if saving to photos fails |
| removeAfterSavedToDocuments | boolean | false | Delete file after saving to documents |
| removeAfterFailedToSaveDocuments | boolean | false | Delete file if saving to documents fails |
| removeAfterShared | boolean | false | Delete file after sharing (iOS only) |
| removeAfterFailedToShare | boolean | false | Delete file if sharing fails (iOS only) |
UI Customization
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| cancelButtonText | string | "Cancel" | Cancel button text |
| saveButtonText | string | "Save" | Save button text |
| trimmingText | string | "Trimming video..." | Progress dialog text |
| headerText | string | - | Header text |
| headerTextSize | number | 16 | Header text size |
| headerTextColor | string | - | Header text color |
| trimmerColor | string | - | Trimmer bar color |
| handleIconColor | string | - | Trimmer left/right handles color |
| fullScreenModalIOS | boolean | false | Use fullscreen modal on iOS |
Dialog Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| enableCancelDialog | boolean | true | Show confirmation dialog on cancel |
| cancelDialogTitle | string | "Warning!" | Cancel dialog title |
| cancelDialogMessage | string | "Are you sure want to cancel?" | Cancel dialog message |
| cancelDialogCancelText | string | "Close" | Cancel dialog cancel button text |
| cancelDialogConfirmText | string | "Proceed" | Cancel dialog confirm button text |
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| enableSaveDialog | boolean | true | Show confirmation dialog on save |
| saveDialogTitle | string | "Confirmation!" | Save dialog title |
| saveDialogMessage | string | "Are you sure want to save?" | Save dialog message |
| saveDialogCancelText | string | "Close" | Save dialog cancel button text |
| saveDialogConfirmText | string | "Proceed" | Save dialog confirm button text |
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| enableCancelTrimming | boolean | true | Enable cancel during trimming |
| cancelTrimmingButtonText | string | "Cancel" | Cancel trimming button text |
| enableCancelTrimmingDialog | boolean | true | Show cancel trimming confirmation |
| cancelTrimmingDialogTitle | string | "Warning!" | Cancel trimming dialog title |
| cancelTrimmingDialogMessage | string | "Are you sure want to cancel trimming?" | Cancel trimming dialog message |
| cancelTrimmingDialogCancelText | string | "Close" | Cancel trimming dialog cancel button |
| cancelTrimmingDialogConfirmText | string | "Proceed" | Cancel trimming dialog confirm button |
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| alertOnFailToLoad | boolean | true | Show alert dialog on load failure |
| alertOnFailTitle | string | "Error" | Error dialog title |
| alertOnFailMessage | string | "Fail to load media..." | Error dialog message |
| alertOnFailCloseText | string | "Close" | Error dialog close button text |
Advanced Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| enableHapticFeedback | boolean | true | Enable haptic feedback |
| closeWhenFinish | boolean | true | Close editor when done |
| enableRotation | boolean | false | Enable video rotation |
| rotationAngle | number | 0 | Rotation angle in degrees |
| changeStatusBarColorOnOpen | boolean | false | Change status bar color (Android only) |
| zoomOnWaitingDuration | number | 5000 | Duration for zoom-on-waiting feature in milliseconds (default: 5000) |
Example Configuration
showEditor(videoPath, {
// Basic settings
maxDuration: 60000,
minDuration: 3000,
// Save options
saveToPhoto: true,
openShareSheetOnFinish: true,
removeAfterSavedToPhoto: true,
// UI customization
headerText: "Trim Your Video",
cancelButtonText: "Back",
saveButtonText: "Done",
trimmerColor: "#007AFF",
// Behavior
autoplay: true,
enableCancelTrimming: true,
});Platform Setup
Android SDK Customization
You can override SDK versions in android/build.gradle:
buildscript {
ext {
VideoTrim_kotlinVersion = '2.0.21'
VideoTrim_minSdkVersion = 24
VideoTrim_targetSdkVersion = 34
VideoTrim_compileSdkVersion = 35
VideoTrim_ndkVersion = '27.1.12297006'
}
}Advanced Features
Audio Trimming
For audio-only trimming, specify the media type and output format:
showEditor(audioUrl, {
type: 'audio', // Enable audio mode
outputExt: 'wav', // Output format (mp3, wav, m4a, etc.)
maxDuration: 30000, // 30 seconds max
});Remote Files (HTTPS)
To trim remote files, you need the HTTPS-enabled version of FFmpeg:
Android:
// android/build.gradle
buildscript {
ext {
VideoTrim_ffmpeg_package = 'https'
// Optional: VideoTrim_ffmpeg_version = '6.0.1'
}
}iOS:
FFMPEGKIT_PACKAGE=https FFMPEG_KIT_PACKAGE_VERSION=6.0 pod installUsage:
showEditor('https://example.com/video.mp4', {
maxDuration: 60000,
});Video Rotation
Rotate videos during trimming using metadata (doesn't re-encode):
showEditor(videoUrl, {
enableRotation: true,
rotationAngle: 90, // 90, 180, 270 degrees
});Note: Uses display_rotation metadata - playback may vary by platform/player.
Trimming Progress & Cancellation
Users can cancel trimming while in progress:
showEditor(videoUrl, {
enableCancelTrimming: true,
cancelTrimmingButtonText: "Stop",
trimmingText: "Processing video...",
});Error Handling
Handle loading errors gracefully:
showEditor(videoUrl, {
alertOnFailToLoad: true,
alertOnFailTitle: "Oops!",
alertOnFailMessage: "Cannot load this video file",
alertOnFailCloseText: "OK",
});Examples
Complete Implementation (New Architecture)
import React, { useEffect, useRef } from 'react';
import { TouchableOpacity, Text, View } from 'react-native';
import { showEditor, isValidFile, type Spec } from 'react-native-video-trim';
import { launchImageLibrary } from 'react-native-image-picker';
export default function VideoTrimmer() {
const listeners = useRef({});
useEffect(() => {
// Set up event listeners
listeners.current.onFinishTrimming = (NativeVideoTrim as Spec)
.onFinishTrimming(({ outputPath, startTime, endTime, duration }) => {
console.log('Trimming completed:', {
outputPath,
startTime,
endTime,
duration
});
});
listeners.current.onError = (NativeVideoTrim as Spec)
.onError(({ message, errorCode }) => {
console.error('Trimming error:', message, errorCode);
});
return () => {
// Cleanup listeners
Object.values(listeners.current).forEach(listener =>
listener?.remove()
);
};
}, []);
const selectAndTrimVideo = async () => {
const result = await launchImageLibrary({
mediaType: 'video',
quality: 1,
});
if (result.assets?.[0]?.uri) {
const videoUri = result.assets[0].uri;
// Validate file first
const isValid = await isValidFile(videoUri);
if (!isValid) {
console.log('Invalid video file');
return;
}
// Open editor
showEditor(videoUri, {
maxDuration: 60000, // 1 minute max
saveToPhoto: true, // Save to gallery
openShareSheetOnFinish: true,
headerText: "Trim Video",
trimmerColor: "#007AFF",
});
}
};
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<TouchableOpacity
onPress={selectAndTrimVideo}
style={{
backgroundColor: '#007AFF',
padding: 15,
borderRadius: 8
}}
>
<Text style={{ color: 'white', fontSize: 16 }}>
Select & Trim Video
</Text>
</TouchableOpacity>
</View>
);
}Old Architecture Implementation
import React, { useEffect } from 'react';
import { NativeEventEmitter, NativeModules } from 'react-native';
import { showEditor } from 'react-native-video-trim';
export default function VideoTrimmer() {
useEffect(() => {
const eventEmitter = new NativeEventEmitter(NativeModules.VideoTrim);
const subscription = eventEmitter.addListener('VideoTrim', (event) => {
switch (event.name) {
case 'onFinishTrimming':
console.log('Video trimmed:', event.outputPath);
break;
case 'onError':
console.error('Trimming failed:', event.message);
break;
// Handle other events...
}
});
return () => subscription.remove();
}, []);
// Rest of implementation...
}Troubleshooting
Common Issues
Android Build Errors:
- Ensure
file_paths.xmlexists for share functionality - Check SDK versions match your project requirements
- Verify permissions in
AndroidManifest.xml
iOS Build Errors:
- Run
pod installafter installation - Check Info.plist permissions for photo access
- Use development builds with Expo (not Expo Go)
Runtime Issues:
- Validate files with
isValidFile()before processing - Use HTTPS version for remote files
- Check network connectivity for remote files
- Ensure proper permissions for save operations
Performance Tips
- Use
trim()for batch processing without UI - Clean up generated files regularly with
cleanFiles() - Consider file compression for large videos
Credits
- Android: Based on Android-Video-Trimmer
- iOS: UI from VideoTrimmerControl
