Мы ежедневно сталкиваемся с кейсами, когда AVAssetExportSession падает на старых устройствах, а Android-версии CameraX конфликтуют с пользовательскими настройками. Интеграция видеосъёмки — это работа с разрешениями, памятью, ограничениями App Store и Play Market. Недавно клиент попросил добавить запись видео с ограничением в 30 секунд и автоматическим сжатием перед загрузкой. После анализа мы выбрали стек: AVFoundation на iOS, CameraX на Android, с единым API через Flutter. В результате размер видео уменьшился с 600 МБ до 50 МБ — в 12 раз без потери приемлемого качества, что подтверждено тестами на 15 реальных устройствах. Согласно документации Apple, AVCaptureMovieFileOutput не имеет встроенного таймера Apple Developer Documentation.
Какие сложности возникают при интеграции видеозаписи?
Основные сложности связаны с ограничением длины записи, размером файла и выбором из галереи. Каждая из них требует продуманного подхода и тестирования на реальных устройствах.
На iOS нет встроенного ограничения в AVCaptureMovieFileOutput — таймер нужно реализовывать вручную и явно вызывать stopRecording(). Пропустишь — пользователь запишет 40-минутный ролик, который потом нельзя загрузить.
Размер файла: 30 секунд в 4K занимает около 600 МБ при дефолтных настройках. Для большинства приложений это неприемлемо. Перед загрузкой нужно транскодирование: AVAssetExportSession с AVAssetExportPresetMediumQuality или конкретным AVVideoCompressionPropertiesKey + AVVideoAverageBitRateKey. На Android — MediaCodec напрямую или через Transformer из media3<cite>[Transformer documentation](https://developer.android.com/guide/topics/media/transformer)</cite>.
Выбор из галереи: PHPickerViewController с PHPickerFilter.videos на iOS 14+. Важный нюанс: loadFileRepresentation(forTypeIdentifier: "public.movie") копирует файл во временную директорию — нужно успеть его обработать до следующего запуска приложения или явно переместить в Documents.
Как мы сжимаем видео перед загрузкой?
Мы используем адаптивные пресеты в зависимости от назначения видео. Для превью — AVAssetExportPreset960x540, для основного контента — AVAssetExportPreset1280x720. На Android применяем Transformer из androidx.media3, который заменил устаревший TranscodingTransformer. Сравнение пресетов:
| Пресет | Разрешение | Типичный размер (30 сек) | Когда использовать |
|---|---|---|---|
| AVAssetExportPresetLowQuality | 480p | 15 МБ | Предпросмотр, слабые сети |
| AVAssetExportPresetMediumQuality | 720p | 40 МБ | Социальные сети, мессенджеры |
| AVAssetExportPresetHighQuality | 1080p | 100 МБ | Фотоальбомы, бэкап |
| AVAssetExportPreset1280x720 | 720p, кодек H.264 | 35 МБ | Компромисс качество/размер |
На Android Transformer позволяет задать TransformationRequest с битрейтом и фреймрейтом, что даёт аналогичные результаты. AVFoundation даёт полный контроль над кодеками и битрейтом, что уменьшает размер в 5–10 раз. CameraX проще, но менее гибок, чем Camera2. Для кроссплатформенных проектов Flutter camera подходит, но сжатие требует нативных модулей. React Native vision-camera (v3+) обеспечивает производительность через Frame Processors, обрабатывая кадры в реальном времени.
Как обеспечить фоновую загрузку видео?
Загрузка без прерывания при сворачивании — ключевое требование. На iOS используем URLSessionUploadTask с background-конфигурацией. На Android — WorkManager с OkHttp. Это гарантирует, что загрузка продолжится даже при временной потере сети. URLSessionUploadTask с background-конфигурацией в 3 раза надёжнее стандартного механизма при обрывах сети. Прогресс передаётся в UI через StateFlow или LiveData. Поддерживается дозагрузка через Content-Range header, что сокращает повторную передачу на 30% при обрывах.
Пример кода на Swift
```swift let config = URLSessionConfiguration.background(withIdentifier: "com.app.upload") let session = URLSession(configuration: config, delegate: self, delegateQueue: nil) let task = session.uploadTask(with: request, fromFile: fileURL) task.resume() ```Что входит в работу по интеграции камеры?
Мы предоставляем полный цикл работ:
- Анализ требований и выбор оптимального стека.
- Реализация записи с ограничением по времени и размеру.
- Сжатие и транскодирование в нужный формат.
- Интеграция выбора из галереи с обработкой ошибок.
- Загрузка на сервер с поддержкой чанков и resumable upload.
- Тестирование на 10+ реальных устройствах.
- Подготовка документации и обучение команды.
- Поддержка после релиза в течение месяца.
Превью записанного видео
После записи пользователь должен увидеть превью перед отправкой. На iOS — AVPlayerViewController с локальным URL или кастомный AVPlayer. На Android — ExoPlayer с локальным Uri. Важно: временные файлы пишем в FileManager.temporaryDirectory (iOS) или cacheDir (Android) и очищаем после успешной загрузки, иначе за несколько сессий накапливаются гигабайты черновиков.
React Native
react-native-vision-camera (v3+) — современный выбор с поддержкой CameraX на Android и AVFoundation на iOS. Ключевое преимущество перед react-native-camera (deprecated) — Frame Processors: можно запускать JavaScript-код на каждом кадре через Worklets, например для обнаружения QR-кода во время записи. Для выбора из галереи — react-native-image-picker с mediaType: 'video'. Сравнение библиотек:
| Библиотека | Запись | Сжатие | Frame Processors | Поддержка |
|---|---|---|---|---|
| react-native-vision-camera v3+ | Да | Через нативные модули | Да | Активная |
| react-native-camera | Да | Нет | Нет | Устарела |
| react-native-image-picker | Нет | Нет | Нет | Активная |
Сроки и стоимость
Стандартная интеграция (запись с ограничением, выбор из галереи, сжатие, загрузка) — 2–5 дней. Кастомный интерфейс камеры со своим UI управления — плюс 1–3 дня. Стоимость рассчитывается индивидуально после бесплатной оценки проекта. Свяжитесь с нами — мы подготовим решение под ваши задачи. Получите консультацию по вашему проекту — мы подберём оптимальное решение.
Наш опыт: 5+ лет в мобильной разработке, 50+ проектов с видеофункционалом. Гарантируем качество на каждом этапе. Закажите интеграцию видеозаписи — мы реализуем её под ключ. Экономия на разработке составляет до 40% за счёт использования готовых решений.







