Overcoming Timeouts in AI Transcription for Mobile Apps
A user uploads a 40-minute meeting recording—and waits for the text. If a raw 300 MB MP4 goes to the server and a JSON returns 90 seconds later, the UX is broken before the first word even appears. We build pipelines where the mobile client doesn't just send the file but participates in data preparation: trimming, conversion, chunking—and receives the result progressively while the model is still processing. We specialize in end-to-end AI transcription integration, accounting for platform specifics and API limitations. With over 5 years of mobile development experience and 15+ implemented transcription pipelines for iOS and Android, totaling more than 10,000 hours of audio processed.
The most common mistake is sending the entire file via URLSession.dataTask or OkHttp with default timeouts. For files over 50 MB, this leads to NSURLErrorTimedOut (iOS) or SocketTimeoutException (Android) in 70% of cases. Servers often respond with 413 Entity Too Large if the limit isn't coordinated. On devices with 2 GB RAM, buffering the entire file in memory causes OOM—especially with video.
Why VAD Is Critical for Accuracy?
Chunking every 60 seconds without considering pauses cuts words in half—transcription splits "транскрибация" into "транс" and "крибация". Voice Activity Detection (VAD) cuts at real pauses: on iOS we use AVAudioEngine with a threshold of -45 dBFS, on Flutter the voice_activity_detector package (WebRTC VAD). This improves recognition accuracy by 15–20% for informal speech compared to uniform chunking.
Typical VAD settings:
| Parameter | Recommended Value | Note |
|---|---|---|
min_speech_duration |
0.8 s | At least 0.5 s for short phrases |
min_silence_duration |
1.2 s | Increase to 2 s for interviews |
threshold |
-45 dBFS | For quiet recordings use -35 dBFS |
frame_size |
30 ms | 10–30 ms per WebRTC |
How to Tune VAD for Your Data
- Record a 10-minute speech sample on the target device.
- Run it through VAD with default parameters and visualize chunk boundaries.
- Adjust
min_speech_durationandthresholdso chunks don't clip phrase starts/ends. - Test on multiple files with varying loudness and background noise.
How to Convert Codecs Without Loss?
Whisper API accepts audio/wav, mp3, mp4, ogg, but not all codecs inside. .mov with pcm_s16le is fine, with ac3 gives 400 Bad Request. On iOS AVAssetExportSession with preset AVAssetExportPresetAppleM4A covers 95% of formats. On Android—MediaExtractor + MediaCodec (PCM) → MediaMuxer (AAC). For exotic codecs we add FFmpeg (mobile-ffmpeg-full-gpl on Android, ffmpegkit on iOS).
More on codec conversion
If standard tools fail, FFmpeg is used with settings: `-acodec pcm_s16le -ar 16000 -ac 1` for Mono WAV, which is guaranteed to be accepted by all APIs.How the Pipeline Works in Practice
File Preparation on Device
// iOS: Extract audio track from video
let asset = AVURLAsset(url: videoURL)
let exportSession = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetAppleM4A)!
exportSession.outputFileType = .m4a
exportSession.outputURL = tempAudioURL
await exportSession.export()
After export—split into chunks of 25 MB (Whisper API limit) using VAD boundaries. Each chunk is uploaded via URLSession.uploadTask(with:fromFile:) with a background configuration (URLSessionConfiguration.background) so the upload continues even when the app is minimized.
On Android analogously: WorkManager with CoroutineWorker for background processing, OkHttp with RequestBody.create through File, not ByteArray—critical for memory economy on devices with 2 GB RAM.
Streaming Results
Instead of polling every N seconds—WebSocket or SSE. If using your own backend on top of Whisper, the server can stream partial_transcript as chunks are processed. On the client it's URLSessionWebSocketTask (iOS) or OkHttp WebSocket (Android), which appends lines to StateFlow / @Published—UI updates in real time.
For direct integration with the OpenAI Whisper API there's no streaming—the API is synchronous. So for large files, split into independent requests and merge results on the client by chunk index, not by response order (the network does not guarantee order).
Storage and Post-processing
Raw Whisper transcription returns segments with timestamps—more valuable than just text. Store JSON with start, end, text for each segment: this enables "tap on word → rewind audio".
For post-processing—punctuation and diarization (who said what). Whisper does not separate speakers. This requires a separate step: pyannote.audio via API or AssemblyAI with speaker_labels: true. On the client just merge two JSONs by timestamps.
Provider Comparison
| Provider | Accuracy (RU) | Streaming | Diarization | File Limit |
|---|---|---|---|---|
| OpenAI Whisper | High | No | No | 25 MB |
| AssemblyAI | Medium | Yes | Yes | 5 GB |
| Deepgram Nova-2 | High | Yes | Yes | No limit |
| Google Speech-to-Text v2 | Medium | Yes | Yes | 1 GB |
| On-device (iOS CoreML) | Medium | No | No | RAM-bound |
For Russian, Whisper large-v3 delivers 30% higher accuracy than Google Speech-to-Text, especially on informal speech and technical jargon. Deepgram Nova-2 with language: ru is a good option if real-time is needed. Transcription costs can be reduced by up to 40% by choosing the right provider.
OpenAI Whisper documentation
What's Included
- Format audit—determine average file size, codecs, language, diarization requirements.
- Provider and architecture selection—recommendation on model (Whisper, Deepgram, AssemblyAI) and upload strategy.
- Pipeline development—file preparation, chunking, background upload, result streaming.
- Post-processing integration—punctuation, diarization, UI synchronization.
- Testing on real devices—including CoreML and MediaCodec.
- Documentation—API description, data flow diagrams, modification instructions.
- Post-delivery support—monitoring setup, bug fixes, consultations.
Work Process
We start with an audit: file format, average size, languages, need for diarization, offline requirements. Based on that we choose the provider and pipeline architecture.
Development proceeds in stages: first a basic upload + transcription without optimizations, then add chunking, background upload, UI streaming, post-processing. Each stage is a separate branch with functional tests on real devices (not simulators—CoreML and MediaCodec behave differently on real hardware).
Timeline from a simple Whisper API integration to a full pipeline with diarization and background upload: 2 to 6 weeks depending on platform and requirements. Integration cost is estimated individually after the audit.
Contact us for a free audit of your files—it takes no more than an hour. Order the integration and get a working pipeline in the shortest time.







