Разработка LMS с поддержкой SCORM 1.2 и 2004

Поддержка SCORM в LMS

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Разработка LMS с поддержкой SCORM 1.2 и 2004
Сложный
от 2 недель до 3 месяцев

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1422
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1287
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    984
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1250
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    986
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    1000

Поддержка SCORM в LMS

Представьте: вы купили дорогой курс в Articulate Storyline, а ваша LMS отказывается его загружать — ошибка "неверный формат" или курс запускается, но прогресс не сохраняется. Клиент не может пройти обучение, а техподдержка вендора винит стандарт. Такая ситуация — типичная цена отсутствия грамотной поддержки SCORM. Мы, как команда с опытом более десяти лет в e-learning, решили эту проблему десятки раз. Наш подход — не костыль в iframe, а встроенная поддержка SCORM 1.2 и 2004 на уровне архитектуры. SCORM — это стандарт обмена учебными курсами, и его корректная реализация критична для любой современной LMS.

Проблемы, которые мы решаем

Несовместимость версий. SCORM 1.2 использует объект API, 2004 — API_1484_11. Если ваша LMS завязывается только на одну версию, половина курсов отвалится. Потеря suspend_data. При перезагрузке страницы прогресс студента пропадает. Утечки памяти в iframe. После закрытия курса API-объект может остаться в памяти. Мы решаем все три проблемы: динамически определяем версию пакета, дросселируем сохранения с хранением suspend_data в JSONB PostgreSQL и освобождаем API при размонтировании.

Как работает SCORM API?

SCORM-курс общается с LMS через JavaScript API. LMS создаёт глобальный объект API (SCORM 1.2) или API_1484_11 (SCORM 2004) в окне, где запущен iframe. Вот базовая реализация на TypeScript:

class ScormApi12 { private lessonStatus = 'not attempted'; private suspendData = ''; private score = 0; private sessionTime = ''; private dataStore = new Map<string, string>(); private onComplete: (data: ScormData) => void; constructor(onComplete: (data: ScormData) => void) { this.onComplete = onComplete; } LMSInitialize(_: string): string { this.lessonStatus = 'incomplete'; return 'true'; } LMSGetValue(element: string): string { switch (element) { case 'cmi.core.lesson_status': return this.lessonStatus; case 'cmi.suspend_data': return this.suspendData; case 'cmi.core.score.raw': return String(this.score); case 'cmi.core.lesson_location': return this.dataStore.get('lesson_location') ?? ''; default: return this.dataStore.get(element) ?? ''; } } LMSSetValue(element: string, value: string): string { switch (element) { case 'cmi.core.lesson_status': this.lessonStatus = value; break; case 'cmi.suspend_data': this.suspendData = value; break; case 'cmi.core.score.raw': this.score = Number(value); break; case 'cmi.core.session_time': this.sessionTime = value; break; default: this.dataStore.set(element, value); } return 'true'; } LMSCommit(_: string): string { this.saveProgress(); return 'true'; } LMSFinish(_: string): string { this.onComplete({ status: this.lessonStatus, score: this.score, suspendData: this.suspendData, sessionTime: this.sessionTime, }); return 'true'; } LMSGetLastError(): string { return '0'; } LMSGetErrorString(_: string): string { return 'No error'; } LMSGetDiagnostic(_: string): string { return ''; } private async saveProgress() { await fetch('/api/scorm/progress', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ status: this.lessonStatus, score: this.score, suspendData: this.suspendData, }), }); } } 

Как инжектировать API в iframe?

Курс ищет API в родительском окне. LMS устанавливает объект до загрузки iframe и удаляет его при размонтировании:

function ScormPlayer({ courseId, enrollmentId }) { const iframeRef = useRef<HTMLIFrameElement>(null); useEffect(() => { const api = new ScormApi12(async (data) => { await fetch(`/api/enrollments/${enrollmentId}/complete`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data), }); }); (window as any).API = api; (window as any).API_1484_11 = api; return () => { delete (window as any).API; delete (window as any).API_1484_11; }; }, [enrollmentId]); return ( <iframe ref={iframeRef} src={`/api/courses/${courseId}/launch`} className="w-full border-0" style={{ height: 'calc(100vh - 64px)' }} allow="camera; microphone; fullscreen" title="SCORM Course" /> ); } 

Загрузка и распаковка SCORM-пакета

Серверная часть на Node.js с библиотекой adm-zip и xml2js:

import AdmZip from 'adm-zip'; import { parseStringPromise } from 'xml2js'; app.post('/api/courses/upload', authenticate, upload.single('scorm'), async (req, res) => { const zipBuffer = req.file!.buffer; const zip = new AdmZip(zipBuffer); const courseId = crypto.randomUUID(); const extractPath = `/courses/${courseId}`; zip.extractAllTo(path.join(process.env.STORAGE_PATH!, extractPath), true); const manifestEntry = zip.getEntry('imsmanifest.xml'); if (!manifestEntry) throw new Error('Invalid SCORM package: no imsmanifest.xml'); const manifest = await parseStringPromise(manifestEntry.getData().toString()); const title = manifest.manifest.organizations[0].organization[0].title[0]; const launchUrl = manifest.manifest.resources[0].resource[0]['$']['href']; const scormVersion = manifest.manifest['$']['version']?.includes('1.2') ? '1.2' : '2004'; const course = await db.courses.create({ id: courseId, title, launchUrl: `${extractPath}/${launchUrl}`, scormVersion, uploadedBy: req.user.id, }); res.json(course); }); 

Хранение прогресса

Используем PostgreSQL с JSONB для suspend_data и индексом по enrollment_id:

CREATE TABLE scorm_progress ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), enrollment_id UUID REFERENCES enrollments(id), lesson_status VARCHAR(50), score NUMERIC(5,2), suspend_data JSONB, session_time INTERVAL, completed_at TIMESTAMPTZ, updated_at TIMESTAMPTZ DEFAULT now() ); CREATE INDEX idx_enrollment ON scorm_progress(enrollment_id); 

Почему SCORM 1.2 всё ещё актуален?

Несмотря на выход SCORM 2004 много лет назад, 80% коммерческих пакетов до сих пор делают под SCORM 1.2 — он проще и шире поддерживается. Мы поддерживаем обе версии, автоматически определяя версию из манифеста.

Параметр SCORM 1.2 SCORM 2004
API объект window.API window.API_1484_11
Статусы passed/failed/completed/incomplete + not attempted/unknown
Оценка 0–100 0.0–1.0 с min/max/raw
Прогресс suspend_data suspend_data + adl.nav
Распространённость ~80% курсов ~20%

Наш опыт и преимущества

Мы — команда из 15 человек с опытом более десяти лет в веб-разработке. Успешно реализовали более 50 LMS-проектов, включая интеграцию SCORM для банков, ритейла и EdTech. Наши решения выдерживают свыше 10 000 одновременных сессий. Гарантируем совместимость с Articulate Storyline, Adobe Captivate, iSpring — тестируем на трёх популярных пакетах. Экономия времени на разработку с нуля может достигать 70%, а стоимость интеграции обычно окупается за несколько месяцев.

Сравнение с альтернативами: готовые LMS (например, Moodle) поддерживают SCORM из коробки, но их API сложен для кастомизации, а производительность под высокой нагрузкой часто страдает. Наше решение на 40% быстрее обрабатывает запуск курсов и позволяет гибко менять логику хранения прогресса.

Процесс работы

  1. Аналитика — встреча с командой, разбор требований: какие SCORM-пакеты будут загружаться, нужны ли кастомные статусы.
  2. Проектирование — архитектура модуля: диаграмма потоков, выбор хранилища, схема API.
  3. Реализация — написание API-объекта, обработчика загрузки, бэкенда прогресса.
  4. Тестирование — юнит-тесты на моках, интеграционные тесты с реальными пакетами (Articulate, iSpring).
  5. Деплой — настройка окружения, CI/CD, мониторинг.

Что входит в работу?

  • Исходный код модуля SCORM (API, загрузчик, прогресс).
  • Документация по API для интеграции стороннего контента.
  • Инструкция для администратора по загрузке и управлению курсами.
  • Гарантия совместимости с Articulate Storyline, Adobe Captivate, iSpring.
  • Обучение team lead и техническая поддержка 1 месяц после сдачи.

Сроки и стоимость

Сроки — от 7 рабочих дней (SCORM 1.2) до 14 дней (SCORM 1.2 + 2004). Стоимость рассчитывается индивидуально — зависит от сложности кастомизации (например, нестандартные статусы или требования к suspend_data). Свяжитесь с нами — оценим ваш проект бесплатно.

Этап Длительность Результат
Базовая интеграция SCORM 1.2 7 дней Работающий модуль с API и прогрессом
Полная интеграция (1.2 + 2004) 14 дней Поддержка обеих версий, тестирование на 3 пакетах

Закажите разработку модуля SCORM — получите быструю и надёжную интеграцию, адаптированную под ваш бизнес.