ffmpeg for Android and iOS apps. On a server, not the phone.
Your Android, iOS, React Native or Flutter app uploads the video, your backend sends one request, and Videxo compresses, cuts and makes thumbnails on a server instead of the phone.
curl "$VIDEXO_API_URL/v1/transcode" \
-H "Authorization: Bearer $VIDEXO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": "https://videxo.io/samples/talk.mp4",
"preset": "web-720p",
"filename": "talk-720p.mp4",
"metadata": {
"order": "1234"
}
}' import { Videxo } from '@videxo/sdk';
const videxo = new Videxo({ apiKey: process.env.VIDEXO_API_KEY, baseUrl: process.env.VIDEXO_API_URL });
const job = await videxo.transcode({
"input": "https://videxo.io/samples/talk.mp4",
"preset": "web-720p",
"filename": "talk-720p.mp4",
"metadata": {
"order": "1234"
}
});
const done = await videxo.jobs.wait(job.id); Install with npm i @videxo/sdk, or send the same request with curl or JavaScript. About the SDK
const response = await fetch(`${process.env.VIDEXO_API_URL}/v1/transcode`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.VIDEXO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"input": "https://videxo.io/samples/talk.mp4",
"preset": "web-720p",
"filename": "talk-720p.mp4",
"metadata": {
"order": "1234"
}
}),
});
const job = await response.json(); How it fits
Upload, process, notify. Your backend stays in charge.
- 1
Reserve an upload
Your backend calls POST /v1/uploads with its API key, file size and content type. It passes the one-time upload URL to the app.
- 2
Upload the recording
The app PUTs the exact file bytes to that signed URL, up to 100 MB and your plan’s input limit. Your API key stays on your backend.
- 3
POST /v1/transcode with the input_url
After upload completes, your backend sends a JSON request with its private input_url as the input, a preset or options, and your webhook URL. The API returns the job, queued.
- 4
Read the private input
The job reads the completed upload. Your account’s jobs can use it for 24 hours.
- 5
Run ffmpeg, store outputs
The job runs; its outputs come with size, SHA-256, retention and signed download links.
- 6
Webhook: job.succeeded, signed
Your backend verifies the signature and reads the outputs, signed download URLs and usage.
- 7
Get a fresh download link
If needed, read the job again or use its output-alias endpoint. Links last up to one hour, bounded by file retention.
- 8
Send the link to the app
A push or the next poll of your own API tells the app the job is done. The app downloads the processed file through its signed URL.
Code for both ends: an iOS app in Swift and an Android app in Kotlin, each talking to a backend from the integration guides.
Typical jobs
What video apps send. Each a JSON request that runs today.
Compress and transcode
Phone video is large. Shrink it after upload, before you store it and send it to other users.
POST /v1/transcode {"input":"https://example.com/talk.mp4","filename":"talk-small.mp4","video":{"codec":"h264","crf":28,"encoder_preset":"veryfast"},"audio":{"codec":"aac","bitrate":"128k"}}Thumbnails
A poster for every video in a feed or a gallery, ready before anyone presses play.
POST /v1/thumbnails {"input":"https://example.com/talk.mp4","filename":"poster.jpg","resize":{"width":640}}Vertical 9:16
Landscape recordings cut to 9:16 for stories and full-screen feeds.
POST /v1/transcode {"input":"https://example.com/talk.mp4","preset":"social-vertical","filename":"talk-vertical.mp4"}GIF previews
A few seconds that play in a chat or a notification, where video does not.
POST /v1/gif {"input":"https://example.com/talk.mp4","filename":"preview.gif","trim":{"start":5,"duration":4},"fps":12,"resize":{"width":480}}Extract and convert audio
The sound alone, for voice notes, transcription or a podcast feed.
POST /v1/audio {"input":"https://example.com/talk.mp4","filename":"talk.mp3","audio":{"bitrate":"192k"}}Rotate and flip
Sideways recordings turned upright and selfies un-mirrored.
POST /v1/transcode {"input":"https://example.com/talk.mp4","filename":"talk-rotated.mp4","rotate":90}
Why not on the device
Phones are for recording. Encoding belongs on a server.
Battery and heat
A long encode keeps the processor busy and warms the phone in the user’s hand. On a server it costs the user nothing.
App size
A full ffmpeg build adds tens of megabytes to your app. FFmpegKit, the usual way to bundle it on iOS and Android, has been officially retired, and its repository was archived on July 2, 2026.
Time
The user waits, or the system pauses your app in the background before a long job ends. A server job keeps going when the app closes.
One pipeline
The same request for iOS, Android and the web, changed on your backend without an app release.
FFmpegKit's status as its project page states it on 2026-11-05: FFmpegKit on GitHub
Soon for apps. Planned, not available yet.
What works today is the flow above. These add playback options for the phone.
Resumable uploads Soon
Uploads that pick up where they stopped after a lost connection, and files past 100 MB.
Adaptive streaming (HLS) and a player Soon
Playback that adapts to the connection, with an embeddable player.
Signed playback Soon
Playback links that only work for the viewers you sign them for.
Questions, answered.
FFmpegKit is retired. What now for ffmpeg on Android and iOS?
Its project page says FFmpegKit has been officially retired and that development continues with FFmpegKitNext, maintained by its original author; the repository was archived on July 2, 2026. Moving processing to a server avoids bundling ffmpeg at all: the app uploads the file, your backend sends one request, and the processed video comes back as a download link, the same for Android, iOS and the web.
Does it work with React Native, Flutter, Expo, Swift and Kotlin?
Yes. The app only uploads a file to a one-time URL and talks to your own backend, so any HTTP client works: fetch in React Native and Expo, the http package in Flutter, URLSession in Swift, OkHttp or Ktor in Kotlin. The docs have complete iOS (Swift) and Android (Kotlin) example apps.
Does the app call Videxo directly?
Keep your API key on your backend. It reserves an upload and gives the app its one-time URL; the app sends bytes directly, up to 100 MB and your plan’s input limit. Create jobs from your backend.
Which files from phones can it read?
MP4 and MOV from iPhone and Android cameras, in H.264 or HEVC, as they are. Inputs can be completed private uploads up to 100 MB and your plan’s input limit, or public http or https URLs to your storage.
How does the app get the processed video?
The webhook gives your backend signed download links for each output. Pass a link to the app to download the file. Playback over HLS Soon is planned.
Run your first job. Free, no card.
Building a video app? Write to hello@videxo.io.