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

react-native-screen-recorder-pro

v0.1.0

Published

React Native screen recorder package with Android WebM/MP4 and iOS ReplayKit MP4 support.

Readme

react-native-screen-recorder-pro

React Native native screen recorder package by aztrix-codes.

This package provides a native screen recorder for Android and iOS with chunked recording support. It is designed for assessment, proctoring, training, support-session, and long-running screen capture flows where recordings need to be uploaded in parts instead of waiting for one large final file.

Features

  • Android MP4 recording using MediaRecorder.OutputFormat.MPEG_4, H.264 video, and AAC audio.
  • Android WebM recording using MediaRecorder.OutputFormat.WEBM, VP8 video, and Opus audio.
  • iOS MP4 recording using ReplayKit and AVAssetWriter.
  • Chunked recording with configurable chunk duration.
  • Native event listener for completed chunks.
  • Recoverable chunk storage for supported recorders.
  • Direct compatibility with native module names ScreenRecorderNative and WebmScreenRecorderNative.
  • TypeScript definitions included.
  • React Native autolinking support for Android and iOS.

Supported Platforms And Formats

| Platform | Default format | Supported formats | Native module | | --- | --- | --- | --- | | Android | mp4 | mp4, webm | ScreenRecorderNative, WebmScreenRecorderNative | | iOS | mp4 | mp4 | ScreenRecorderNative |

Android defaults to MP4 for broad upload/playback compatibility. WebM remains available on Android by explicitly passing format: "webm". iOS records MP4 because ReplayKit does not provide WebM output directly.

This package does not transcode between formats. If your backend requires WebM from iOS, upload the iOS MP4 as-is and transcode server-side.

Installation

npm install react-native-screen-recorder-pro

For iOS, install pods after adding the package:

cd ios
pod install

Then rebuild the app:

npx react-native run-android
npx react-native run-ios

This is a native module. It will not work in Expo Go unless you create a custom development build that includes the native code.

Android Setup

The package ships its own Android manifest entries for the foreground services:

  • com.aztrixcodes.screenrecorderpro.WebmScreenRecorderService
  • com.aztrixcodes.screenrecorderpro.ScreenRecorderService

The package also declares these permissions:

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />

Your app is still responsible for runtime permission handling where required. At minimum, request microphone permission before starting a recording if you need audio.

On Android 13 and newer, request POST_NOTIFICATIONS if your app needs foreground service notifications to be visible to the user.

When recording starts, Android shows the system MediaProjection consent prompt. The user must approve this prompt before capture can begin.

iOS Setup

iOS uses ReplayKit. It records screen content into MP4 chunks.

Notes:

  • Test on a real iOS device. Simulator support is limited by Apple APIs.
  • iOS does not output WebM.
  • The native module name is ScreenRecorderNative.
  • ReplayKit may pause or interrupt capture when the app becomes inactive, protected content appears, the device locks, or iOS rejects capture.

Quick Start

import {
  EVENTS,
  addRecorderListener,
  startRecording,
  stopRecording,
} from "react-native-screen-recorder-pro";

const subscription = addRecorderListener(EVENTS.CHUNK_READY, chunk => {
  console.log("Chunk ready:", chunk.path);
});

await startRecording({
  chunkDurationMs: 10000,
  recordingSessionId: "session-001",
});

await stopRecording();
subscription.remove();

On Android and iOS, this starts MP4 recording by default.

The wrapper remembers the active format after startRecording, so stopRecording() can be called without passing the format for the same session. You can still pass the format explicitly when you prefer:

await stopRecording({ format: "mp4" });

Use Case: Android MP4 Recording

import {
  EVENTS,
  addRecorderListener,
  startRecording,
  stopRecording,
} from "react-native-screen-recorder-pro";

const subscription = addRecorderListener(
  EVENTS.CHUNK_READY,
  async chunk => {
    await uploadChunk({
      uri: chunk.path,
      durationMs: chunk.durationMs,
    });
  },
  { format: "mp4" }
);

await startRecording({
  format: "mp4",
  chunkDurationMs: 10000,
});

await stopRecording({ format: "mp4" });
subscription.remove();

Android MP4 is the default. Use it when your upload or playback pipeline expects MP4/H.264. The Android MP4 event payload contains path and durationMs.

Use Case: Android WebM Recording

import {
  EVENTS,
  addRecorderListener,
  startRecording,
  stopRecording,
} from "react-native-screen-recorder-pro";

const subscription = addRecorderListener(
  EVENTS.CHUNK_READY,
  async chunk => {
    await uploadChunk({
      uri: chunk.localPath || chunk.path,
      fileName: chunk.uploadFileName,
      sequence: chunk.sequence,
      isFinal: chunk.isFinal,
      durationMs: chunk.durationMs,
    });
  },
  { format: "webm" }
);

await startRecording({
  format: "webm",
  chunkDurationMs: 10000,
  recordingSessionId: "assessment-123",
  uploadNameStrategy: "native_path",
  nextSequenceNumber: 1,
});

await stopRecording({ format: "webm" });
subscription.remove();

Android WebM uses MediaRecorder.OutputFormat.WEBM, VP8 video, and Opus audio. It includes richer recovery metadata with sequence numbers and upload file names.

Use WebM on Android when you want smaller chunk files or when your backend/player specifically supports WebM.

Use Case: iOS MP4 Recording

import {
  EVENTS,
  addRecorderListener,
  startRecording,
  stopRecording,
} from "react-native-screen-recorder-pro";

const subscription = addRecorderListener(EVENTS.CHUNK_READY, chunk => {
  console.log("iOS MP4 chunk:", chunk.path);
});

await startRecording({
  format: "mp4",
  chunkDurationMs: 10000,
  recordingSessionId: "ios-session-001",
});

await stopRecording({ format: "mp4" });
subscription.remove();

iOS only supports mp4. Passing webm on iOS throws an unsupported format error.

Use Case: Resume Failed Uploads With Recovery

For WebM Android and iOS MP4 flows, completed chunks are persisted as recoverable records. This helps if the app closes, the network fails, or upload acknowledgement is delayed.

import {
  acknowledgeRecoverableChunk,
  getRecoverableChunks,
} from "react-native-screen-recorder-pro";

const sessionId = "assessment-123";
const chunks = await getRecoverableChunks(sessionId, { format: "webm" });

for (const chunk of chunks) {
  await uploadChunk({
    uri: chunk.localPath || chunk.path,
    fileName: chunk.uploadFileName,
    sequence: chunk.sequence,
  });

  await acknowledgeRecoverableChunk(sessionId, chunk.recoveryId, {
    format: "webm",
  });
}

Call acknowledgeRecoverableChunk only after your backend confirms the chunk is safely stored.

To clear all recovery records for a session:

import { clearRecoveryState } from "react-native-screen-recorder-pro";

await clearRecoveryState("assessment-123", { format: "webm" });

Use Case: React Hook Pattern

import { useEffect, useRef } from "react";
import {
  EVENTS,
  addRecorderListener,
  startRecording,
  stopRecording,
} from "react-native-screen-recorder-pro";

export function useScreenRecorder(sessionId) {
  const subscriptionRef = useRef(null);

  useEffect(() => {
    subscriptionRef.current = addRecorderListener(EVENTS.CHUNK_READY, chunk => {
      console.log("chunk ready", chunk);
    });

    return () => {
      subscriptionRef.current?.remove();
      subscriptionRef.current = null;
    };
  }, []);

  async function start() {
    await startRecording({
      chunkDurationMs: 10000,
      recordingSessionId: sessionId,
    });
  }

  async function stop() {
    await stopRecording();
  }

  return { start, stop };
}

Always remove event subscriptions when the screen unmounts.

API Reference

startRecording(options)

Starts native screen recording.

startRecording(options?: StartRecordingOptions | number): Promise<unknown>

Options:

| Field | Type | Default | Description | | --- | --- | --- | --- | | format | "webm" or "mp4" | Android: mp4, iOS: mp4 | Desired output format. Pass webm explicitly for Android WebM. | | chunkDurationMs | number | 10000 | Target chunk duration in milliseconds. | | recordingSessionId | string | "" | Stable ID used for recovery and upload grouping. | | uploadNameStrategy | string | native_path | Controls generated upload file names where supported. | | nextSequenceNumber | number | 1 | First sequence number for generated chunks. |

You can also pass a number directly:

await startRecording(10000);

That is treated as chunkDurationMs.

stopRecording(options)

Stops native screen recording.

stopRecording(options?: { format?: "webm" | "mp4" }): Promise<unknown>

The final chunk may be emitted through onChunkReady or returned in the native stop result depending on platform and format.

addRecorderListener(eventName, listener, options)

Subscribes to native recorder events.

addRecorderListener(
  eventName: ScreenRecorderEventName,
  listener: (event: unknown) => void,
  options?: { format?: "webm" | "mp4" }
): EmitterSubscription

Remove the listener when done:

const subscription = addRecorderListener(EVENTS.CHUNK_READY, onChunk);
subscription.remove();

getRecoverableChunks(recordingSessionId, options)

Returns persisted chunk records for a session.

getRecoverableChunks(
  recordingSessionId?: string,
  options?: { format?: "webm" | "mp4" }
): Promise<RecoverableChunk[]>

If the selected native module does not support recovery, the wrapper returns an empty array.

acknowledgeRecoverableChunk(recordingSessionId, recoveryId, options)

Removes one persisted recovery record after successful upload.

acknowledgeRecoverableChunk(
  recordingSessionId?: string,
  recoveryId?: string,
  options?: { format?: "webm" | "mp4" }
): Promise<boolean>

clearRecoveryState(recordingSessionId, options)

Clears all persisted recovery records for a session.

clearRecoveryState(
  recordingSessionId?: string,
  options?: { format?: "webm" | "mp4" }
): Promise<boolean>

setAssessmentPortalActive(isActive, options)

Sets an iOS native flag used by the current native implementation for portal-style recording flows.

setAssessmentPortalActive(
  isActive: boolean,
  options?: { format?: "webm" | "mp4" }
): void

On Android or unsupported modules this is a no-op.

getSupportedFormats(platform)

Returns supported formats for a platform.

getSupportedFormats("android"); // ["mp4", "webm"]
getSupportedFormats("ios"); // ["mp4"]

getDefaultFormat(platform)

Returns the default format for a platform.

getDefaultFormat("android"); // "mp4"
getDefaultFormat("ios"); // "mp4"

getNativeModule(format)

Returns the underlying native module for advanced use.

const module = getNativeModule("webm");

Events

Import event names from EVENTS:

import { EVENTS } from "react-native-screen-recorder-pro";

| Constant | Native event | Description | | --- | --- | --- | | EVENTS.CHUNK_READY | onChunkReady | A chunk has been finalized and is ready for upload. | | EVENTS.RECORDING_INTERRUPTED | onRecordingInterrupted | iOS capture was interrupted. | | EVENTS.RECORDING_RESUME_STARTED | onRecordingResumeStarted | iOS resume attempt started. | | EVENTS.RECORDING_RESUMED | onRecordingResumed | iOS capture resumed. | | EVENTS.RECORDING_RESUME_FAILED | onRecordingResumeFailed | iOS resume attempt failed. |

Typical chunk payload:

type RecoverableChunk = {
  recoveryId?: string;
  recordingSessionId?: string;
  localPath?: string;
  path?: string;
  uploadFileName?: string;
  sequence?: number;
  durationMs?: number;
  createdAt?: number;
  isFinal?: boolean;
  requiresWebm?: boolean;
};

Notes:

  • Use localPath || path as the upload URI.
  • uploadFileName is the recommended server-side file name when provided.
  • sequence is useful for ordering chunks.
  • isFinal indicates the final emitted chunk for a recording.
  • requiresWebm can be true for iOS recovery records because the local file is MP4 even if your upload pipeline expects WebM.

Direct NativeModules Compatibility

The package intentionally preserves these native module names:

import { NativeModules } from "react-native";

NativeModules.WebmScreenRecorderNative; // Android WebM
NativeModules.ScreenRecorderNative; // Android MP4 and iOS MP4

This allows existing app code that already calls NativeModules directly to migrate later with minimal changes.

For new code, prefer the wrapper API exported from this package.

Choosing The Right Format

Use Android MP4 when:

  • You want the default behavior.
  • Your backend requires MP4/H.264.
  • Your users need broad native playback compatibility.

Use Android WebM when:

  • You explicitly pass format: "webm".
  • You want smaller chunks.
  • Your backend or player supports WebM.
  • You need recovery metadata with sequence numbers and upload file names.

Use iOS MP4 when:

  • You are recording on iOS. This is the only supported iOS output format.

Upload Flow Recommendation

Recommended production flow:

  1. Generate a stable recordingSessionId before starting.
  2. Subscribe to EVENTS.CHUNK_READY.
  3. Start recording with chunkDurationMs, recordingSessionId, and nextSequenceNumber.
  4. Upload each chunk as soon as it is emitted.
  5. Acknowledge recoverable chunks only after successful backend confirmation.
  6. On app restart, call getRecoverableChunks(recordingSessionId) and retry pending uploads.
  7. Stop recording on screen exit, assessment submit, logout, or app-level cancellation.
  8. Remove listeners on unmount.

Error Handling

Common errors:

| Error | Cause | Fix | | --- | --- | --- | | Native module is not linked | App was not rebuilt after installing | Rebuild Android/iOS app. | | Unsupported format | webm was requested on iOS or invalid format was passed | Use getSupportedFormats() before choosing format. | | Activity is null | Android recording started before an Activity was available | Start only after the screen is mounted and focused. | | User denied capture | Android MediaProjection consent was cancelled | Ask user to start recording again. | | iOS interruption | ReplayKit stopped due to system/app state | Listen for interruption/resume events and handle gracefully. |

Limitations

  • WebM is Android only.
  • iOS output is MP4 only.
  • The package does not provide video playback UI.
  • The package does not upload files by itself.
  • The package does not transcode files.
  • Native screen recording requires a rebuilt native app.
  • Browser/web React Native targets are not supported.

Publishing Checklist

Before publishing to npm:

cd react-native-screen-recorder-pro
npm pack --dry-run
npm publish

The package currently publishes as:

{
  "name": "react-native-screen-recorder-pro",
  "author": "aztrix-codes"
}

License

MIT