Содержание статьи +
- TL;DR
- Почему это важно
- Офлайн – это отдельный путь воспроизведения, а не настройка
- Два скачивания, никогда не одно
- Постоянная лицензия решает всё
- Тот же зашифрованный файл, другой тип лицензии
- Реальность по платформам: iOS, Android и веб
- Два таймера: окно хранения и окно воспроизведения
- Математика памяти: сколько весит сезон на телефоне
- Что разрешает правообладатель – офлайн это вопрос прав
- Где здесь Фора Софт
- Ключевые выводы
- Что почитать дальше
TL;DR
Дать зрителю скачать серию, чтобы посмотреть её в самолёте, – это не кнопка, которую добавляют в плеер, а отдельный путь воспроизведения со своим менеджером загрузок, своей хранимой лицензией и своими правилами. То, что позволяет скачанному видео играть без сети, называется постоянная лицензия (persistent license): небольшой пакет с ключами расшифровки и правилами, записанный на устройство, пока оно ещё онлайн; для веба это описано в стандарте W3C Encrypted Media Extensions, а нативно его реализуют FairPlay на Apple, Widevine на Android и PlayReady на Windows и многих телевизорах. Для офлайна вы ничего не перешифровываете – скачанное видео это тот же файл с шифрованием cbcs, что вы уже стримите, так что новое здесь только тип лицензии. Дальше загрузкой правят два таймера: окно хранения (сколько дней живёт лицензия) и окно воспроизведения (стартует при первом запуске), и оба задаёт правообладатель – он же решает, разрешён ли офлайн вообще.
Почему это важно
Загрузки – это то, как стриминговый сервис удерживает время просмотра в дороге, в полёте и там, где сеть слабая или платная, и это заметная функция почти любого подписного приложения, поэтому продакт-менеджера спросят о ней рано. Ловушка – считать «загрузки» небольшой задачей фронтенда, тогда как на деле это функция защиты контента: ошибитесь в модели лицензии, и сохранённый фильм либо откажется играть в режиме полёта, либо, хуже, будет играть вечно после конца аренды и нарушит договор со студией. Эта статья объясняет офлайн-скачивание и воспроизведение простым языком, чтобы вы могли оценить объём работ, разобрать SDK плеера у подрядчика и точно поговорить и с инженерами, и с правообладателями. Это глубокое продолжение раздела про офлайн в статье про воспроизведение на iOS и Android; рядом стоит матрица клиентов OTT, которая показывает все экраны, что нужно покрыть.
Офлайн – это отдельный путь воспроизведения, а не настройка
Начнём с модели в голове, потому что именно её команды путают первой. Когда зритель смотрит стрим, плеер постоянно тянет из сети две вещи: маленькие куски видео, называемые сегментами, и – для защищённого контента – лицензию, пакет данных с ключом расшифровки и правилами использования. И то и другое приходит по запросу, и ни то ни другое не должно пережить сессию. Офлайн переворачивает это. Приложение скачивает всё заранее, пока связь ещё есть, и пишет на устройство, чтобы позже, с выключенной сетью, плеер читал из локальной памяти, а не из интернета.
Эта единственная разница – «скачать заранее и сохранить» вместо «тянуть по запросу» – расходится по всему стеку. Нужен менеджер загрузок, который надёжно тянет тайтл целиком в фоне и переживает закрытие приложения. Нужно защищённое место на устройстве для зашифрованного видео. И, что удивляет неспециалистов, нужна особая лицензия, которую разрешено записать на диск и прочитать снова без сервера в зоне доступа. Стриминговый код не делает ничего из этого, поэтому офлайн строят и тестируют как отдельный путь, а не прикручивают к плееру.
Два скачивания, никогда не одно
Самая полезная фраза в этой статье: офлайн-загрузка это два скачивания, не одно. Первое очевидно – сегменты видео и аудио, те же файлы, что CDN уже отдаёт для стрима. Второе – лицензия, и именно она решает, заиграет ли что-нибудь.
Когда вы стримите, плеер просит у вашего сервера лицензий – сервиса, выдающего ключи расшифровки после проверки прав зрителя – лицензию каждый раз при старте защищённого тайтла, и эта лицензия выбрасывается в конце сессии. Для офлайна плеер должен запросить другой тип лицензии во время загрузки, пока устройство онлайн, и сохранить её рядом с медиа. Позже, в режиме полёта, плеер читает эту хранимую лицензию, получает ключ и расшифровывает видео локально. Забудете второе скачивание – медиа на устройстве есть, но каждый кадр чёрный, потому что ключ не приехал. Как устроен сам обмен ключами, разобрано в статье про серверы лицензий и доставку ключей; здесь важно одно: офлайн значит, что вы захватываете и лицензию, и захватываете её рано.
Постоянная лицензия решает всё
Тип лицензии, которой разрешено жить на устройстве, называется постоянная лицензия (persistent license), и это точное техническое понятие, а не маркетинговое слово. Веб-стандарт, управляющий воспроизведением в браузере, – спецификация W3C Encrypted Media Extensions, обычно сокращаемая до EME, рекомендация W3C 2017 года – определяет три типа сессии расшифровки. Сессия temporary не хранит ничего: лицензия и ключи исчезают в конце сессии, это обычный стриминг. Сессия persistent-license – офлайновая: по словам стандарта, лицензия «будет сохранена» (will be persisted), а запись о её уничтожении тоже должна сохраняться при удалении ключей. Третий тип, persistent-usage-record, хранит только журнал того, что играли, – для отчётности. Офлайн-скачивание это тип persistent-license, и стандарт помечает его поддержку как необязательную – первый намёк, что офлайн доступен не везде.
Нативные системы зеркалят это под своими именами. На устройствах Apple система защиты контента FairPlay Streaming возвращает ключ, помеченный сервером как временный или постоянный; когда он постоянный, устройство пишет офлайн-ключ, который сможет прочитать позже. На Android Widevine от Google выдаёт офлайн-лицензию, которую плеер хранит как маленький идентификатор. На Windows и многих смарт-ТВ PlayReady от Microsoft держит постоянную лицензию в энергонезависимой памяти, которая «живёт всё время существования хранилища или до наступления ограничения по времени». Три вендора, одна идея: лицензия, которой по политике разрешено пережить соединение с сетью.
Отсюда два следствия, и оба важны для оценки. Во-первых, постоянную лицензию надо получить, пока устройство онлайн – достать её позже в режиме полёта нельзя, поэтому поток загрузки обязан получить и проверить её прежде, чем скажет зрителю «готово к офлайну». Во-вторых, постоянная лицензия чувствительнее стриминговой, потому что ключ теперь лежит на устройстве, и правообладатели требуют более высокую планку безопасности для её выдачи – обычно аппаратную защиту – поэтому офлайн часто блокируют на устройствах с root/jailbreak и на чисто программных путях воспроизведения.
Тот же зашифрованный файл, другой тип лицензии
Вот успокаивающая часть для всех, кто боится, что офлайн удвоит счёт за кодирование: нет. Видео, которое скачивает зритель, – это тот же файл, что вы уже стримите. Современный стриминг шифрует каждый тайтл один раз по схеме cbcs зонтичного стандарта Common Encryption (ISO/IEC 23001-7), упакованного в контейнер CMAF fragmented-MP4 (ISO/IEC 23000-19), и этот один зашифрованный пакет уже играет под FairPlay, Widevine и PlayReady. Мы разбираем это схождение в статье Multi-DRM: один workflow, все устройства, а детали схемы – в CENC, CTR и CBCS простыми словами.
Офлайн переиспользует всё это. Вы не делаете «офлайн-копию» каталога. Вы скачиваете те же сегменты cbcs и связываете их с постоянной лицензией вместо временной. Держите две идеи раздельно: медиа не меняется; меняется только тип лицензии. Именно это различие позволяет сервису добавить загрузки без второго кодирования тысяч часов видео.
Реальность по платформам: iOS, Android и веб
Как и стриминг, офлайн строят под каждую платформу, и детали различаются. Таблица ниже – карта покрытия; читайте по столбцу, который оцениваете. Столбец «Нативная поддержка» – главный: офлайн комфортен на двух мобильных платформах и по-настоящему труден в обычном браузере.
| Возможность | iOS / iPadOS | Android | Веб-браузер |
|---|---|---|---|
| API загрузки | AVAssetDownloadURLSession | Media3 DownloadManager | Service Worker + IndexedDB (best-effort) |
| DRM | FairPlay (постоянный ключ) | Widevine (офлайн-лицензия) | EME persistent-license (где есть) |
| Объект лицензии | Постоянный ключ FairPlay | keySetId из OfflineLicenseHelper | Persistent MediaKeySession |
| Где хранится медиа | Управляемое хранилище | Кэш загрузок приложения | IndexedDB (временный) |
| Поддержка срока | Да (срок в ключе) | Да (срок в лицензии) | Да (срок в лицензии) |
| Нативная поддержка | Сильная | Сильная | Слабая / часто непрактична |
На iOS вы скачиваете HLS-контент через AVAssetDownloadURLSession, управляющий AVAssetDownloadTask, и для защищённых тайтлов дополнительно запрашиваете постоянный ключ FairPlay во время загрузки и сохраняете его; фреймворк Apple сам управляет зашифрованным хранилищем. На Android движок ExoPlayer внутри Jetpack Media3 использует DownloadManager (запущенный из фонового DownloadService) для медиа, а помощник OfflineLicenseHelper скачивает офлайн-лицензию Widevine, возвращая маленький keySetId, который вы храните и передаёте плееру, чтобы разблокировать файл. Минимальный набросок этого свопа на Android – иллюстративный, не продакшен-код:
// 1) Пока онлайн: заранее получаем офлайн-лицензию Widevine.
val keySetId = offlineLicenseHelper.downloadLicense(format) // сохраняем этот blob
// 2) Позже, офлайн: собираем источник с сохранённым ключом, без URL лицензии.
val drmConfig = MediaItem.DrmConfiguration.Builder(C.WIDEVINE_UUID)
.setKeySetId(keySetId) // используем сохранённый ключ вместо URL сервера
.build()В вебе офлайн – слабый угол. Тип сессии persistent-license в EME существует, и плееры вроде Shaka Player умеют хранить контент и лицензии в локальной базе браузера (IndexedDB). Но поддержка неровная по браузерам, постоянные лицензии есть не везде, а память браузера явно best-effort – операционная система может забрать её, когда на устройстве кончается место, так что «скачанный» фильм может просто исчезнуть. Для надёжных загрузок реалистичный ответ – нативное приложение или хотя бы установленная обёртка; веб-путь это бонус, а не фундамент. Веб-механика DRM лежит в статьях про стек браузерного DRM (EME) и веб-воспроизведение.
Два таймера: окно хранения и окно воспроизведения
Это та часть, которую продакт-менеджеры путают чаще всего, и самое важное правило статьи. Скачанным тайтлом правят два отдельных таймера, заданных правообладателем и реализуемых постоянной лицензией, и кончается то, что наступит раньше.
Первый таймер – окно хранения (storage / rental duration): сколько лицензии разрешено жить на устройстве после выдачи. Частое значение – 30 дней. Скачайте фильм сегодня, не открывайте – лицензия всё равно истечёт через 30 дней. На сервере лицензий это одно число: 30 дней это 30 × 24 × 3600 = 2 592 000 секунд, и по их истечении устройство удаляет лицензию, и загрузка перестаёт играть.
Второй таймер – окно воспроизведения (playback duration): более короткий отсчёт, стартующий при первом нажатии «play». Частое значение – 48 часов. Классическое правило аренды «30 дней, чтобы начать, 48 часов после начала» – это ровно два таймера в работе: окно хранения даёт месяц на старт, а нажатие play запускает 48-часовое окно, которое дальше правит всем. PlayReady даже поддерживает режим «real-time expiration» для очень коротких, точно отмеренных аренд. Модель двух таймеров задаётся в политике лицензий, которую мы разбираем целиком в статье Политика лицензий: аренда, офлайн и output control.
Разберём короткий пример вслух. Зритель скачивает фильм 1-го числа с окном хранения 30 дней и окном показа 48 часов. Если он не откроет его, фильм истечёт 31-го – таймер хранения. Если он нажмёт play 20-го, стартует таймер показа, и фильм перестанет работать 22-го, за восемь дней до конца окна хранения, – потому что всегда побеждает более ранний из двух дедлайнов. Задача приложения – показывать зрителю актуальный таймер: «Доступно ещё 29 дней» до старта и «Истекает через 47 часов» после нажатия play. Ошибка в этом сообщении – самое частое обращение в поддержку по офлайну.
Подписная загрузка работает так же механически, просто с более дружелюбными числами: окно хранения часто привязано к подписке (загрузка работает, пока активна подписка и устройство периодически отмечается), а окна показа может не быть вовсе. Механизм – постоянная лицензия со сроком – идентичен; меняются только значения политики.
Математика памяти: сколько весит сезон на телефоне
Другое число, которое удивляет команды, – место на диске, и стоит показать арифметику, потому что она определяет продуктовое решение. Поток 1080p на 5 мегабит в секунду тратит 5 ÷ 8 = 0,625 мегабайта каждую секунду. За час это 0,625 × 3600 ≈ 2250 мегабайт – около 2,25 ГБ в час. 45-минутная серия – это примерно 1,7 ГБ в таком качестве, а сезон из десяти серий – около 17 ГБ, достаточно, чтобы одним сериалом забить свободное место на бюджетном телефоне.
Поэтому зрелые функции загрузок никогда молча не берут максимальное качество. Они предлагают выбор качества загрузки – например, «стандарт» против «высокого» – и по умолчанию ставят меньшее. Экономия большая, потому что ступень ниже использует меньший битрейт: многие сервисы качают в эффективном кодеке HEVC около 720p, выходя на ~250 МБ в час для стандарта и ~500 МБ в час для высокого против 2,25 ГБ полной ступени 1080p. Дайте зрителю этот выбор – и сезон падает с 17 ГБ до 2–4 ГБ. Многие платформы добавляют умные загрузки – автоматически тянут следующую серию и удаляют просмотренную – чтобы устройство любителя сериалов оставалось примерно постоянным, а не забивалось. Ступени, из которых берутся эти качества, – тема статьи Encoding ladder: основы.
Что разрешает правообладатель – офлайн это вопрос прав
Финальный сдвиг ракурса: многое из того, что может ваша функция офлайна, – вообще не ваш выбор. Можно ли скачать тайтл, как долго идут окна хранения и показа, на скольких устройствах одновременно может лежать копия и переживёт ли загрузка просрочку платежа – всё это решения правообладателя о правах, выраженные в лицензии, которую выдаёт ваш сервер, и реализуемые DRM устройства. Некоторые студии запрещают офлайн для премиальных или ранних тайтлов целиком; тогда ваш каталог становится лоскутным, где у одних тайтлов кнопка загрузки есть, а у других нет, и это состояние должно приходить из вашей системы прав, а не из глобального тумблера.
Число устройств – часть той же картины. Крупные сервисы ограничивают, на скольких устройствах одновременно могут лежать загрузки – обычно два на стандартном тарифе и около шести на премиальном – и сколько активных загрузок держит одно устройство, часто около 100, причём тарифы с рекламой ограничены меньшим месячным лимитом. Это бизнес-правила поверх DRM, и живут они в вашей логике биллинга и прав, которую мы разбираем в статье Биллинг подписок и entitlement. Планка безопасности тоже важна: поскольку постоянный ключ лежит на устройстве, правообладатели обычно требуют аппаратную защиту (уровень L1 у Widevine или Secure Enclave у Apple) для офлайна в HD и 4K и вовсе блокируют загрузки на устройствах с root/jailbreak, где этой защите нельзя доверять.
«Частые ошибки – пять, что ломают загрузки. Первая: забыть второе скачивание – медиа сохранено, постоянной лицензии нет, и каждый офлайн-кадр чёрный; всегда получайте и проверяйте лицензию во время загрузки, пока онлайн. Вторая: пытаться достать лицензию в режиме полёта – нельзя, получайте заранее. Третья: показать не тот таймер, и зритель, нажавший play, видит «осталось 29 дней» и в шоке, когда всё умирает через 48 часов; показывайте активное окно. Четвёртая: качать по умолчанию в полном качестве и забивать телефон; дайте выбор качества и ставьте меньшее. Пятая: считать, что браузер потянет надёжный офлайн; планируйте нативное приложение, потому что память браузера best-effort и может быть очищена.»
Где здесь Фора Софт
Офлайн обычно вскрывает все слабые места стримингового продукта разом, потому что должен работать в масштабе целого каталога, на iOS и Android, по правилам прав каждого правообладателя и с постоянной лицензией, которую надо корректно получить, сохранить и просрочить на устройстве. Фора Софт строит видеостриминг, OTT/Internet TV, e-learning и телемедицину с 2005 года – 250+ проектов для 400+ клиентов за 20+ лет – так что офлайн-паттерны отсюда (постоянные лицензии FairPlay и Widevine, модель аренды с двумя таймерами, управление качеством загрузки и правила прав, что её гейтят) – часть нашей повседневной стриминговой работы. Мы вендор-нейтральны: мы превращаем офлайн-политику каждого правообладателя в поток загрузки, который держится в поле, а не перепродаём один DRM-SDK.
Ключевые выводы
- Офлайн – это второй путь воспроизведения: менеджер загрузок, защищённое хранилище и постоянная лицензия.
- Офлайн-загрузка это два скачивания – медиа и постоянная лицензия, полученная онлайн.
- Вы не перекодируете; загрузка это тот же файл cbcs, но с постоянной лицензией.
- Загрузкой правят два таймера: окно хранения и более короткое окно показа; побеждает ранний.
- Правообладатель решает, разрешён ли офлайн, окна, число устройств и планку безопасности.
- Надёжному офлайну нужно нативное приложение; память браузера best-effort и может быть очищена.