← Blog

Add a video editor to your React Native app (Expo included)

· 6 min read · react-nativeexpovideo-editing

Your users want to make video in your app, and "trim and post" isn't enough for them. This guide shows how to add a complete React Native video editor to your app, Expo included, with Nitrakit: install, show the editor, connect your own media picker and export an MP4. The code comes straight from the React Native guide in our docs.

The Nitrakit video editor: a preview above a multi-track timeline and a bar of editing tools

Why the editor belongs inside your app

When editing happens somewhere else, users leave. They export, switch apps, edit, and maybe come back to post. Each step is a chance to lose the post, and the moment of making something happens in someone else's product instead of yours.

The other option, building the editor yourself, means a timeline, text, captions, effects, audio and export, on iOS and Android, kept working release after release. For most app teams that is a second product, and it pulls engineers off the one you're actually building.

Nitrakit is the third option: a complete editor you add as a component, styled as your app.

What your users get

The editor your users already know how to use:

  • A preview that plays in real time. Users tap a layer to select it, then drag, pinch or use its handles to move, resize and rotate it.
  • A timeline with tools. Trim, split, speed, volume, effects, transitions, text with animations, audio, and undo.
  • Word-timed captions from your app's own speech-to-text, so you choose the provider.
  • Export to MP4 on the device, while the user keeps editing.

Editing and export run on the user's device, so there's no video server for you to run. Projects save as JSON that you own, so users can come back to a draft later or on another device.

What stays yours: where media comes from, what your pickers look like, the wording, and the look of the whole editor. More on that below.

The editor's text style presets open, with a highlighted title on the preview

Requirements

From the React Native guide:

  • React Native with the New Architecture (the default since 0.76) and react-native-nitro-modules.
  • iOS 16 or later; Android 8.0 or later (minSdkVersion 26).
  • Expo: a development build. Expo Go can't load the SDK's native code.

If you're on Expo, that last point is the only difference: you run your own development build instead of Expo Go, as you would for any library with native code.

Install the React Native video editor

During early access, the SDK comes from Nitrakit's package registry. Your invite includes an access token; keep it out of your repository and read it from the NITRAKIT_TOKEN environment variable. The full steps are on the install page.

Point the @nitrakit scope at the registry in your project's .npmrc. It's safe to commit, because the token comes from the environment:

@nitrakit:registry=https://packages.nitrakit.dev/api/packages/nitrakit/npm/
//packages.nitrakit.dev/api/packages/nitrakit/npm/:_authToken=${NITRAKIT_TOKEN}
npm install @nitrakit/react-native react-native-nitro-modules
  • iOS: the native SDK ships inside the package. Run pod install. If users pick from their photo library, add NSPhotoLibraryUsageDescription to your Info.plist.
  • Android: Gradle downloads the native SDK from the registry too. Give it the token in your user-level Gradle settings, or set NITRAKIT_TOKEN in the environment (for example on CI):
nitrakitToken=<your token>

Raise minSdkVersion to 26 if it's lower.

Add it to an Expo app

On Expo, add the config plugin to app.json instead of editing native files. It sets the Android version for you:

{ "expo": { "plugins": ["@nitrakit/react-native"] } }

Then run npx expo prebuild and build your development build as usual. Your team keeps the Expo workflow it already has.

Create a project

An editor holds one project and its undo history. Create it with your output size and frame rate, then add the user's first video:

import { createEditor, importFile } from '@nitrakit/react-native'

const editor = createEditor(1080, 1920, 30)

const media = editor.addMedia(assetId, importFile(pickedUri, 'clip.mp4'), 'clip.mp4')
const track = editor.addTrack('visual', true)
editor.insertMedia(track, media.source, 0, 0, media.durationUs)

assetId is your app's id for the file, for example its key in your storage. Projects refer to media only by these ids, which is what lets a project sync through your backend and reopen on another device. See Projects and media for signed URLs and the media resolver.

Show the editor

Two components make up the editor. NitrakitPreview plays the project; NitrakitEditor has the timeline, tools and panels. Give both the same editor and they stay in sync:

import { NitrakitEditor, NitrakitPreview } from '@nitrakit/react-native'

export function EditorScreen({ editor }: { editor: Editor }) {
  return (
    <View style={{ flex: 1, backgroundColor: '#000' }}>
      <NitrakitPreview editor={editor} style={{ flex: 1 }} />
      <NitrakitEditor editor={editor} style={{ height: 400 }} onRequest={onRequest} />
    </View>
  )
}

Create the editor once per project (in a useMemo or your state store), not on every render.

Because they're two components, the layout is yours. Show both, only the timeline, or only the preview with controls you build; the layouts page covers each.

Connect your own media picker with onRequest

The editor never opens the photo library or a file browser itself. When the user taps Add media, picks a font or a colour, the editor asks your app through onRequest. So the picker is your screen, in your design, and media can come from the camera roll, your own content library or your backend.

Return the answer, or a promise of it. Return null if the user backed out, or nothing to let the SDK show its built-in picker:

async function onRequest(request: EditorRequest) {
  switch (request.kind) {
    case 'addMedia':
    case 'addOverlay':
    case 'addAudio':
    case 'addSticker': {
      const picked = await pickFromLibrary() // your picker
      if (!picked) return null
      const path = importFile(picked.uri, picked.fileName)
      const media = editor.addMedia(startUpload(path), path, picked.fileName) // your storage's id
      return { source: media.source }
    }
  }
  // anything else: the built-in picker
}

The built-in pickers cover fonts, colours, text, text styles and filters, so you can start with media only and replace the rest when your designers get to it. Every request and its answer is on the Pickers page.

Export an MP4

Export renders the project to an MP4 in the background, while the user keeps editing:

import { filesDir } from '@nitrakit/react-native'

const path = `${filesDir()}/export-${Date.now()}.mp4`
try {
  await editor.exportVideo(path, editor.exportSettings(1080), (f) => setProgress(f))
  // the file at `path` is ready to save, share or upload
} catch (e) {
  // failed, or cancelled with editor.cancelExport()
}

What happens to the file next is up to your app: save it to the photo library, share it, or upload it to your backend. Settings, progress and cancelling are on the Export page.

Make it look like your app

Product and design teams push back on a screen that looks borrowed. The editor takes your theme as a prop:

<NitrakitEditor
  editor={editor}
  theme={{
    background: '#101418',
    bar: '#0b0e11',
    accent: '#2ee6a6',
    font: 'Brand Sans',
    clips: { video: '#3355ff', audio: '#18a058' },
  }}
/>

Beyond colours and fonts, you can remove tools you don't offer, add your own, swap the icons, and rename every label in your users' languages. It's all set at runtime, so it can follow your app's dark mode, feature flags and language. See Customisation.

Curious what it adds to your app's download? The App size page lists it per platform, including React Native.

Try it free, license it for release

You can build and test everything without a license key. Before you release your app, you get a license key and install it once when the app starts, outside any component:

import { setLicense } from '@nitrakit/react-native'

const status = setLicense('nk2.…')
if (status.problems.length) console.warn('Nitrakit:', status.problems)

The key names the apps it covers, so it can live in your code. Details are on the License key page.

Get early access

Nitrakit is in early access. Request a registry token, follow the React Native guide, and you'll have the editor running in your own development build. Want to see it first? The web demo shows the editor in your browser.

Questions while you integrate? Ask us on Discord.

Get early access