Skip to content
← All Case Studies
Vixit Video Compressor & Tools

Vixit Video Compressor & Tools

Integrating FFmpeg into a mobile app for video compression, format conversion, and audio extraction — with background processing that doesn't kill the UX.

AndroidKotlinFFmpegWorkManagerJetpack Compose

1. The Problem

Videos shot on modern phones are massive — a 1-minute 4K video can be 400MB+. Sharing these over WhatsApp, email, or social media often means hitting file size limits, waiting forever for uploads, or losing quality to aggressive auto-compression. Users needed a tool that gives them control: choose your output quality, format, and file size.

2. The Solution

Vixit is a complete video toolkit: compress videos with adjustable quality (reduce 400MB to 20MB), convert between formats (MP4, AVI, MKV, WebM), extract audio tracks to MP3/AAC, and trim videos with frame-accurate precision. All processing happens in the background so users can close the app and come back later.

3. Technical Deep Dive: FFmpeg Integration

The core challenge was integrating FFmpeg — a powerful but complex C library — into a Kotlin/Android app. I used FFmpegKit to bridge native code with Kotlin, then built a command builder layer on top that translates user-friendly options (like 'Medium Quality, 720p') into FFmpeg command strings (like '-c:v libx264 -crf 28 -vf scale=-2:720 -preset fast'). This abstraction layer makes it easy to add new tools without touching FFmpeg internals.

4. Background Processing

Video conversion can take minutes — users shouldn't be forced to keep the app open. I implemented WorkManager for background processing with persistent notifications showing real-time progress (percentage, estimated time remaining, file size). If the user kills the app or the phone restarts, WorkManager automatically resumes the conversion. Each conversion job is a CoroutineWorker with proper cancellation support.

5. Architecture Decisions

The app follows MVVM with a Repository pattern. The FFmpeg command layer is completely decoupled from the UI — ViewModels only know about 'ConversionJob' objects, not FFmpeg details. This made testing easier and allowed me to swap FFmpeg versions without touching any UI code. File management uses Android's MediaStore API for scoped storage compliance.

6. What I Learned

Working with native libraries (FFmpeg) taught me about JNI bridges, memory management in native code, and the importance of proper error handling when native code crashes don't give you nice stack traces. Building the progress tracking system taught me about WorkManager's constraints, retry policies, and how to handle edge cases like low storage space mid-conversion.