On‑device PNG → MP4 encoder for React‑Native & Expo
No FFmpeg • No GPL • Just the platform video encoders — AVAssetWriter (iOS) & MediaCodec (Android)
- Offline – runs entirely on the device, no upload required
- Tiny footprint – adds ≈150 kB native code, zero third-party binaries
- Expo-friendly – ships with a config-plugin; just add it to
app.json - Classic & New Architecture – works if the host app opts into TurboModule/Fabric later
Supported React‑Native versions: 0.65 → 0.73 (Expo SDK 49/50).
Older versions may compile but are not tested.
npx expo install react-native-image-sequence-encoderAdd the plugin entry to app.json / app.config.js so EAS can autolink:
That’s it — run a development build or EAS production build and the native module is ready.
Local testing: run
npx expo run:iosornpx expo run:androidafter installing the library; Expo Go will not include the native code.
npm install react-native-image-sequence-encodercd ios && pod install && cd ..Android registration (one‑time): open MainApplication.java or
MainApplication.kt and add the package:
import com.reactnativeimagesequenceencoder.ImageSequenceEncoderPackage;
@Override
protected List<ReactPackage> getPackages() {
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(new ImageSequenceEncoderPackage());
return packages;
}Storage permission (optional): only needed if you save the MP4 outside the app sandbox.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- Android 13+ -->
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>For legacy projects still on RN 0.59 or below:
react-native link react-native-image-sequence-encoderThen follow the iOS pod install and Android package registration steps
above.
import { encode } from 'react-native-image-sequence-encoder';
import * as FileSystem from 'expo-file-system';
// after you have /cache/frames/frame-00000.png …
const uri = await encode({
folder: FileSystem.cacheDirectory + 'frames/',
fps: 30,
width: 1280,
height: 720,
output: FileSystem.documentDirectory + 'chat.mp4',
});
console.log('MP4 saved at', uri);| Option | Type | Description |
|---|---|---|
folder |
string | Directory ending with /, containing sequential PNG frames |
fps |
number | Frames per second in the output file |
width |
number | Output width in pixels |
height |
number | Output height in pixels |
output |
string | Absolute path for the MP4 (overwritten if already exists) |
Returns Promise<string> – absolute file URI of the saved video.
⚠️ The module does no down‑scaling; make surewidth&heightmatch the PNG resolution or resize the frames before callingencode().
| Problem | Fix |
|---|---|
Native module not linked |
Rebuild the dev client (eas build --profile development) or run npx react-native run-android / run-ios. |
INFO_OUTPUT_FORMAT_CHANGED twice (Android) |
Stick to even dimensions (e.g. 1280×720); some encoders reject odd sizes. |
| iOS < 12 crash | The podspec targets iOS 12+. Older OS versions are not supported. |
PRs are welcome! See CONTRIBUTING.md for details.
MIT © 2025 Elliot Fleming
{ "expo": { "plugins": ["react-native-image-sequence-encoder"] } }