We implement end-to-end video sending in mobile chat apps — from file selection to inline player. Raw camera footage cannot be uploaded directly: without transcoding and chunked upload, users wait minutes, and on weak connections they get timeouts. Our team has over a decade of experience in iOS and Android development, with more than 50 video integration projects for chat apps. We guarantee stability and performance.
Why video upload requires transcoding
Video from an iPhone 14 Pro at 4K/60fps weighs ~400 MB per minute. Even a 15-second clip is 100 MB. Uploading that directly is unacceptable in both time and data usage.
On iOS, video from PHPickerViewController or UIImagePickerController arrives as MOV (HEVC or H.264). It must be transcoded before upload. The standard path uses AVAssetExportSession with preset AVAssetExportPresetMediumQuality (720p, ~2 Mbit/s) or AVAssetExportPreset1280x720. Export is asynchronous, taking 2–30 seconds depending on clip length and device model. On iPhone SE 2nd gen, transcoding a 30-second video to 720p takes about 8 seconds.
On Android, the situation is more complex: MediaMuxer + MediaCodec give maximum control but require heavy coding. For most projects we use FFmpegKit (a mobile FFmpeg fork) — it lets you set bitrate, resolution, and codec with a single command: -vcodec libx264 -crf 28 -vf scale=720:-2. The downside is adding ~15 MB to the APK.
How to ensure resumable upload
Video cannot be uploaded in a single request without resume support. If the connection drops, all progress is lost.
The proper approach is multipart upload on the server side (AWS S3 Multipart Upload, Cloudflare R2, or custom chunked upload). The file is divided into 5–10 MB parts, each uploaded as a separate request. On interruption, we resume from the last successful chunk.
On iOS, we implement this with URLSession using Background Configuration (URLSessionConfiguration.background(withIdentifier:)): upload continues even after the app is backgrounded. On Android, we use WorkManager with an UploadWorker that receives setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) for background operation.
In React Native, we use react-native-background-upload or a custom native module. Standard fetch with FormData does not support background upload on iOS.
How to reduce user wait time
We generate a preview frame before upload: on iOS via AVAssetImageGenerator with generateCGImagesAsynchronously, on Android via MediaMetadataRetriever.getFrameAtTime(). The frame is compressed to JPEG 480p and uploaded separately — it appears instantly in the chat while the video is still uploading.
For playback in chat, we don't embed a full player in the cell — that kills scroll performance. Instead, we show a thumbnail with a play button; tapping opens AVPlayerViewController (iOS) or ExoPlayer (Android) overlaid on the chat. ExoPlayer with SimpleExoPlayer and DefaultMediaSourceFactory supports HLS, DASH, and progressive MP4 out of the box.
By comparison, Android's native VideoView gives less control over buffering and doesn't natively support HLS — ExoPlayer solves these issues, typically starting streams 2x faster.
Limitations and UX
The video length limit is not technical but a UX decision. We recommend 60–120 seconds for chats. If exceeded, we show a warning before transcoding starts, not after.
A progress bar showing speed (e.g., "2.3 MB/s") and remaining time is mandatory. A cancel button must stop both transcoding and upload, and delete temporary files.
| Stage | Time (30s clip, 720p) |
|---|---|
| Transcoding (iPhone 14) | 3–5 s |
| Transcoding (iPhone SE 2) | 7–12 s |
| Upload 15 MB at 10 Mbit/s | ~12 s |
| Preview generation | < 1 s |
| Problem | Solution |
|---|---|
| Large file size | Transcode to 720p H.264 |
| Connection drop | Chunked upload with resume |
| Display delay | Instant preview |
What is included in our work
We provide: API documentation, source code of the module, configured authorization schemes for S3/GCS, server deployment instructions, and training for your iOS/Android developers. We guarantee support during the commissioning phase. Order video upload implementation for your chat — our engineers will audit and propose the optimal solution.
Timelines
Basic implementation (selection, transcoding, chunked upload, preview, playback) — 3–5 days if your backend already supports multipart upload. Background upload with resume adds another 1–2 days. Cost is calculated individually after requirements analysis.
Contact us for a free project estimate. Our certified engineers perform integration reviews and provide optimization recommendations.







