Транскодування (Transcoding) — це процес перетворення цифрового медіафайлу з одного формату стиснення в інший з повним декодуванням і повторним кодуванням. На відміну від трансмодуляції (зміни лише контейнера), транскодування змінює кодек, бітрейт, роздільну здатність та інші параметри стисненого потоку. За даними Apple AVFoundation documentation (2026), транскодування використовується для адаптації контенту під різні пристрої та мережеві умови.
Головне
Транскодування — це процес перетворення медіафайлу з одного формату стиснення в інший шляхом повного декодування вихідного потоку в проміжний нестиснений PCM-формат і подальшого кодування з новими параметрами. Якщо у вихідному файлі відео стиснено кодеком H.264 з бітрейтом 10 Мбіт/с, а на виході потрібен H.265 з бітрейтом 3 Мбіт/с — це транскодування.
Транскодування відрізняється від простого перепакування (трансмодуляції), при якому змінюється лише контейнер (наприклад, MP4 в MKV), а сам стиснений бітовий потік залишається незмінним. При транскодуванні відбуваються обчислювально затратні перетворення: декодування кожного кадру, застосування фільтрів (масштабування, кольорокорекція, обрізання), повторне кодування з новими параметрами. Це робить транскодування однією з найбільш ресурсоємних операцій при роботі з медіа.
Транскодування застосовується в широкому спектрі завдань: адаптація відео під обмеження пропускної здатності мережі, конвертація у формат з апаратною підтримкою декодування на цільовому пристрої, створення кількох версій для HLS/DASH-стрімінгу, вилучення аудіодоріжок в окремий файл. Сервіси OTT (Netflix, YouTube, Twitch) транскодують кожен завантажений файл у десятки варіантів з різними бітрейтами, роздільними здатностями та кодеками для забезпечення адаптивного стрімінгу мільйонам користувачів.
Процес транскодування складається з трьох основних етапів: декодування, обробка та кодування. Кожен етап може бути виконаний як на CPU, так і на GPU/апаратних блоках залежно від доступності та необхідної продуктивності.
Перший етап — декодування вихідного потоку. Вихідний файл читається з контейнера (MP4, MOV, MKV), після чого стиснені відеопакети направляються в декодер. Декодування може бути апаратним (якщо кодек підтримується) або програмним через FFmpeg. На виході декодування отримуються нестиснені кадри у форматі YUV420 або BGRA — саме на цій стадії транскодування відрізняється від простого ремультиплексування.
Другий етап — фільтрація та обробка. Декодовані кадри проходять через ланцюжок фільтрів: масштабування до цільової роздільної здатності, зміна частоти кадрів, кольорокорекція, накладання тексту або графіки. Ланцюжок фільтрів FFmpeg будується як граф, де кожен фільтр — це окремий модуль обробки. Наприклад, фільтр scale=1280:720 змінює роздільну здатність, fps=30 змінює частоту кадрів, а yadif виконує деінтерлейсинг. Всі операції виконуються над нестисненими кадрами, тому другий етап є найбільш ресурсоємним.
Третій етап — кодування в цільовий формат. Оброблені кадри подаються на вхід енкодеру, який стискає їх за алгоритмом цільового кодека. Енкодер може бути апаратним (VideoToolbox на iOS, MediaCodec на Android) або програмним (libx264, libx265). Параметри кодування: CRF (Constant Rate Factor) для постійної якості, бітрейт для CBR/VBR, профіль і рівень для сумісності з цільовими пристроями.
// Схема pipeline транскодування на FFmpeg
AVFormatContext *inputCtx, *outputCtx;
AVCodecContext *decoderCtx, *encoderCtx;
AVFrame *frame = av_frame_alloc();
AVPacket packet;
while (av_read_frame(inputCtx, &packet) >= 0) {
// 1. Декодувати
avcodec_send_packet(decoderCtx, &packet);
avcodec_receive_frame(decoderCtx, frame);
// 2. Фільтрувати (масштабування + зміна fps)
sws_scale(swsCtx, frame->data, frame->linesize,
0, frame->height, scaledFrame->data,
scaledFrame->linesize);
// 3. Кодувати
avcodec_send_frame(encoderCtx, scaledFrame);
avcodec_receive_packet(encoderCtx, &outPacket);
av_interleaved_write_frame(outputCtx, &outPacket);
}
Наведений пайплайн демонструє класичний цикл транскодування. Функція av_read_frame читає стиснені пакети з вхідного файлу, avcodec_send_packet декодує їх у кадри, sws_scale виконує масштабування, і avcodec_send_frame кодує оброблений кадр у вихідний формат. Такий триетапний цикл повторюється для кожного кадру або групи кадрів (GOP), залежно від налаштувань енкодера.
Різниця між транскодуванням і трансмодуляцією — одна з найчастіших точок плутанини в медіаінженерії. Розуміння цієї різниці критично важливе для вибору правильної стратегії обробки медіа.
| Параметр | Транскодування | Трансмодуляція |
|---|---|---|
| Що змінюється | Кодек, бітрейт, роздільна здатність | Контейнер, метадані |
| Обчислювальне навантаження | Високе (декодування + кодування) | Мінімальне (копіювання пакетів) |
| Якість | Може погіршитися (втрати генерації) | Без втрат |
| Час виконання | Хвилини–години для довгого відео | Секунди–хвилини |
| Застосування | Адаптація формату, стиснення | Зміна контейнера для сумісності |
Трансмодуляція — це перепакування стисненого потоку в інший контейнер без декодування та повторного кодування. Якщо відео вже стиснено кодеком H.265 у контейнері MP4, і його потрібно помістити в контейнер MOV або MKV — трансмодуляція просто копіює бітові пакети з одного контейнера в інший. Якість не страждає, час обробки мінімальний, оскільки не потрібне декодування кадрів. FFmpeg виконує трансмодуляцію з прапорцем -codec copy.
Транскодування ж повністю розшифровує та перестискає медіапотік. Кожного разу, коли відео проходить через транскодування, може виникнути втрата покоління (generation loss) — незначне погіршення якості через повторне стиснення з втратами. Навіть при однаковому бітрейті третє покоління транскодування зазвичай гірше за перше. Саме тому професіонали рекомендують зберігати мастер-копії в нестиснених або мінімально стиснених форматах (ProRes, DNxHR) і транскодувати лише фінальні версії для доставки.
Вибір інструменту транскодування залежить від платформи, вимог до продуктивності та сценарію використання. Для мобільної розробки доступні як нативні API, так і крос-платформенні бібліотеки.
FFmpeg — стандарт де-факто для транскодування на всіх платформах. Командний рядок FFmpeg дозволяє виконувати практично будь-які перетворення: зміна кодека, зміна бітрейту, обрізання, склеювання, накладання фільтрів. Для мобільних застосунків FFmpeg інтегрується через бібліотеку libavformat, libavcodec та libavfilter. Приклад типової команди транскодування: ffmpeg -i input.mp4 -c:v libx265 -crf 23 -c:a aac -b:a 128k output.mp4.
На iOS транскодування виконується через AVAssetWriter та AVAssetReader. AVAssetReader декодує вихідний файл, читаючи нестиснені кадри, а AVAssetWriter кодує їх у цільовий формат. Цей підхід використовує апаратні енкодери VideoToolbox автоматично, що забезпечує максимальну продуктивність. На Android аналогічна функціональність доступна через MediaCodec у парі з MediaExtractor та MediaMuxer — MediaExtractor вилучає стиснені пакети, MediaCodec декодує та кодує, MediaMuxer записує результат.
Для серверного транскодування в production-середовищі використовуються хмарні сервіси: AWS Elemental MediaConvert, Azure Media Services, Google Transcoder API. Ці сервіси автоматично масштабуються під навантаження, підтримують всі популярні формати та можуть транскодувати один вхідний файл у десятки вихідних варіантів для адаптивного стрімінгу (HLS, DASH). Для мобільних застосунків хмарне транскодування — оптимальне рішення, оскільки воно не навантажує пристрій користувача та дозволяє готувати контент асинхронно.
Розглянемо практичні приклади транскодування на мобільних платформах з використанням апаратного прискорення та налаштуванням ключових параметрів якості.
import AVFoundation
func transcodeVideo(sourceURL: URL, destURL: URL) {
let asset = AVAsset(url: sourceURL)
let preset = AVAssetExportPresetHEVCHighestQuality
AVAssetExportSession(asset: asset, presetName: preset)?
.exportAsynchronously {
switch assetExportSession?.status {
case .completed:
print("Транскодування завершено")
case .failed:
print("Помилка: " + assetExportSession.error.localizedDescription)
default:
break
}
}
// Ручне транскодування з AVAssetReader + AVAssetWriter
let reader = try AVAssetReader(asset: asset)
let writer = try AVAssetWriter(url: destURL,
fileType: .mp4)
let outputSettings: [String: Any] = [
AVVideoCodecKey: AVVideoCodecType.hevc,
AVVideoWidthKey: 1920,
AVVideoHeightKey: 1080,
AVVideoCompressionPropertiesKey: [
AVVideoAverageBitRateKey: 4_000_000,
AVVideoProfileLevelKey: AVVideoProfileLevelH265Main10
]
]
let adaptor = AVAssetWriterInput(
mediaType: .video,
outputSettings: outputSettings
)
writer.add(adaptor)
}
У прикладі використовуються два підходи до транскодування на iOS. AVAssetExportSession — простий спосіб з попередніми налаштуваннями якості (HEVCHighestQuality для H.265). Ручний пайплайн через AVAssetReader + AVAssetWriter дає повний контроль над параметрами: бітрейт, профіль, рівень. Параметр AVVideoProfileLevelH265Main10 вмикає HDR-профіль Main10 з глибиною кольору 10 біт, що важливо для сучасного HDR-контенту.
class Transcoder(private val context: Context) {
fun transcodeToHevc(inputUri: Uri, outputFile: File) {
val extractor = MediaExtractor()
extractor.setDataSource(context, inputUri, null)
val trackFormat = extractor.getTrackFormat(videoTrackIndex)
val mime = trackFormat.getString(MediaFormat.KEY_MIME)
val decoder = MediaCodec.createDecoderByType(mime!!)
val encoder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_HEVC)
val outputFormat = MediaFormat.createVideoFormat(
MediaFormat.MIMETYPE_VIDEO_HEVC, 1920, 1080
).apply {
setInteger(MediaFormat.KEY_BIT_RATE, 4_000_000)
setInteger(MediaFormat.KEY_FRAME_RATE, 30)
setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 2)
}
encoder.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
encoder.start()
}
}
Код на Android створює пайплайн з MediaExtractor — MediaCodec decoder — MediaCodec encoder — MediaMuxer. MediaExtractor визначає тип кодека з вхідного файлу та вибирає відповідний декодер. Енкодер налаштовується на H.265 (HEVC) з бітрейтом 4 Мбіт/с та інтервалом ключових кадрів 2 секунди, що оптимально для стрімінгу. Важливо: MediaCodec encoder працює синхронно, тому для realtime-транскодування потрібно організувати цикл з коректною обробкою часових міток (PTS) для кожного кадру.
Транскодування на мобільних пристроях — завдання, що вимагає ретельної оптимізації через обмежені ресурси CPU, GPU та теплові обмеження. Декілька стратегій допомагають виконувати транскодування ефективно.
Ключовий фактор продуктивності — апаратний енкодер. На iOS VideoToolbox надає апаратне кодування H.264 та H.265 зі швидкістю, в 5–10 разів вищою за програмний libx264. На Android MediaCodec використовує апаратні OMX-компоненти, якщо вони доступні. Увімкнення апаратного кодування скорочує час транскодування 10-хвилинного відео з 30–40 хвилин (програмно) до 3–5 хвилин (апаратно) на флагманському пристрої.
Для мобільного транскодування критично важливий баланс між якістю, розміром та часом обробки. Для H.265 на мобільних пристроях рекомендується бітрейт 4–8 Мбіт/с для 1080p відео з частотою кадрів 30 FPS. CRF-режим (Constant Rate Factor) в libx265 дозволяє задати якість безпосередньо, де 23–28 дає хорошу візуальну якість при помірному розмірі файлу. Для апаратних енкодерів використовуйте CBR-режим з цільовим бітрейтом, оскільки CRF апаратно не підтримується.
Безперервне транскодування на мобільному пристрої викликає значний нагрів. За 5–7 хвилин інтенсивного кодування 4K-відео температура процесора може досягти 50–55 градусів, після чого вмикається троттлінг. Рішення — транскодування з паузами або зниження частоти кадрів до 30 FPS. Якщо застосунок вимагає масового транскодування (наприклад, відеоредактор), краще виконувати обробку батчами по 2–3 хвилини з інтервалами охолодження. Для production-сценаріїв оптимально перенести транскодування на серверну сторону та використовувати хмарні сервіси.
Поширені запитання
Кодування (encoding) — стиснення вихідних нестиснених даних у цільовий кодек. Транскодування включає і декодування, і кодування: спочатку декодує існуючий стиснений потік, потім кодує заново. Просте кодування приймає на вхід нестиснені дані (наприклад, з камери), а транскодування — вже стиснений файл.
Для максимальної сумісності — H.264. Для кращого стиснення — H.265 (HEVC). Якщо пристрій підтримує апаратне кодування H.265 (iPhone 8+, Android з Snapdragon 845+), воно забезпечує вдвічі менший розмір файлу при тій самій якості. AV1-кодування на мобільних пристроях поки що надто повільне навіть з апаратним прискоренням.
Строго кажучи, транскодування без втрат неможливе при зміні lossy-кодека. Якщо обидва кодеки стиснені з втратами, кожне покоління транскодування погіршує якість. Lossless-транскодування можливе лише між lossless-форматами (FFV1, H.264 Lossless) або при зміні контейнера без перекодування (трансмодуляція).
Так, якщо використовуються апаратні декодер та енкодер, а цільова роздільна здатність не перевищує 1080p. На пристроях з VideoToolbox (iOS) або MediaCodec (Android) realtime-транскодування H.264→H.265 можливе із затримкою 1–3 секунди. Для 4K realtime потрібен потужний SoC Apple A17 Pro, Snapdragon 8 Gen 2 або вище.
Транскодування з втратами накопичує артефакти стиснення. Якщо вихідний файл вже був сильно стиснений (бітрейт 2–3 Мбіт/с для 1080p), повторне стиснення подвоює втрати. Рекомендується транскодувати лише з мастер-копій з високим бітрейтом (20+ Мбіт/с) і використовувати CRF 18–23 для мінімальних втрат.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також