Разработка публикации постов с видео в мобильном приложении
Видео в постах — это не просто загрузка файла. Здесь важен весь путь: выбор, обрезка, транскодирование, upload с прогрессом, генерация превью, и наконец — воспроизведение в ленте без подвисаний. Каждый шаг с нюансами.
Выбор и обрезка видео
PHPickerViewController с filter: .videos на iOS. Для социальных постов обычно ограничиваем длину — 60–90 секунд. Проверяем длительность через PHAsset.duration ещё в пикере, до загрузки данных.
Обрезка — AVPlayerViewController со встроенным trim editor (iOS 14+, AVPlayerViewController.allowedPictureInPictureMediaTypes), или кастомный триммер через AVPlayer + AVPlayerLayer с drag-handles для CMTimeRange. Кастомный триммер даёт полный контроль над UI, но требует ~2–3 дней разработки отдельно.
На Android — VideoTrimmingView через MediaPlayer + MediaMetadataRetriever для генерации тайм-лайна. Или используем isoviewer / mp4parser для обрезки без полного декодирования.
Транскодирование: обязательно, не опционально
Видео с камеры iPhone 14 Pro в 4K/60fps — 400 МБ в минуту. Для поста в 60 секунд это 400 МБ. Транскодируем до загрузки.
Целевые параметры для постов: 1080p, H.264, 4–6 Мбит/с, AAC 128 кбит/с. Это даёт ~35–45 МБ для 60-секундного клипа — разумный компромисс между качеством и размером.
На iOS — AVAssetExportSession с AVAssetExportPreset1920x1080:
let export = AVAssetExportSession(asset: asset, presetName: AVAssetExportPreset1920x1080)!
export.outputURL = tempOutputURL
export.outputFileType = .mp4
export.exportAsynchronously {
// completion
}
Прогресс транскодирования через export.progress опрашиваем по таймеру — у AVAssetExportSession нет делегата для прогресса, только polling. На iPhone SE 2nd gen транскодирование 60-секундного видео — 20–30 секунд. Нужен явный прогресс-индикатор, иначе пользователь решит, что приложение зависло.
На Android — FFmpegKit для гибкого транскодирования или MediaTranscoder (Natario1) — более современная библиотека на MediaCodec без FFmpeg. MediaTranscoder весит ~500 КБ против ~15 МБ у FFmpegKit — важно для размера APK.
Upload
Видео для поста — крупный файл, upload должен поддерживать возобновление. S3 Multipart Upload: файл делим на части по 5–10 МБ, каждую загружаем параллельно (2–3 параллельных запроса ускоряют upload без перегрузки сети).
На iOS — URLSession с BackgroundConfiguration для продолжения upload при сворачивании. Completion handler через application(_:handleEventsForBackgroundURLSession:) в AppDelegate.
На Android — WorkManager с UploadWorker и setConstraints(Constraints.Builder().setRequiredNetworkType(CONNECTED).build()). WorkManager гарантирует выполнение даже после перезапуска устройства — если пользователь вышел из приложения в середине загрузки, при следующем запуске upload продолжится.
Превью и плеер в ленте
Превью-кадр генерируем до начала upload — из оригинального видео через AVAssetImageGenerator (iOS) или MediaMetadataRetriever (Android), кадр на 1-й секунде. Загружаем превью отдельно, быстро — пользователь видит пост в ленте с превью, пока видео ещё обрабатывается.
Плеер в ленте — автозапуск при появлении в viewport. Не использовать AVPlayer для каждой ячейки ленты — один shared AVPlayer, который переназначается при скролле (AVQueuePlayer для предзагрузки следующего). На Android — ExoPlayer с ExoPlayer.Builder().setLoadControl(DefaultLoadControl()) и PlayerView в RecyclerView. Предзагружаем следующее видео при скролле через MediaSource в ConcatenatingMediaSource.
Mute по умолчанию — стандарт для автозапуска в ленте. Звук включается тапом.
Сроки
Выбор + транскодирование + upload + превью + воспроизведение в ленте — 3–5 дней при готовом бэкенде. Обрезка видео + background upload + оптимистичный UI — ещё 2–3 дня. Стоимость рассчитывается индивидуально.







