Содержание статьи +
- Кратко
- Зачем это читать
- Офлайн – это спектр, а не выключатель
- Две отдельные задачи
- Часть A. Доставка контента офлайн
- Часть B. Трекинг офлайн: как к нему пришли стандарты
- Разрешение конфликтов при возврате связи
- Как стандарты справляются с офлайном
- Пример офлайн-сценария
- Частые ошибки
- Где здесь Фора Софт
- Главное
- Что читать дальше
Кратко
Под словами «офлайн-обучение» скрываются две разные инженерные задачи: доставить курс на устройство, пока связь есть, и вернуть учебные записи на сервер, когда связь появится снова. Большинство продуктов незаметно проваливается именно на второй. SCORM, стандарт упаковки курсов для любой системы обучения, рассчитан на постоянное соединение с браузером и сам по себе не умеет отслеживать офлайн-сессию. Experience API (xAPI) создавали в том числе для того, чтобы это исправить: он записывает каждое событие как короткое самодостаточное утверждение, которое можно сохранить на устройстве и отправить позже. Безопасной синхронизацию делает простая деталь: у каждого события xAPI есть собственный уникальный идентификатор и реальное время, когда оно произошло, поэтому хранилище учебных записей отбрасывает дубликаты и восстанавливает верную хронологию, когда бы ни пришли данные. Если правильно разделить данные (события-добавления синхронизируются сами, а изменяемому состоянию вроде закладки нужно продуманное правило разрешения конфликтов), вахтовик, проведший три дня без сети, завершит курс без потери прогресса.
Зачем это читать
В России огромная часть обучения проходит там, где связи нет или она появляется эпизодически: на вахте и удалённых промышленных объектах, на судах и буровых, в поездах дальнего следования и в самолёте, в сёлах, куда мобильный интернет доходит не везде. Ещё больше людей каждый день то теряют сеть, то снова её находят: в дороге, в учебном классе в подвале, в цеху. Если ваш продукт для обучения работает только при связи, вы отсекли аудиторию, которой гибкое обучение нужнее всего, и заодно снизили долю завершений у всех остальных. В корпоративном обучении ставки выше: обучение требованиям охраны труда можно проводить с применением дистанционных технологий, кроме практических занятий (п. 66 Правил, утверждённых ПП № 2464) [1], а сведения о проверке знаний вносятся в реестр обученных лиц в течение трёх рабочих дней [11], и офлайн-продукт должен уложить синхронизацию в этот срок. Статья написана для L&D-директора, основателя EdTech-стартапа или продакт-менеджера, который решает, насколько глубоко вкладываться в офлайн и что заказывать у инженеров. Мы разберём обе части задачи – офлайн-доставку контента и офлайн-трекинг прогресса – со стандартами, на которых держится каждая, и цифрами для оценки масштаба. Это продолжение статьи «Учебное видео на слабых сетях», где речь о медленной, но доступной связи; здесь – о связи, которой нет.
Офлайн – это спектр, а не выключатель
За словом «офлайн» скрываются три разные ситуации, и правильное решение зависит от того, в какой из них находятся ваши учащиеся. Первая – иногда онлайн: вечером дома хороший Wi-Fi, днём связи практически нет. Такой учащийся синхронизируется по расписанию. Вторая – прерывистая связь: человек в идущем поезде или у сельской вышки, канал рвётся и возвращается каждые несколько минут – слишком ненадолго для стриминга, но достаточно часто, чтобы отправлять короткие порции данных. Третья – полностью офлайн: вахтовик на месторождении, экипаж судна, учащийся в зоне без покрытия. Такой человек может часами или днями оставаться без связи и синхронизируется, только добравшись до базы или города.
Это не то же самое, что слабая сеть из статьи о слабых сетях. Слабая сеть медленная, дорогая или с потерями, но она есть, поэтому адаптивный стриминг всё ещё может доставить видео попроще в реальном времени. Офлайн означает, что в момент обучения подстраиваться не подо что: контент уже должен лежать на устройстве, а трекинг – подождать. Спутать эти два случая – первая ошибка проектирования: самая продуманная лестница адаптивного битрейта ничего не даст учащемуся, у которого вообще нет сигнала.
Две отдельные задачи
Любая офлайн-функция в обучении распадается на две независимые задачи, и главная мысль статьи – не смешивать их.
Первая задача – доставка: пока связь есть, положить на устройство контент курса (видео, слайды, тест), чтобы потом открыть его без сети. Вторая – трекинг: зафиксировать, что учащийся делал офлайн (смотрел, отвечал, завершил), и вернуть эти записи на сервер, когда связь появится, точно и без дубликатов.
Многие команды делают первое и забывают второе. Учащийся скачивает курс, проходит его в самолёте, а после посадки его завершение нигде не регистрируется, потому что в продукте не было плана для записей, сделанных офлайн. Для обязательного обучения или аттестации курс, который учащийся прошёл, но система не может это подтвердить, всё равно что не пройден; а если это обучение по охране труда, неподтверждённый результат ещё и не попадёт в реестр [11]. Трекинг – полноценная функция, а не довесок к скачиванию.
Часть A. Доставка контента офлайн
Доставить контент на устройство можно двумя проверенными путями, и выбор между ними – решение в духе «покупать или разрабатывать».
Первый путь – нативное мобильное приложение, которое скачивает уроки в локальное хранилище. Это основной подход в мобильном обучении, и он даёт максимум контроля: надёжные большие загрузки, фоновое скачивание, зашифрованное хранилище и понятный учащемуся менеджер загрузок. Цена – разработка и поддержка приложений под каждую платформу.
Второй путь – прогрессивное веб-приложение (PWA), то есть сайт, спроектированный для работы офлайн. Это возможно благодаря service worker – небольшому скрипту из спецификации W3C Service Workers, который работает между страницей и сетью и может отдавать файлы из локального кеша, когда связи нет [2]. Service worker вместе с Cache API делает страницы курса, слайды и небольшие медиафайлы доступными офлайн без установки из магазина приложений [10].
С большим видео, однако, есть ограничение. Браузер обычно выгружает service worker, когда учащийся уходит со страницы, и долгая загрузка может оборваться. Для этого придуман Background Fetch API: он передаёт большую загрузку браузеру, чтобы тот докачал её даже после того, как все страницы и воркеры сайта закрыты [3]. Оговорка: Background Fetch – это инкубационная спецификация группы Web Platform Incubator Community Group (WICG), а не утверждённый стандарт W3C, и браузеры поддерживают её неравномерно [3]. Из-за этой неопределённости серьёзный офлайн-продукт с большим объёмом видео часто всё равно делает загрузки в нативном приложении, а service worker использует для всего остального. А там, где интернета нет даже на базе, контент доставляют физически: открытая платформа Kolibri, например, импортирует и обновляет курсы с USB-накопителя или с другого устройства по локальной сети [9].
Считаем объём хранилища
Офлайн ограничен памятью устройства, поэтому посчитайте, прежде чем обещать кнопку «скачать весь курс». Если взять цифры из статьи о слабых сетях (около 340 МБ на час в 360p), видеокурс на 40 часов займёт:
40 часов × 0,34 ГБ/час = 13,6 ГБ на 360p
На телефон среднего класса со свободными 8 ГБ это не поместится. Влезет около 8 ÷ 0,34 ≈ 23 часов видео в 360p, а если уроки отдавать в виде аудио со слайдами примерно по 15 МБ в час, весь 40-часовой курс займёт 40 × 0,015 = 0,6 ГБ, ещё и с запасом. Продуктовое решение следует прямо из арифметики: дайте учащемуся выбрать качество при скачивании, по умолчанию предлагайте самый лёгкий вариант и никогда не рассчитывайте, что на устройство поместится весь каталог.
Ещё одна ловушка доставки касается только защищённого видео. Если уроки зашифрованы средствами DRM, для офлайн-воспроизведения на устройстве нужна постоянная лицензия (persistent license), а у таких лицензий бывает срок действия. Учащийся, скачавший курс в марте и открывший его без сети в июне, может обнаружить, что видео не воспроизводится, потому что лицензия истекла. Механизм разобран в разделе Фора Софт о стриминге – Encrypted Media Extensions (EME). Для офлайна из этого следует одно: задавайте срок лицензии под то, сколько учащиеся реально остаются без связи, например под длину вахты.
Часть B. Трекинг офлайн: как к нему пришли стандарты
Именно эту часть продукты чаще всего делают неправильно, и здесь выбор учебного стандарта решает, возможен ли офлайн вообще.
Почему SCORM сам по себе не справляется
SCORM (Sharable Content Object Reference Model), стандарт упаковки, в котором до сих пор сделано большинство курсов, построен на одном допущении: есть постоянное соединение с системой управления обучением (LMS). Контент общается с LMS только через один канал – программный интерфейс на JavaScript, который LMS внедряет в страницу браузера. В Rustici Software, которая ведёт справочный сайт SCORM.com, формулируют это прямо: контент не может общаться через веб-сервисы, отправку форм или запись в базу данных, только через этот интерфейс в браузере [4]. Нет интерфейса – нет трекинга. Сам стандарт разобран в статье «SCORM: что это, что отслеживает и когда применять»; здесь важно одно: учащийся, открывший SCORM-курс без связи, не создаёт записи, которую LMS когда-либо увидит. Исключение – отдельный офлайн-плеер, который эмулирует этот интерфейс локально и передаёт данные позже, но это дополнительный механизм, и есть он не в каждой LMS.
Это ограничение подтолкнуло к появлению следующего стандарта: в проекте, из которого вырос xAPI, трекинг офлайн- и длительного контента, с которым не справлялся SCORM, был отдельной задачей [4].
Как xAPI делает офлайн возможным
Experience API (xAPI) записывает учебное событие как небольшое самодостаточное утверждение – фразу по схеме «субъект – глагол – объект», например «Мария завершила модуль 3». Каждое утверждение – это небольшой фрагмент данных, поэтому приложение может полностью офлайн записать его в локальное хранилище на устройстве, накопить очередь таких утверждений и отправить её на сервер, когда связь вернётся. Сервер, который их принимает и хранит, называется Learning Record Store (LRS); считайте его журналом, куда записываются эти фразы. Персональные данные учащегося есть с обеих сторон: очередь на устройстве стоит шифровать, а LRS, куда она уходит, должен находиться в России – сбор и хранение ПДн граждан РФ в зарубежных базах запрещены (ч. 5 ст. 18 152-ФЗ) [12]. Как точно фиксировать события просмотра видео, разобрано в статье «Трекинг видео через xAPI».
Надёжной отложенную синхронизацию делают две детали спецификации xAPI. Именно они отличают точную офлайн-запись от испорченной хронологии.
Первая – разница между timestamp и stored. У каждого утверждения два времени: timestamp – когда событие на самом деле произошло, и stored – когда LRS его принял. Приложение-источник может и должно само проставлять timestamp [5]. Поэтому событие, записанное в 09:14 в автобусе без связи, сохраняет свой реальный timestamp 09:14, даже если LRS проставит stored только в 18:00, когда учащийся вернётся в сеть. Учебная запись показывает, когда человек учился, а не когда вернулась связь.
Вторая – утверждения неизменяемы и несут уникальный идентификатор. Каждое утверждение получает универсальный уникальный идентификатор (UUID), и спецификация предписывает клиенту задавать его самому. Сохранённое в LRS утверждение уже не меняется: LRS может дозаполнить поля вроде stored, но само событие не трогает [5]. На этом и держится безопасная синхронизация.
cmi5: офлайн предусмотрен изначально
cmi5 – профиль xAPI для курсов, запускаемых из LMS, – с самого начала проектировали с расчётом на небраузерные и офлайн-сценарии. В его документации прямо сказано, что контенту cmi5 не нужен браузер и он может быть мобильным приложением [6]. Запуская урок, LMS передаёт ему всё, что нужно, чтобы потом связаться с LRS: адрес LRS, данные учащегося, идентификаторы сессии и регистрации и одноразовый URL для получения токена авторизации [6]. Приложение с поддержкой офлайна получает токен, пока есть связь, затем проводит сессию без сети и синхронизируется позже.
Но с токеном есть ловушка. Токены авторизации ради безопасности намеренно делают короткоживущими, поэтому токен, полученный в понедельник, может истечь к тому моменту, когда учащийся, всё это время бывший офлайн, вернётся в сеть в четверг. Офлайн-сценарий должен предусматривать повторную аутентификацию и обновление токена при появлении связи, а не рассчитывать, что исходный токен ещё действует. Сам стандарт cmi5 разобран в статье «cmi5: мост между SCORM и xAPI».
Разрешение конфликтов при возврате связи
«Что будет, когда всё это начнёт синхронизироваться?» – именно этот вопрос отпугивает команды от офлайна. Ответ успокаивает, если разделить данные на два вида.
Первый вид – события-добавления: утверждения xAPI, которые описывают то, что произошло. Конфликтов с ними не бывает в принципе. У каждого утверждения есть заданный клиентом UUID, и оно неизменяемо, поэтому спецификация требует, чтобы LRS, получив утверждение с уже известным ему идентификатором, не менял своё состояние: он отвечает «нет содержимого» или статусом конфликта, но никогда не дублирует и не перезаписывает запись [7]. Проще говоря, если из-за нестабильного соединения приложение отправило один и тот же пакет дважды, вторая отправка ничего не испортит. Завершение нельзя засчитать дважды: дубликат распознаётся и отбрасывается. Инженерная задача сводится к тому, чтобы повторять попытки, пока LRS не подтвердит каждое утверждение.
Второй вид – изменяемое состояние: одно значение, которое меняется со временем. Это закладка для продолжения («вы остановились на 14:32»), suspend-данные, позволяющие курсу продолжиться с места остановки, или «лучший результат на данный момент». Здесь конфликт вполне возможен. Если учащийся проходит один и тот же модуль офлайн на телефоне и на планшете, оба устройства вернутся с разным «последним положением», и системе придётся выбирать. Стандарт этого не решает, решение остаётся за продуктом. Обычное правило – last-write-wins («побеждает последняя запись») по реальному timestamp: сохранить значение от события, которое произошло позже. Более аккуратный вариант – слияние (merge) там, где оно имеет смысл: брать самый дальний прогресс, а не самый свежий, чтобы учащегося никогда не откатывало назад. Главное, чего нужно избежать, – чтобы старое устройство, синхронизировавшееся с опозданием, не затёрло более свежий прогресс.
Как стандарты справляются с офлайном
| Возможность | SCORM 1.2 / 2004 | xAPI 1.0.3 | cmi5 |
|---|---|---|---|
| Офлайн-доставка контента | Пакет работает локально, но трекингу нужен интерфейс LMS | Не зависит от типа контента; работает в связке с загрузкой в приложении или PWA | Не зависит от контента; явно поддерживает мобильный и небраузерный контент [6] |
| Офлайн-трекинг | «Из коробки» нет, нужен офлайн-плеер от LMS [4] | Да: утверждения копятся на устройстве и отправляются позже [5] | Да: на базе xAPI, с заданной моделью запуска и токена [6] |
| Как синхронизируются записи | Через локальную эмуляцию JS-интерфейса, данные передаются при появлении связи | POST очереди утверждений в LRS пачками | POST пачками внутри сессии cmi5, после обновления токена |
| Защита от дублей | Зависит от плеера | Встроена: неизменяемые утверждения, дедупликация по UUID [7] | Наследует дедупликацию xAPI [7] |
| Когда выбирать для офлайна | Старые курсы, уже упакованные в SCORM | Собственные приложения, подробный и мобильный трекинг | Курсы из LMS, которые должны работать и офлайн |
Если офлайн-трекинг важен, основа – xAPI, а для курсов, запускаемых из LMS, – cmi5. В SCORM можно упаковать контент, но офлайн-запись будет зависеть от плеера, который к нему добавлен.
Пример офлайн-сценария
Возьмём приложение для обучения линейного персонала, который работает вахтой на удалённых объектах. Курс – 12 видеомодулей в 360p, в сумме около 6 ГБ. Сценарий такой.
На базе, по Wi-Fi, техник скачивает все 12 модулей (6 ГБ помещаются в память телефона), и приложение получает токен авторизации cmi5. Следующие три дня без сети он смотрит модули и сдаёт тесты. Каждое событие – launched, progressed, passed, completed – записывается как утверждение xAPI со своим реальным timestamp и новым UUID и встаёт в очередь в зашифрованной локальной базе устройства. В очереди может оказаться несколько сотен утверждений, но каждое весит намного меньше килобайта, и весь пакет занимает долю мегабайта: видео заняло 6 ГБ, а записи почти ничего не стоят.
Вернувшись в зону покрытия, приложение обновляет истёкший токен и отправляет очередь утверждений пачками через POST в LRS на российских серверах. Если соединение рвётся посреди синхронизации, приложение повторяет попытку; утверждения, которые уже дошли, распознаются по UUID и отбрасываются, так что ничего не засчитывается дважды [7]. Дашборд показывает три дня обучения в те дни, когда оно действительно было, хотя на сервер все записи пришли одной пачкой в четверг в 16:00.
Одна деталь меняет проектирование, если курс входит в обучение по охране труда и тест в приложении служит проверкой знаний. На внесение её результатов в реестр обученных лиц отводится три рабочих дня [11]: тест, сданный в понедельник и синхронизированный в четверг, почти не оставляет работодателю запаса. Значит, либо проверку знаний назначают на время, когда связь есть, либо ограничивают для неё офлайн-окно, а приложение показывает учащемуся, что результат ещё не отправлен.
Частые ошибки
Эти сбои всплывают в первый же раз, когда реальный учащийся оказывается без сети.
Считать, что SCORM работает офлайн. Сам по себе – нет: нет интерфейса LMS, нет и записи [4]. Если офлайн важен, стройте трекинг на xAPI или cmi5 либо добавьте полноценный офлайн-плеер.
Не задавать идентификатор утверждения на клиенте. Дедупликация, благодаря которой повторная отправка безопасна, работает, только если клиент присваивает UUID каждому утверждению до отправки [5][7]. Если идентификаторы присваивает сервер, повторная синхронизация превратится в двойное завершение.
Дать токену авторизации истечь. Токен, полученный перед многодневным офлайн-окном, к возвращению связи, скорее всего, истечёт. Заложите обновление токена и повторную аутентификацию, иначе синхронизация молча сорвётся [6].
Last-write-wins, который затирает прогресс. Если сверять изменяемое состояние по «самой поздней синхронизации», а не по «самому дальнему прогрессу», учащегося может откатить назад. Выбирайте правило слияния осознанно.
DRM-лицензии, которые истекают раньше, чем вернётся связь. Если постоянная офлайн-лицензия короче периода без связи, скачанное видео заблокируется. Сопоставьте срок лицензии с реальной длительностью офлайна.
Офлайн-окно длиннее регуляторного срока. Если результат нужен для реестра обученных по охране труда, синхронизация «когда-нибудь» не годится: срок внесения считается в рабочих днях [11].
Забыть про доступность в офлайн-пакете. Субтитры и транскрипты весят несколько килобайт и должны входить в скачиваемый пакет: требования WCAG 2.1 AA к субтитрам, на которых построен ГОСТ Р 52872-2019, действуют и без сети [8]. Подробнее – в статье «Субтитры, транскрипты и аудиоописание».
Неограниченное локальное хранилище. Кнопка «скачать всё» без ограничения объёма забивает память, и приложение удаляют. Предлагайте варианты качества и показывайте объём до загрузки.
Где здесь Фора Софт
Фора Софт с 2005 года разрабатывает ПО для видеостриминга, связи в реальном времени и мобильного обучения. В офлайн-обучении сложность редко в самой загрузке; сложнее всего трекинг и сверка, которые доказывают, что учащийся без связи действительно прошёл курс. Готовая LMS может дать базовую кнопку «скачать для офлайна», но при этом незаметно терять записи, сделанные без сети. Заказная разработка позволяет самим управлять очередью утверждений xAPI, обновлением токена и правилами разрешения конфликтов для изменяемого состояния, но этот механизм нужно правильно построить. Мы помогаем командам понять, сколько офлайн-возможностей реально нужно их аудитории, а затем строим слой доставки и синхронизации так, чтобы вахтовик после трёх дней без сети вернулся с сохранённым прогрессом. Тот же опыт офлайн-синхронизации, связи в реальном времени и мобильной доставки мы применяем в продуктах для видеоконференций, телемедицины и OTT.
Главное
- Офлайн – это две задачи: доставить контент на устройство и вернуть записи на сервер.
- SCORM нужна постоянная связь с LMS; xAPI создавали в том числе ради офлайн-трекинга.
- У утверждений xAPI есть реальный timestamp и UUID, поэтому синхронизация сохраняет верную хронологию.
- События-добавления дедуплицируются по UUID: повторная отправка безопасна.
- Изменяемому состоянию (закладка, прогресс) нужно правило: last-write-wins или слияние.
- cmi5 – удобная для офлайна обёртка для курсов из LMS; следите за истечением токена.
- LRS – в России; для охраны труда офлайн-окно должно укладываться в срок внесения в реестр.