Интеграция FFmpeg для обработки мультимедиа в мобильном приложении
FFmpeg на мобильном устройстве — это когда нужно транскодировать видео, извлечь аудио, смержить несколько дорожек, конвертировать формат или нарезать медиафайл прямо на телефоне без отправки на сервер. Нативные API (AVFoundation, MediaCodec) не закрывают все эти сценарии — FFmpeg закрывает.
Подключение FFmpeg к проекту
iOS. ffmpeg-kit — мобильная сборка FFmpeg с Swift/Objective-C обёрткой:
// Podfile
pod 'ffmpeg-kit-ios-full', '~> 6.0'
// Использование
FFmpegKit.executeAsync("-i input.mp4 -vn -acodec copy output.aac") { session in
guard let returnCode = session?.getReturnCode() else { return }
if ReturnCode.isSuccess(returnCode) {
print("Готово: \(session?.getOutput() ?? "")")
} else {
print("Ошибка: \(session?.getLogsAsString() ?? "")")
}
}
Android. Тот же ffmpeg-kit-android (Maven):
implementation("com.arthenica:ffmpeg-kit-android:6.0.LTS")
FFmpegKit.executeAsync(
"-i input.mp4 -vf scale=1280:720 -c:v libx264 -preset ultrafast -crf 23 output.mp4"
) { session ->
if (ReturnCode.isSuccess(session.returnCode)) {
// обрабатываем результат на main thread
}
}
ffmpeg-kit поставляется в нескольких вариантах сборки: min (минимальный набор кодеков), min-gpl, https, full, full-gpl. Для большинства задач достаточно https (H.264, AAC, MP3, HTTPS-потоки). full-gpl включает x264, x265, libvpx — нужен если хотим кодировать H.264 через libx264 вместо системного кодека.
Flutter. ffmpeg_kit_flutter (pub.dev) — та же библиотека с Dart-обёрткой.
Типичные задачи и команды
Транскодирование видео
# H.264, 720p, CRF 23 (баланс качество/размер)
-i input.mov -c:v libx264 -preset ultrafast -crf 23 -c:a aac -b:a 128k -vf scale=1280:720 output.mp4
-preset ultrafast — скорость кодирования важнее размера файла. На телефоне CPU медленный, ultrafast или superfast — разумный выбор для UGC-контента. veryfast даёт заметно меньший размер, но кодирует в 2–3 раза дольше.
Обрезка без перекодирования
# Stream copy — быстро, без потери качества, но точность до ключевого кадра
-i input.mp4 -ss 00:00:10 -to 00:00:30 -c copy output.mp4
# Точная обрезка — медленнее, но frame-accurate
-i input.mp4 -ss 00:00:10 -to 00:00:30 output.mp4
-c copy не перекодирует — работает за секунды. Без -c copy FFmpeg декодирует и перекодирует каждый кадр. Для UI приложения: показываем кнопку «Быстрая обрезка» (c copy) и «Точная обрезка» (с перекодированием).
Объединение файлов
# Concat через список файлов (один формат)
-f concat -safe 0 -i filelist.txt -c copy output.mp4
filelist.txt содержит пути: file '/path/to/clip1.mp4'\nfile '/path/to/clip2.mp4'. Создаём файл программно во временной директории перед вызовом.
Извлечение аудио, замена звуковой дорожки
# Извлечь аудио
-i input.mp4 -vn -acodec copy output.aac
# Заменить аудио в видео
-i video.mp4 -i audio.aac -c:v copy -map 0:v:0 -map 1:a:0 output.mp4
Наложение водяного знака
-i input.mp4 -i watermark.png -filter_complex "overlay=W-w-10:H-h-10" output.mp4
W-w-10:H-h-10 — правый нижний угол с отступом 10 px.
Мониторинг прогресса
FFmpeg пишет прогресс в stderr. ffmpeg-kit предоставляет StatisticsCallback:
FFmpegKit.executeAsync(command,
withCompleteCallback: { session in /* завершено */ },
withLogCallback: nil,
withStatisticsCallback: { stats in
guard let duration = totalDurationMs else { return }
let progress = Double(stats?.getTime() ?? 0) / duration
DispatchQueue.main.async { self.progressBar.progress = Float(progress) }
}
)
stats.getTime() — текущая позиция обработки в миллисекундах. Получить totalDurationMs можно через FFprobeKit.getMediaInformationAsync.
Производительность и ограничения
На iPhone 14 Pro транскодирование 1-минутного 1080p видео через libx264 ultrafast занимает ~45–60 секунд. Это много для UX. Альтернативы:
-
Системный кодировщик через
VideoToolbox:-c:v h264_videotoolbox— использует аппаратное ускорение Apple, в 5–10 раз быстрее, но меньше контроля над битрейтом -
На Android:
-c:v h264_mediacodec— аппаратный H.264 через MediaCodec
Аппаратный кодировщик доступен не на всех устройствах и версиях. Добавляем fallback на libx264:
val command = if (isHardwareEncoderAvailable()) {
"-i input.mp4 -c:v h264_mediacodec output.mp4"
} else {
"-i input.mp4 -c:v libx264 -preset ultrafast output.mp4"
}
Размер бинарника: ffmpeg-kit-full добавляет ~30–50 МБ к размеру приложения. ffmpeg-kit-min — ~8–12 МБ. Выбираем минимальную сборку под конкретные задачи.
Сроки
Базовая интеграция с одной-двумя операциями (обрезка + конвертация) — 2 дня. Полноценный медиапроцессор с прогрессом, очередью задач и fallback на системные API — 4–5 дней.







