Реалізація HLS-стримінга з мобільного пристрою
HLS-стрім з мобільного — це не те ж саме що відтворення HLS. Тут телефон виступає джерелом: записує відео сегментами, загружає їх на сервер і оновлює m3u8-плейлист. Це менш поширений сценарій, ніж RTMP-стрім, але потрібний для інтеграцій з CDN-сервісами, які приймають origin-push через HTTP.
Як працює HLS-push з пристрою
Класична схема: телефон → HTTP PUT/POST TS-сегментів + оновлення .m3u8 → origin HTTP сервер → CDN → глядачі. Альтернатива: телефон → RTMP → медіа-сервер → HLS для глядачів (тоді HLS генерує сервер, не телефон).
Прямий HLS-push з пристрою підтримують: Apple Media Stream Segmenter (тільки macOS), CloudFront з WebDAV, Akamai Media Services, власний nginx з ngx_http_dav_module.
iOS: ReplayKit + HLS Segmenter
На iOS немає вбудованого HLS-енкодера для live-стримінга — тільки AVAssetExportSession для файлів. Для live HLS з пристрою будуємо pipeline вручну:
AVCaptureSession → AVCaptureVideoDataOutput → VideoToolbox (кодування H.264) → накопичуємо NAL units у TS-сегменти по 2–4 секунди → URLSession.uploadTask на сервер → оновлюємо m3u8 маніфест.
Складання MPEG-TS з NAL units — ручна упаковка PES пакетів з PAT/PMT таблицями. Готової бібліотеки на Swift немає. Тому на практиці:
Варіант 1: FFmpegKit. FFmpegKit.executeAsync з HLS output:
-f avfoundation -i 0:0 -c:v h264_videotoolbox -b:v 2M -hls_time 2 -hls_list_size 5 -hls_flags delete_segments -method PUT http://origin/stream/index.m3u8
h264_videotoolbox — апаратний кодировщик. -method PUT загружає сегменти й плейлист на сервер. Працює, розумне навантаження на CPU.
Варіант 2: RTMP → сервер → HLS. Телефон пушить RTMP через HaishinKit, медіа-сервер (Nginx-RTMP, MediaMTX) конвертує у HLS. Надійніше, але додає 1–2 секунди затримки.
Android: MediaMuxer + HLS
Android MediaMuxer підтримує output format MUXER_OUTPUT_MPEG_4 — це mp4, не TS. Для HLS потрібен либо TS (MPEG-2 Transport Stream), либо fMP4 (fragmented MP4, підтримується HLS v7+).
fMP4 сегменти з MediaMuxer: записуємо в ByteArrayOutputStream через кастомний MediaMuxer з MUXER_OUTPUT_MPEG_4, встановлюємо fragmented MP4 прапор через MediaFormat.KEY_IS_ADTS + специфічний для виробника шлях. Це нестандартно й ненадійно.
Надійний шлях: FFmpegKit — той же підхід що на iOS, тільки для Android. h264_mediacodec замість h264_videotoolbox:
-f android_camera -i 0 -c:v h264_mediacodec -b:v 2M -hls_time 2 -hls_list_size 5 -method PUT http://origin/stream/index.m3u8
Low-Latency HLS (LL-HLS)
Стандартний HLS — затримка 6–30 секунд. LL-HLS (HLS Part) знижує до 2–4 секунд. Для цього сервер і клієнт повинні підтримувати EXT-X-PART директиви (Apple WWDC 2019).
Генерувати LL-HLS частини з мобільного пристрою (0.2–0.5 сек part duration) — надзвичайно складно без спеціалізованого енкодера. Практичніше: пристрій пушить RTMP з малим буфером, медіа-сервер (Nimble Streamer, Wowza з LL-HLS плагіном) генерує LL-HLS для глядачів.
Сценарій застосування: запис і одночасний стрім
Часто потрібно: знімаємо відео → записуємо на пристрій + одночасно стримимо. AVCaptureSession з двома output: AVCaptureMovieFileOutput (локальний запис) і AVCaptureVideoDataOutput (захист для стримінга). Обидва працюють паралельно — процесор телефона тягне обидва потоки без проблем на сучасному залізі (A15+).
Терміни
Реалізація HLS-стримінга з мобільного через FFmpegKit з загруженням на origin-сервер — 2–3 дні. З кастомним TS-сегментером і LL-HLS — 1–2 тижні.







