Video trimmer for your React Native app
npm install react-native-video-trim

✅ iOS & Android •
✅ New & Old Architecture •
✅ Expo Compatible
A powerful, easy-to-use video and audio trimming library for React Native applications.
- 📹 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
| 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 |


``bash`
npm install react-native-video-trimor
yarn add react-native-video-trim
📱 iOS Setup (React Native CLI)
`bash`
npx pod-install ios
Permissions Required:
- For saving to Photos: Add NSPhotoLibraryUsageDescription to Info.plist
🤖 Android Setup (React Native CLI)
For New Architecture:
`bash`
cd android && ./gradlew generateCodegenArtifactsFromSchema
Permissions Required:
- For saving to Photos: Add to AndroidManifest.xml:`xml`
For Share Sheet functionality, add to AndroidManifest.xml:`xml`
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
android:resource="@xml/file_paths" />
Create android/app/src/main/res/xml/file_paths.xml:`xml`
🔧 Expo Setup
`bash`
npx expo prebuild
Then rebuild your app. Note: Expo Go may not work due to native dependencies - use development builds or expo run:ios/expo run:android.
Get up and running in 3 simple steps:
`javascript
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,
});
`
`javascript
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.
Opens the video trimmer interface.
`typescript`
showEditor(videoPath: string, config?: EditorConfig): void
Parameters:
- videoPath (string): Path to video file (local or remote HTTPS URL)config
- (EditorConfig, optional): Configuration options (see Configuration Options)
Example:
`javascript`
showEditor('/path/to/video.mp4', {
maxDuration: 30,
saveToPhoto: true,
});
Programmatically trim a video without showing the UI.
`typescript`
trim(url: string, options: TrimOptions): Promise
Returns: Promise resolving to the TrimResult interface
Example:
`javascript`
const outputPath = await trim('/path/to/video.mp4', {
startTime: 5000, // 5 seconds
endTime: 25000, // 25 seconds
});
| Method | Description | Returns |
|--------|-------------|---------|
| isValidFile(videoPath) | Check if file is valid video/audio | Promise |listFiles()
| | List all generated output files | Promise |cleanFiles()
| | Delete all generated files | Promise |deleteFile(filePath)
| | Delete specific file | Promise |closeEditor()
| | Close the editor interface | void |
Examples:
`javascript
// 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);`
All configuration options are optional. Here are the most commonly used ones:
| 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 |
| 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) |
| 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 |
Cancel Dialog
| 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 |
Save Dialog
| 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 |
Trimming Cancel Dialog
| 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 |
Error Dialog
| 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 |
| 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) |
`javascript`
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,
});
You can override SDK versions in android/build.gradle:
`gradle`
buildscript {
ext {
VideoTrim_kotlinVersion = '2.0.21'
VideoTrim_minSdkVersion = 24
VideoTrim_targetSdkVersion = 34
VideoTrim_compileSdkVersion = 35
VideoTrim_ndkVersion = '27.1.12297006'
}
}


For audio-only trimming, specify the media type and output format:
`javascript`
showEditor(audioUrl, {
type: 'audio', // Enable audio mode
outputExt: 'wav', // Output format (mp3, wav, m4a, etc.)
maxDuration: 30000, // 30 seconds max
});
To trim remote files, you need the HTTPS-enabled version of FFmpeg:
Android:
`gradle`
// android/build.gradle
buildscript {
ext {
VideoTrim_ffmpeg_package = 'https'
// Optional: VideoTrim_ffmpeg_version = '6.0.1'
}
}
iOS:
`bash`
FFMPEGKIT_PACKAGE=https FFMPEG_KIT_PACKAGE_VERSION=6.0 pod install
Usage:
`javascript`
showEditor('https://example.com/video.mp4', {
maxDuration: 60000,
});
Rotate videos during trimming using metadata (doesn't re-encode):
`javascript`
showEditor(videoUrl, {
enableRotation: true,
rotationAngle: 90, // 90, 180, 270 degrees
});
Note: Uses display_rotation metadata - playback may vary by platform/player.


Users can cancel trimming while in progress:
`javascript`
showEditor(videoUrl, {
enableCancelTrimming: true,
cancelTrimmingButtonText: "Stop",
trimmingText: "Processing video...",
});

Handle loading errors gracefully:
`javascript`
showEditor(videoUrl, {
alertOnFailToLoad: true,
alertOnFailTitle: "Oops!",
alertOnFailMessage: "Cannot load this video file",
alertOnFailCloseText: "OK",
});
`javascript
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 (
style={{
backgroundColor: '#007AFF',
padding: 15,
borderRadius: 8
}}
>
Select & Trim Video
);
}
`
`javascript
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...
}
`
Android Build Errors:
- Ensure file_paths.xml exists for share functionalityAndroidManifest.xml
- Check SDK versions match your project requirements
- Verify permissions in
iOS Build Errors:
- Run pod install after 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
- Use trim() for batch processing without UIcleanFiles()`
- Clean up generated files regularly with
- Consider file compression for large videos
- Android: Based on Android-Video-Trimmer
- iOS: UI from VideoTrimmerControl