npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@zlucksolutions/react-native-video-editor

v1.0.7

Published

Video Editor tool for react-native(Trim, crop etc., add music, add textoverlay etc.)

Readme

react-native-video-editor

A UI-based, native video editing SDK for React Native.

This library provides a ready-to-use video editor UI (similar to social media editors) that allows users to trim, crop, add music, text overlays, and voice-overs — all powered by native iOS and Android implementations.

Important: App developers do not need to construct JSON editing configurations. You simply open the editor, enable features via boolean flags, and receive the exported video.

SDK Demo


Features

  • Built-in video editor UI
  • Trim video
  • Crop / change aspect ratio
  • Add background music (BGM)
  • Add text overlays
  • Add voice-over
  • Automatic audio ducking
  • Native export to device storage
  • Event-driven editor lifecycle

Installation

1. Install the library

npm install @zlucksolutions/react-native-video-editor

or

yarn add @zlucksolutions/react-native-video-editor

2. Install peer dependencies (Automated) ⚡

Run this single command to install all required peer dependencies:

npx react-native-video-editor install

This will automatically:

  • ✅ Detect your package manager (npm/yarn/pnpm)
  • ✅ Install all 16 required peer dependencies
  • ✅ Apply patches to peer dependencies
  • ✅ Run pod install for iOS
  • ✅ Display setup instructions

2.1. Enable automatic patch application

To ensure patches are applied whenever you install dependencies, add the following to your project's package.json:

{
  "scripts": {
    "postinstall": "patch-package"
  },
  "devDependencies": {
    "patch-package": "^8.0.1"
  }
}

Then install patch-package:

npm install --save-dev patch-package

or

yarn add -D patch-package

Why is this needed? This package includes patches for some peer dependencies (like react-native-audio-recorder-player) to fix known issues. The postinstall script ensures these patches are automatically applied after every npm install or yarn install.

2.2. Manual Patching (Alternative)

If you don't want to use patch-package automatically, you can apply the patch manually:

  1. Locate the patch file in your project: node_modules/@zlucksolutions/react-native-video-editor/patches/react-native-audio-recorder-player+3.6.14.patch

  2. Copy it to your project root patches folder:

    mkdir -p patches
    cp node_modules/@zlucksolutions/react-native-video-editor/patches/react-native-audio-recorder-player+3.6.14.patch patches/
  3. Apply it using patch:

    patch -p1 < patches/react-native-audio-recorder-player+3.6.14.patch

You can also view/download the patch file directly from the repository: Download Patch


If you prefer to install dependencies manually:

npm install \
  @gorhom/bottom-sheet \
  @react-native-documents/picker \
  react-native-create-thumbnail \
  react-native-fast-image \
  react-native-fs \
  react-native-gesture-handler \
  react-native-linear-gradient \
  react-native-nitro-modules \
  react-native-nitro-sound \
  react-native-permissions \
  react-native-reanimated \
  react-native-safe-area-context \
  react-native-size-matters \
  react-native-video \
  react-native-worklets \
  react-native-audio-recorder-player

Then run:

cd ios && pod install

3. Permissions setup

Android

Add these permissions to your android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission
  android:name="android.permission.WRITE_EXTERNAL_STORAGE"
  android:maxSdkVersion="32" />
  • RECORD_AUDIO is required for the voice-over feature. The SDK requests it at runtime when the user opens the recorder.
  • WRITE_EXTERNAL_STORAGE is only needed to save the exported video to the public Downloads folder on API 32 and below. On API 33+ the SDK writes there without it, so the permission is capped with android:maxSdkVersion="32" — declaring it unbounded will be flagged by Play Console and by lint.

Note: you do not need READ_EXTERNAL_STORAGE. Videos and background music are picked through the Storage Access Framework (@react-native-documents/picker), which grants per-file access without a storage permission.

iOS

Add this usage description to your ios/YourProjectName/Info.plist:

<key>NSMicrophoneUsageDescription</key>
<string>We need access to the microphone to record audio for your videos.</string>

That is the only key the SDK itself requires — the exported video is written to the app's own Documents/Downloads directory, so no Photos permission is needed to save it.

If your app picks source videos from the photo library (the SDK does not; it only receives a URI you pass in), add the relevant key for that yourself:

<key>NSPhotoLibraryUsageDescription</key>
<string>We need access to your photo library to select videos</string>

4. iOS setup (CocoaPods)

cd ios
pod install

5. Wrap your app with GestureHandlerRootView

This step is mandatory.

import { GestureHandlerRootView } from 'react-native-gesture-handler';

export default function App() {
  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      {/* Your app root */}
    </GestureHandlerRootView>
  );
}

6. Enable react-native-worklets Babel plugin

Update your babel.config.js:

module.exports = {
  presets: ['module:@react-native/babel-preset'],
  plugins: ['react-native-worklets/plugin'],
};

Restart Metro after updating Babel config:

npx react-native start --reset-cache

Usage

Imports

import {
  openVideoEditor,
  VideoEditorHost,
} from '@zlucksolutions/react-native-video-editor';

Opening the Video Editor

const result = await openVideoEditor({
  source: videoUri,
  editTrim: true,
  editCrop: true,
  editBGM: true,
  editTextOverlay: true,
  editVoiceOver: true,
});

Options

| Option | Type | Default | Description | | ------------------------- | ------------------------------- | ----------- | -------------------------------------- | | source | string | required | URI of the video to edit | | editTrim | boolean | false | Show the trim tool | | editCrop | boolean | false | Show the crop / aspect-ratio tool | | editBGM | boolean | false | Show the background-music tool | | editTextOverlay | boolean | false | Show the text-overlay tool | | editVoiceOver | boolean | false | Show the voice-over recorder | | fontFamily | string | system font | Font used for text overlays | | isVisionCamera | boolean | false | Source was recorded with Vision Camera | | isGesture | boolean | false | Device uses gesture navigation | | preserveSessionOnExport | boolean | false | Keep the editor open after export | | onExportNext | (exportedUri: string) => void | none | Receives the exported URI | | disableResetOnUnmount | boolean | false | Keep the session when editor unmounts |

source accepts a file:// path, an Android content:// URI, or a remote http(s) URL.

fontFamily takes a font filename without its extension - see Custom Font Support.

isVisionCamera - set this to true when source came from react-native-vision-camera. Those recordings carry orientation metadata that must be corrected during export; without this flag the exported video can come out rotated.

isGesture - set this to true on devices using gesture navigation so the bottom sheets leave room for the gesture bar instead of being clipped by it.

preserveSessionOnExport, onExportNext and disableResetOnUnmount change how you receive the exported video - see Export modes.

Result

{
  success: boolean;
  exportedUri?: string;
  error?: string;
}

Export modes

The editor exports in one of two ways, and this changes how you get the result back.

Default — the promise resolves

By default, the user taps Next, the editor closes, and the promise returned by openVideoEditor resolves with the exported URI:

const result = await openVideoEditor({ source: videoUri, editTrim: true });
// result.exportedUri

The Save action is separate: it writes the video into the device's Downloads folder and leaves the editor open. It does not resolve the promise.

Keep the editor open — preserveSessionOnExport

If you want to hand the exported video to your own screen (an upload flow, a preview, a caption step) without tearing the editor down, pass both preserveSessionOnExport and onExportNext:

openVideoEditor({
  source: videoUri,
  editTrim: true,
  preserveSessionOnExport: true,
  disableResetOnUnmount: true,
  onExportNext: (exportedUri) => {
    // Editor stays mounted with all edits intact.
    navigation.navigate('Upload', { uri: exportedUri });
  },
});

Important: in this mode onExportNext is called instead of closing the editor, so the openVideoEditor promise never resolves. Do not await it — take the result from onExportNext. Add disableResetOnUnmount: true if the user should be able to come back and find their edits still there.


Custom Font Support

To use custom fonts for text overlays, follow the steps below.

Step 1: Download the Font

Visit Google Fonts, choose your desired font, and download the zip file.

Step 2: Add Fonts to Your Project

Create a fonts folder in your project (recommended path: src/assets/fonts/) and place your .ttf files inside it.

Step 3: Add Config File

Create a react-native.config.js file at the root of your project and add:

module.exports = {
  project: {
    ios: {},
    android: {},
  },
  assets: ['./src/assets/fonts'], // adjust path if needed
};

Step 4: Link the Fonts

Run the following command at the root of your project:

npx react-native-asset

This will automatically copy the fonts into the correct native folders for both iOS and Android.

Step 5: Use the Font

Pass the font filename (without extension) as the fontFamily prop:

openVideoEditor({
  source: videoUri,
  fontFamily: 'LobsterRegular', // filename without .ttf
});

Minimal Example

import { View, Button, Alert } from 'react-native';
import {
  openVideoEditor,
  VideoEditorHost,
} from '@zlucksolutions/react-native-video-editor';

export default function Example() {
  const openEditor = async () => {
    const result = await openVideoEditor({
      source: 'file:///path/to/video.mp4',
      editTrim: true,
      editCrop: true,
      editBGM: true,
      editTextOverlay: true,
      editVoiceOver: true,
    });

    if (result.success && result.exportedUri) {
      Alert.alert('Video exported', result.exportedUri);
    } else {
      Alert.alert('Editor failed', result.error ?? 'Unknown error');
    }
  };

  return (
    <View style={{ flex: 1 }}>
      <Button title="Open Video Editor" onPress={openEditor} />

      {/* REQUIRED: mount editor host once */}
      <VideoEditorHost />
    </View>
  );
}

VideoEditorHost (Required)

VideoEditorHost must be rendered once in your app (preferably near the root). It is responsible for rendering the native editor UI and managing its lifecycle.

<VideoEditorHost />

openVideoEditor works by signalling this host, so calling it without a mounted VideoEditorHost does nothing and the promise never resolves.


VideoEditorSDK (Advanced)

Most apps should use openVideoEditor + VideoEditorHost. If you would rather render the editor yourself - as its own screen or route, instead of an imperative call - mount VideoEditorSDK directly. It takes every option from the table above, plus a required onCloseEditor callback that replaces the promise:

import { VideoEditorSDK } from '@zlucksolutions/react-native-video-editor';

export default function EditorScreen({ route, navigation }) {
  return (
    <VideoEditorSDK
      source={route.params.videoUri}
      editTrim
      editCrop
      editBGM
      editTextOverlay
      editVoiceOver
      onCloseEditor={({ success, exportedUri, error }) => {
        if (success && exportedUri) {
          navigation.navigate('Preview', { uri: exportedUri });
        } else {
          navigation.goBack();
        }
      }}
    />
  );
}

When you use VideoEditorSDK directly you do not need VideoEditorHost, and you should not call openVideoEditor - pick one approach or the other.


Platform Support

  • iOS: ✅ Fully supported
  • Android: ✅ Fully supported

Example App

A fully working example app is available in the example directory.

cd example
yarn install
cd ios && pod install
yarn ios

Contributing

  • Development workflow: CONTRIBUTING.md
  • Code of conduct: CODE_OF_CONDUCT.md

License

MIT


Built with create-react-native-library