React Native
By the end of this page your app shows the editor on a video, lets users add their own media through your picker, and exports the result.
Requirements
- 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 (
minSdkVersion26).
Install
The package is @nitrakit/react-native; it includes the native code for iOS and Android.
- iOS: run
pod install. If users pick from their photo library, addNSPhotoLibraryUsageDescriptionto yourInfo.plist. - Android: raise
minSdkVersionto 26 if it's lower.
1. Install your license key Stable
The key unlocks full-length, watermark-free exports for your app. Install it once when your app starts, outside any component. Without a key everything still works, so you can skip this while trying the SDK.
import { setLicense } from '@nitrakit/react-native'
const status = setLicense('nk1.…')
if (status.problems.length) console.warn('Nitrakit:', status.problems)
See License key.
2. Create a project Stable
An editor holds one project and its undo history. Create it with your output size and frame rate, then add media: adding a file makes it a source; placing the source on a track makes it a clip the user sees in the timeline.
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)
assetIdis your app's id for the file, for example its key in your storage: the project refers to media only by these ids.importFileturns what a picker gives you (content://,file://) into a path the SDK can read. The SDK keeps its own copy, so editing starts right away.- Times are microseconds.
3. Tell the SDK where media lives Stable
When a project is opened on a device that doesn't have its media yet, the SDK asks your app where each media id lives. Return a URL (it can be signed) and the SDK downloads it, showing the progress on the clips:
import { setMediaResolver } from '@nitrakit/react-native'
setMediaResolver(async (id) => (await api.signedUrl(id)).url) // or a local path
Set it once, at start-up. Skip it if your projects never leave the device. See Projects and media.
4. Show the editor Stable
Two components make up the editor: NitrakitPreview plays the project and lets the user move
and resize layers; NitrakitEditor has the timeline, tools and panels. Give both the same
editor; they stay in sync with each other and with your code.
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 (for example in a useMemo or your state store), not on
every render.
5. Connect your pickers Stable
The editor never opens the photo library or a file browser itself. When the user taps
Add media, picks a font or a colour, it asks your app through onRequest, so these
screens look like the rest of your app and media can come from wherever you keep it.
Return the answer, or a promise of it. Return null if the user backed out, or undefined
(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; adding media always needs yours. See Your pickers for every request and its answer.
6. Save the project Stable
Projects save as JSON, with media referred to by your ids. Store it on the device or sync it to your backend, and reopen it anywhere:
import { openEditor } from '@nitrakit/react-native'
const json = editor.toJson()
const reopened = openEditor(json)
reopened.loadMedia() // from the device, else through your resolver
editor.setListener(() => scheduleSave(editor.toJson())) // after every change
While your app uploads a file, show the progress on its clips with
editor.setMediaProgress(id, fraction).
7. Export Stable
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()
}
See Export.
Playback
Control playback from your own buttons through a ref:
const preview = useRef<PreviewHandle>(null)
<NitrakitPreview ref={preview} editor={editor} onPosition={(us) => setTime(us)} />
preview.current?.play()
preview.current?.seek(2_000_000)