Реализация AI-улучшения качества видео в мобильном приложении
Улучшение качества видео — принципиально другая задача, чем улучшение фото. Фото можно обрабатывать секундами: пользователь подождёт. Видео требует или реального времени (запись/стриминг), или постобработки с приемлемой скоростью (условно: ролик 1 минута за 2–3 минуты). Это диктует выбор модели и архитектуру решения.
Два режима — разные архитектуры
Постобработка записанного видео — поедаем видеофайл кадр за кадром через декодер, обрабатываем ML-моделью, энкодируем обратно. Скорость важна, реального времени не нужно.
Real-time улучшение при записи или просмотре — бюджет строго 33 мс на кадр при 30 fps. Сложные модели не влезут. Нужно компромиссное качество.
Большинство клиентских задач — первый режим: пользователь снял старое видео или загрузил файл, нажал «улучшить».
Постобработка на iOS: AVAssetReader + Metal + Core ML
// Читаем видео как последовательность CVPixelBuffer
let asset = AVAsset(url: videoURL)
let reader = try AVAssetReader(asset: asset)
let output = AVAssetReaderTrackOutput(
track: asset.tracks(withMediaType: .video).first!,
outputSettings: [kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange]
)
reader.add(output)
reader.startReading()
// Параллельно — writer для результата
let writer = try AVAssetWriter(outputURL: resultURL, fileType: .mp4)
let writerInput = AVAssetWriterInput(mediaType: .video, outputSettings: videoSettings)
let adaptor = AVAssetWriterInputPixelBufferAdaptor(assetWriterInput: writerInput, ...)
На каждом кадре: конвертируем YUV → RGB (Metal shader), прогоняем через Core ML модель, конвертируем RGB → YUV, пишем в AVAssetWriter. Конвертация через Metal критична — на CPU это 15–20 мс на кадр только на цветовое пространство.
Какая модель? Для денойзинга видео — RVRT или BasicVSR++ (temporal super resolution, учитывают соседние кадры). Но они требуют батча кадров и на мобиль в оригинале не идут. Компромисс — per-frame модели типа Real-ESRGAN (игнорируют временну́ю согласованность, но проще в деплое) или легковесные temporal-модели с окном 3–5 кадров.
Temporal flickering — главная проблема per-frame подхода: соседние кадры обрабатываются независимо, детали на стыках «мигают». Решение — temporal consistency loss при fine-tuning или постпроцессинг: averaging активаций между соседними кадрами с весом 0.1–0.2.
Android: MediaCodec + TFLite
// Используем MediaCodec для декодирования
val decoder = MediaCodec.createDecoderByType(format.getString(MediaFormat.KEY_MIME)!!)
decoder.configure(format, null, null, 0)
// Поверхность для декодирования напрямую в текстуру OpenGL
val surface = Surface(surfaceTexture)
decoder.configure(format, surface, null, 0)
decoder.start()
На Android декодирование в Surface → обработка через OpenGL/Vulkan compute → обратно через MediaCodec encoder. TFLite GPU Delegate работает с текстурами OpenGL напрямую через setExternalContext(), что убирает одну копию памяти на кадр.
Для Full HD (1920×1080) тайловая нарезка 256×256 даёт ~48 тайлов. При инференсе 15 мс/тайл — 720 мс на кадр. То есть постобработка минуты видео (1800 кадров) займёт ~22 минуты. Это приемлемо для редактора, не приемлемо для quick-enhance. Под quick-enhance — лёгкая модель (2–4 МБ TFLite), без тайлинга, с downscale до 540p для инференса.
Real-time денойзинг при записи
Если нужен real-time — работаем с уменьшенным разрешением. Модели, обученные на 360p/480p входе, дают результат быстро. На iPhone 14 Pro — ESRGAN x2 на 480p входе ~28 мс через ANE. На Android Snapdragon 8 Gen 2 — сопоставимо через GPU Delegate.
Для CameraX с кастомной обработкой — ImageAnalysis use case с setBackpressureStrategy(STRATEGY_KEEP_ONLY_LATEST): не копим очередь, если обработка не успевает.
Аудио не ломаем
Видео-пайплайн обрабатывает только видео-трек. Аудио копируется через AVAssetReaderTrackOutput / MediaExtractor без изменений. Типичная ошибка — забыть синхронизировать PTS (presentation timestamps) между аудио и обработанным видео треком. После AI-обработки длительность кадров не меняется, PTS из оригинала переносим один к одному.
Процесс
Анализ целевых сценариев (постобработка vs real-time), выбор модели с замерами на целевых устройствах, реализация декодирования/энкодирования через AVFoundation/MediaCodec, ML-пайплайн с тайлингом или без, тестирование на граничных случаях — HDR видео, нестандартные разрешения, поворот.
Ориентиры по срокам
Постобработка на одной платформе с per-frame моделью — 3–5 недель. Обе платформы с temporal-согласованностью и real-time режимом — 8–14 недель.







