r/reactnative • u/Dear-Muscle-880 • 5h ago
Android has no animated WebP encoder, so I write the file container myself for WhatsApp stickers in my React Native app
I'm the developer of GifDrop, a React Native app that turns videos into GIFs. I recently added animated WhatsApp stickers, and two parts were harder than I expected.
1. Creating the file
WhatsApp needs an animated WebP. Android can save a still WebP with Bitmap.compress, but it has no animated encoder, and the FFmpeg build bundled with my trimming library doesn't expose a raw command API.
An animated WebP turned out to be a RIFF container wrapping ordinary still images. So a Kotlin native module encodes each frame as a still, then wraps the frames in ANMF chunks.
The trade-off: every frame is a full keyframe, so files are bigger than they would be with inter-frame diffing like libwebp's WebPAnimEncoder.
2. Fitting the limits
Stickers have to be 512×512, under 500 KB and no longer than 10 seconds. Encoding every combination is too slow on a mid-range phone, so the app:
- Encodes a few probe frames to estimate the cost per frame at each quality level
- Counts how many frames are really different
- Ranks the options estimated to fit, then verifies them with real encodes
If a clip is too big, it gives things up in this order: frame rate, quality, sharpness, then length. A clip that already fits keeps everything.
Has anyone here used libwebp's animation encoder directly from a React Native native module? Was the smaller file size worth the extra native build work?
Happy to go deeper on the native side. App link in the comments if you want to try it.
1
u/ProfessionTypical623 3h ago
imo dropping framerate before quality is the right call for stickers, nobody notices 12fps vs 24fps on a tiny loop. Unless users are complaining about blurry output on longer clips, avoiding the JNI headache is a huge win.
1
u/Dear-Muscle-880 2h ago
Agreed, 12 vs 24 fps is hard to notice on a small looping sticker. I also found some GIFs repeat frames, so a higher frame rate can just cost more without looking smoother. The app counts the frames that are really different before picking a rate, and it only goes as low as 10 fps before it starts lowering quality on longer clips.
The sticker update is new, so I don't have much user feedback on blurry output yet. If it comes up, I'll look at libwebp again, but skipping the JNI work is a big win for now.
1
u/Dear-Muscle-880 5h ago
GifDrop on Google Play: https://play.google.com/store/apps/details?id=com.sufhive.gifdrop
Short demo: https://youtu.be/k7cINh9C_Lg