Engineering · 2026-06-22

SCORM, xAPI, and caption delivery tracking: how to verify caption completion in an LRS and why SCORM 1.2 breaks caption sidecar delivery

L&D compliance audits routinely miss a category of caption failures that video-sidecar workflows cannot detect: captions that are absent, broken, or untestable inside SCORM packages. The gap exists because SCORM 1.2 — still the most widely deployed eLearning packaging standard — has no mechanism for delivering captions as a sidecar file. Captions in a SCORM 1.2 package must be baked into the published HTML5 output before the ZIP is uploaded to the LMS. If the course author did not configure captions before publishing, no post-upload LMS action can add them. The LMS sees a SCORM package as a sealed unit.

SCORM 2004 extends the content packaging specification with additional resource type declarations in the manifest but adds no caption-specific data model. xAPI (Tin Can API) provides a framework for tracking learner activity but defines no standard caption Statement recipe — organisations that want to record whether a learner enabled captions or whether a learner's caption track was functional must build a custom recipe and implement it in both the SCORM/xAPI content and the LRS. cmi5 comes closest to supporting accessibility feature state in its launch mechanism, but caption delivery remains outside its data model.

This guide covers what each standard actually allows, how to implement xAPI caption usage tracking with a verifiable Statement recipe, how to audit SCORM caption delivery across a large L&D library, eight failure modes that produce uncaptioned learners in SCORM-packaged content, and a seven-question FAQ for L&D engineering teams and accessibility coordinators managing SCORM-heavy libraries.

TL;DR — four things every L&D engineer should know about SCORM and caption delivery

  1. SCORM 1.2 has no sidecar caption mechanism. Captions must be embedded in the published output before LMS upload. The LMS cannot add or modify caption content after the package is uploaded.
  2. SCORM 2004 does not solve the problem. The extended manifest allows additional resource declarations but provides no caption delivery or tracking standard.
  3. xAPI requires a custom Statement recipe to track caption usage. No published xAPI profile defines a standard caption Statement. Implementation requires a custom verb, custom extension, and coordination between the eLearning content and the LRS.
  4. The only reliable caption verification for SCORM content is pre-deployment testing in the target LMS, not LRS query. SCORM packages that pass caption testing in Articulate Review 360 or SCORM Cloud can still fail in a specific LMS due to iframe restrictions, JavaScript conflicts, or LMS SCORM player rendering differences.

SCORM 1.2: why there is no sidecar caption mechanism

SCORM 1.2 was finalised by ADL (Advanced Distributed Learning) in 2001 based on the IMS Content Packaging 1.1.3 specification and the AICC CBT standard. Its data model covers learner status (passed, failed, completed, incomplete), score, suspend data for resuming partial completion, session time, learner name and ID, and a handful of interaction tracking fields for multiple-choice and true/false questions. Accessibility feature delivery — captioning, audio description, keyboard navigation state — is entirely outside the data model.

A SCORM 1.2 package is a ZIP file containing:

When a learner launches a SCORM 1.2 course, the LMS opens the SCO entry point (the HTML file designated in the manifest) inside an iframe. The SCO communicates with the LMS through the SCORM API (a JavaScript API injected by the LMS into the parent frame), using calls like LMSInitialize, LMSGetValue, LMSSetValue, and LMSFinish. The SCORM 1.2 API has no field for caption state, no mechanism to deliver a separate caption file to the SCO, and no method by which the LMS can inject caption data into an already-uploaded package.

Why the LMS cannot add captions to an uploaded SCORM 1.2 package

Every LMS platform that supports video assets — Cornerstone OnDemand, Workday Learning, TalentLMS, Docebo, Kaltura, Absorb — can add caption tracks to video assets stored in its media library. The caption track is stored separately from the video file, associated by the LMS's data model, and delivered to the player at playback time. This is the sidecar model, and it works well for video library content.

SCORM content operates differently. When the SCORM package is uploaded, the LMS extracts the ZIP and stores the content files on its server. The SCORM player renders the HTML entry point in an iframe. The LMS does not process the semantic content of the SCORM package — it does not know which elements inside the SCO are videos, which are audio tracks, or what caption configuration the authoring tool embedded. It cannot identify the narration assets inside the SCO and attach caption tracks to them after the fact.

The practical consequence: if a Storyline 360 course was published without the Notes panel CC configured, or if a Captivate course was published without the SRT import step completed, or if a Rise course was published with direct MP4 upload instead of a video host with captions — the course reaches the LMS with no captions, and no post-upload action by the LMS administrator can add them. The course must be recaptioned in the authoring tool, republished, and re-uploaded as a new SCORM package. For organisations with large SCORM libraries, this means retroactive captioning is an authoring-tool workflow problem, not an LMS workflow problem.

The eLearning authoring tool caption guide covers the correct workflow for each authoring tool in detail. The key implication for this guide: every SCORM 1.2 package in an LMS library was either captioned at publish time or it was not, and there is no mechanism in SCORM 1.2 to determine which from the LMS data layer alone.

How captions actually work inside a SCORM 1.2 package

Caption delivery inside a SCORM 1.2 package is a function of the authoring tool's HTML5 rendering engine, not of the SCORM standard itself. There are three architectures in common use:

Architecture 1: Inline caption text in the HTML5 output (Articulate Storyline built-in CC). Storyline generates a caption track from the Notes panel text and synchronises it to the narration timeline at publish time. The caption text is rendered as DOM elements inside the HTML5 output — text that is positioned over the slide at the appropriate timestamp. When the SCORM package is uploaded to the LMS, the HTML5 output (including the caption DOM elements) is served as-is. The LMS has no way to distinguish the caption elements from any other HTML elements in the SCO output. From the LMS's perspective, captions are just more HTML content in the iframe.

Architecture 2: Embedded track element in video assets (Captivate, Lectora, iSpring with SRT import). When an SRT file is imported into Captivate or Lectora before publishing, the authoring tool embeds the caption data into the video asset's HTML5 player code. The published SCORM package contains the narration video with an HTML5 <track> element referencing a WebVTT file that is also bundled in the ZIP. The LMS serves all these files together; the browser's HTML5 video player handles caption rendering. This is structurally cleaner than inline text but still entirely invisible to the SCORM API — the LMS SCORM runtime knows nothing about the presence or absence of the <track> element.

Architecture 3: Video host captions (Articulate Rise with Vimeo/Wistia). Rise video blocks that embed from a video host (Vimeo, Wistia, YouTube) inherit the caption configuration from the video host. The SCORM package contains an iframe that loads the video host's player; caption tracks are served by the video host's CDN. This architecture is dependent on both the video host configuration and network connectivity at runtime — learners in restricted network environments who cannot reach the video host CDN will get the Rise course without captions. The SCORM package itself has no caption assets; all caption delivery is external to the package.

In all three architectures, the SCORM 1.2 API has no visibility into caption state. Whether captions are on, off, broken, or absent — the SCORM runtime data model captures none of it.

SCORM 2004: the manifest extension that doesn't solve caption delivery

SCORM 2004 (released in three editions: 1st Edition 2004, 2nd Edition 2004, 3rd Edition 2006, 4th Edition 2009) substantially extends the SCORM 1.2 data model and introduces the Sequencing and Navigation specification. Its IMS CP 1.1.4-based content packaging allows a richer manifest structure with more granular resource typing. It does not add a caption delivery mechanism.

What the manifest extension adds

The SCORM 2004 manifest allows resource types beyond the single SCO type of SCORM 1.2. A SCORM 2004 manifest can declare:

The expanded asset resource type could theoretically be used to declare a separate caption file (an SRT or VTT) as an asset resource referenced by the SCO. The SCO's HTML5 code would then load the caption file from the package's resource path at runtime. This is technically valid SCORM 2004 — the manifest would declare the VTT file as an asset resource, the SCO's HTML5 player code would reference it with a relative path, and the SCORM package would contain both the video asset and the caption file as first-class manifest entries.

In practice, no major authoring tool implements this pattern. Articulate Storyline 360 and Rise 360 publish to SCORM 2004 using the same caption embedding architecture as their SCORM 1.2 output — inline Notes CC text for Storyline, embedded track elements or video host iframes for Rise. Captivate, Lectora, and iSpring bundle caption assets with the package but reference them through their own player code rather than through SCORM 2004 manifest dependency declarations.

What the SCORM 2004 data model adds for accessibility

SCORM 2004 4th Edition extended the CMI data model to include cmi.learner_preference.* elements, which are intended to capture learner accessibility preferences. The relevant fields are:

cmi.learner_preference.audio_captioning is the closest thing SCORM 2004 provides to a caption preference field. It allows the SCO to read the learner's stated captioning preference from the LMS and adjust its caption display accordingly. The LMS sets this value based on the learner's accessibility profile, if one is configured. The SCO reads it at initialisation via GetValue("cmi.learner_preference.audio_captioning") and can use the result to auto-enable or auto-disable captions.

Two significant limitations: First, very few LMS platforms actually configure learner accessibility profiles that populate cmi.learner_preference.audio_captioning. The field is widely ignored in LMS implementation. Second, even when the field is populated, it records a preference, not a delivery confirmation. A learner with audio_captioning = 1 (captions on) who encounters a SCORM package with no caption data will have their preference recorded while receiving no captions. The field cannot verify that captions were available or functional.

SCORM 2004 sequencing and caption continuity

SCORM 2004's Sequencing and Navigation specification allows multi-SCO courses with branching logic. This introduces a caption continuity concern that does not exist in single-SCO SCORM 1.2 content: if each SCO in a sequenced course is a separate HTML5 launch point, captions must be independently configured in each SCO. A learner who enables captions in SCO 1 does not automatically have captions enabled in SCO 2 — the SCO 2 launch context is fresh, and caption preference state from cmi.learner_preference.audio_captioning must be re-read and applied at each SCO initialisation.

In practice, most authoring tools handle this through their own session persistence rather than through the SCORM data model. Storyline stores the learner's CC preference in cmi.suspend_data (the opaque blob used for course state persistence) and restores it on SCO resume. This is authoring-tool-specific behaviour — it cannot be verified from the LMS side without parsing the suspend data blob, which is opaque by design.

xAPI caption tracking: building a verifiable Statement recipe

xAPI (Experience API, also called Tin Can API) was developed by ADL as a replacement for the SCORM API model. Instead of a synchronous JavaScript API between the SCO and the LMS, xAPI uses HTTP calls from any learning experience to a Learning Record Store (LRS). Statements are JSON documents containing an actor, verb, and object — the fundamental unit of xAPI activity reporting.

xAPI does not define a standard caption Statement. The xAPI specification itself is intentionally minimal and extensible; verb definitions are provided by community profiles hosted in the xAPI Registry. As of June 2026, no published xAPI profile includes a standard verb for "enabled captions," "disabled captions," or "caption track unavailable." Caption usage tracking via xAPI requires a custom recipe.

The xAPI Statement structure for caption tracking

A minimal xAPI Statement for caption usage has three required components and is extended with context data to make it useful for compliance verification:

{
  "actor": {
    "objectType": "Agent",
    "name": "Learner Name",
    "mbox": "mailto:learner@example.com"
  },
  "verb": {
    "id": "https://glosscap.com/xapi/verbs/enabled-captions",
    "display": { "en-US": "enabled captions" }
  },
  "object": {
    "objectType": "Activity",
    "id": "https://lms.example.com/courses/course-123/module-2",
    "definition": {
      "type": "http://adlnet.gov/expapi/activities/module",
      "name": { "en-US": "Module 2: Onboarding Overview" }
    }
  },
  "context": {
    "registration": "uuid-for-this-attempt",
    "extensions": {
      "https://glosscap.com/xapi/extensions/caption-track-id": "en-US",
      "https://glosscap.com/xapi/extensions/caption-track-available": true,
      "https://glosscap.com/xapi/extensions/caption-delivery-method": "embedded-vtt",
      "https://glosscap.com/xapi/extensions/player-type": "storyline-html5",
      "https://glosscap.com/xapi/extensions/scorm-version": "1.2"
    }
  },
  "timestamp": "2026-06-22T10:23:14Z"
}

Verbs required for a complete caption usage recipe

A minimal but useful caption tracking recipe requires at least four verbs:

Some organisations also implement a caption-autostart verb to record cases where captions were enabled automatically at launch (from a learner preference profile, from cmi.learner_preference.audio_captioning = 1, or from an OS-level accessibility setting). Autostart tracking distinguishes passive accessibility delivery from active learner choice — a distinction that may matter for accommodation verification.

Where the Statement must be sent from

xAPI Statements for caption usage must be sent from inside the SCO — the HTML5 content running in the LMS iframe. This requires the SCO's JavaScript code to:

  1. Include an xAPI client library (ADL xAPIWrapper, or a lightweight fetch wrapper).
  2. Have the LRS endpoint URL, auth credentials, and the actor identification method (mbox, account, openid) available at runtime.
  3. Attach event listeners to the CC button click event and the caption track load event.
  4. Send the appropriate Statement to the LRS when each event fires.

This is not trivial to retrofit into existing SCORM 1.2 content. Articulate Storyline 360 allows custom JavaScript via the Execute JavaScript trigger, which can send xAPI Statements from inside the published SCORM package. Captivate allows JavaScript via Advanced Actions. Lectora supports JavaScript execution natively. But retrofitting caption tracking into existing published SCORM packages requires access to the original source files — the authoring tool project file (.story, .cptx, .lectora), not the published SCORM ZIP.

For organisations using a purpose-built caption API like GlossCap's, the xAPI Statement can alternatively be generated server-side when caption asset delivery is confirmed — for example, when the SRT/VTT retrieval and LMS delivery pipeline documented in the caption API automation guide confirms a successful delivery. This approach generates a Statement recording that a caption asset was delivered, which is not the same as recording that the learner enabled captions, but it is sufficient for coverage auditing at scale.

LRS configuration for caption statement queries

Once caption Statements are arriving in the LRS, the verification workflow requires LRS queries against the Statement data. The xAPI specification defines a REST API for Statement retrieval. Key query parameters for caption compliance verification:

Most enterprise LRS platforms (SCORM Cloud LRS, Learning Locker, Watershed, Veracity Learning, LRS.io) support Statement query via the GET /statements endpoint with these parameters. Some require pagination through large result sets using the more URL property in the response.

cmi5: the closest thing to accessibility-aware launch

cmi5 is a specification published by the Aviation Industry CBT Committee (AICC) in 2016 and adopted by ADL as the recommended profile for xAPI-based learning content. cmi5 defines a standard launch mechanism, a set of required and optional xAPI Statements (called the "cmi5 defined Statements"), and a Course Structure File (a JSON or XML document that describes the course structure and launch parameters). It is the most structured xAPI deployment approach available and is gaining adoption in newer LMS platforms alongside the legacy SCORM 1.2 and SCORM 2004 formats.

cmi5 launch parameters and accessibility

The cmi5 launch mechanism passes parameters to the content via URL query string at launch time. The required parameters include the LRS endpoint, an authorisation token, the actor identification, the activity ID, and a registration identifier. The specification allows additional custom parameters via the Course Structure File's launchParameters property.

The launchParameters property is a freeform string — it can contain anything the content publisher wants. An organisation implementing cmi5 content can include an accessibility parameter in launchParameters, for example:

"launchParameters": "captionsRequired=true&captionLanguage=en-US&audiodescription=false"

The cmi5 content receives this string at launch, parses it, and enables captions automatically. This is the closest the current eLearning standards ecosystem comes to a standards-based accessibility feature launch mechanism — and it is not a standards-based mechanism. It is a freeform string passed through a standard launch channel. Its interpretation is entirely up to the content publisher and the LRS consumer.

cmi5 defined Statements and caption tracking

cmi5 defines nine Statement templates that all conforming content must (or may) send: initialized, completed, passed, failed, abandoned, waived, terminated, and satisfied (from the ADL cmi5 specification Version 1.0 Annex B). None of these templates addresses caption usage.

cmi5 does not restrict custom Statements — content can send additional xAPI Statements beyond the defined templates, including caption tracking Statements using the custom recipe described in the previous section. The constraint is that cmi5 defined Statements (initialized, completed, etc.) must conform to their template exactly, but supplementary Statements for caption tracking are unrestricted.

The practical implication: a cmi5-conforming course can both report standard completion data to the LRS and send caption usage Statements using a custom recipe. This is the recommended implementation for organisations that are transitioning from SCORM to cmi5 and want caption tracking alongside completion tracking.

LMS support for cmi5

cmi5 adoption in enterprise LMS platforms is uneven. As of mid-2026:

Organisations on SCORM 1.2 at scale should not plan a cmi5 migration primarily to solve the caption tracking problem. The authoring tool recaptioning and republishing workflow for SCORM 1.2 content — documented in the authoring tool caption guide — is the correct remediation path for existing uncaptioned SCORM packages. cmi5 migration may be worth planning for net-new content when both completion tracking and accessibility tracking are requirements, but it is a content publishing decision, not a caption delivery shortcut.

LRS verification: what you can and cannot confirm from query data

Once a caption tracking recipe is implemented and Statements are arriving in the LRS, it is important to be precise about what the LRS data can and cannot confirm for compliance purposes.

What LRS caption data can confirm

What LRS caption data cannot confirm

The verification gap that LRS data cannot close

The fundamental limitation of LRS-based caption verification is that it is learner-event-triggered. The LRS only knows what the SCO reports. An uninstrumented SCO — which includes all legacy SCORM content published before caption tracking was added to the authoring workflow — generates no caption Statements at all. The LRS query for caption track unavailability returns zero results, which is falsely reassuring: it means no one reported a failure, not that no failures occurred.

This is the same structural verification gap that exists in WCAG automated scanning tools: a scanner can detect the absence of a <track> element on a video, but it cannot detect a <track> element that points to a malformed VTT file or a VTT file with subtitles rather than captions. The enterprise LMS caption audit methodology covers the full seven-dimension framework including LMS delivery verification — the xAPI LRS layer is one dimension, not a substitute for the others.

Audit methodology: verifying caption delivery across a SCORM library

Given the limitations of the SCORM API and LRS data, verifying caption delivery across a large SCORM library requires a layered methodology that combines package inspection, authoring tool record review, LMS player testing, and (where implemented) LRS query.

Step 1: Inventory your SCORM library by authoring tool and version

The first question for each SCORM package in the library is: which authoring tool produced it, and what version? Caption delivery capability is a function of the authoring tool and version, not of the SCORM standard version. A Storyline 360 package published in 2019 may have used an older version of the Notes CC feature; a Storyline 360 package published in 2024 with the same feature has different rendering behaviour in some LMS players. A Captivate package depends on whether the SRT import step was completed before publishing.

For each SCORM package, record:

This inventory is typically available from the LMS course administration interface (last upload date) and from the authoring tool project records (tool version, caption configuration). For older packages where project files are unavailable, inspect the imsmanifest.xml in the SCORM ZIP directly — the manifest often contains authoring tool metadata in the <metadata> element or as schema attributes on the <manifest> element.

Step 2: Inspect the SCORM package structure for caption assets

For each package in the library, extract the ZIP and inspect its contents. The presence of caption-related files is a direct indicator of caption architecture:

This inspection can be automated for large libraries. A Python script that iterates over SCORM ZIPs, extracts them to temporary directories, and checks for caption asset presence can process hundreds of packages per hour. The script output is a per-package caption status: present, absent, or inconclusive (requires manual review).

Step 3: Test caption rendering in the target LMS

Package inspection confirms that caption data was included at publish time. LMS player testing confirms that captions render correctly when a learner launches the course in the actual LMS. These are distinct: a SCORM package that contains caption assets may still fail to render captions in a specific LMS due to:

For each SCORM package, the minimum LMS test is: launch the course as a learner, click the CC button, verify that caption text appears and advances with the narration, verify at least two timestamps (early in the content and mid-content) that the caption text matches the narration. Test in the browsers and operating systems that your learner population uses — caption rendering differences between Chrome, Safari, Firefox, and Edge on the same SCORM package are common.

Step 4: Query the LRS for caption-track-unavailable Statements (if implemented)

If the custom xAPI caption tracking recipe is implemented in the SCORM packages, query the LRS for caption-track-unavailable and caption-track-error Statements since the last audit. Any results represent confirmed captioning failures — specific packages, specific learners, specific timestamps. These results should drive remediation prioritisation: recaption the authoring tool source, republish, re-upload.

If the xAPI recipe is not yet implemented, the LRS query step yields no useful data. Do not interpret the absence of failure Statements as confirmation that no failures occurred.

Step 5: Cross-reference with the LMS migration caption checklist post-migration

SCORM caption failures are significantly more common immediately after an LMS migration. The migration checklist documents the full pre-cutover audit and post-migration validation protocol for caption data. For SCORM-specific content, the post-migration validation should include package re-download from the new LMS (to confirm the SCORM ZIP was stored intact), CC rendering test in the new LMS player, and LRS query for any caption-track-error Statements that emerged in the first 48 hours of production traffic on the new platform.

LMS-specific SCORM caption behaviour

Each LMS platform's SCORM player has specific behaviour that affects caption delivery. The following notes cover the platforms most commonly used with SCORM-heavy L&D libraries.

Cornerstone OnDemand

Cornerstone's SCORM player renders content in a pop-up window or inline panel depending on player configuration. The pop-up window mode can crop SCO content if the pop-up dimensions are smaller than the SCO's designed output dimensions — CC buttons positioned at the bottom of a Storyline output may be below the visible area of a small pop-up window. Configure Cornerstone's SCORM player dimensions to match the SCO's published output dimensions (typically 720×540 or 1280×720 for Storyline 360 output).

Cornerstone's xAPI (XAPI content type) integration supports Statement receipt from cmi5 and custom xAPI content. Organisations implementing xAPI caption tracking can use Cornerstone's LRS integration to receive caption Statements. The Cornerstone LRS is accessible via the standard xAPI endpoint for query. For details on Cornerstone's caption delivery for video assets (not SCORM), see the Cornerstone OnDemand captions page.

Workday Learning

Workday Learning renders SCORM content in an iframe embedded in the Workday interface. The iframe environment uses Workday's Content Security Policy headers, which may restrict JavaScript execution from within SCORM packages — particularly fetch() calls to external LRS endpoints from inside the iframe. Test xAPI Statement delivery from Storyline's Execute JavaScript trigger inside Workday's iframe before deploying caption tracking at scale. If CSP headers block outbound fetch() calls from the SCORM iframe, Statement delivery requires a proxy endpoint within Workday's allowed origin list.

Workday's native caption support for video assets (SCORM-wrapped videos notwithstanding) is documented on the Workday Learning captions page. For SCORM-packaged video, caption delivery is entirely the responsibility of the SCORM package content, not Workday.

Kaltura with SCORM

Kaltura is primarily a video asset management platform; its SCORM delivery is typically handled through a paired LMS (Moodle, Canvas, Blackboard, or an enterprise LMS with Kaltura integration). SCORM packages hosted in a Kaltura-integrated LMS environment follow the paired LMS's SCORM player behaviour. Kaltura's native caption system (caption_captionasset API) applies to Kaltura-hosted video assets, not to SCORM package contents. A Storyline course embedded in a Kaltura-powered LMS player environment still delivers captions through the Storyline HTML5 output, not through Kaltura's caption infrastructure.

The xAPI/LRS integration for Kaltura is relevant when using the Kaltura MediaSpace xAPI plugin, which sends xAPI Statements for video playback events including caption track engagement on Kaltura-hosted videos. This integration does not extend to SCORM package content. For Kaltura's caption architecture on video assets, see the Kaltura captions page.

TalentLMS

TalentLMS renders SCORM content in an iframe with a configurable player window size. TalentLMS's SCORM player has historically had issues with some Storyline 360 outputs where the CC button is rendered in the Storyline player chrome but outside the iframe's visible area at smaller player window sizes. The correct fix is to set the TalentLMS course player to the SCO's designed output dimensions rather than using TalentLMS's automatic sizing. TalentLMS xAPI integration (via its xAPI block) supports Statement receipt from xAPI-enabled content.

Docebo

Docebo's SCORM player renders content in a modal or embedded panel. Caption delivery within SCORM packages follows the same rules as other LMS platforms. Docebo's xAPI integration supports Statement receipt and query through its LRS module. The Docebo LRS is accessible via standard xAPI endpoint. Caption tracking Statements sent from SCORM content via Docebo's iframe environment follow the same CSP considerations as Workday — test fetch() from inside the Docebo SCORM iframe before production deployment.

The LMS caption ingestion workflow engineering guide covers Docebo's video caption API in detail. For SCORM content, caption delivery is independent of Docebo's video caption infrastructure.

Eight failure modes in SCORM caption delivery and xAPI tracking

1. The publish-without-CC failure: the most common and the hardest to detect

An L&D team that captions its video library correctly often has a separate SCORM authoring workflow that was never integrated with the caption process. Storyline courses are published by instructional designers who are not part of the caption workflow; the Notes CC step is skipped because no one told the instructional designer it was required; the SCORM package is uploaded and deployed without captions. The absence of captions is invisible from the LMS administration interface — the course shows as uploaded and available. Discovery requires either a learner complaint, a targeted audit, or a pre-deployment caption check step in the authoring workflow. Fix: integrate CC verification into the SCORM package approval and upload workflow. Before any SCORM package is uploaded to the LMS, it must pass a CC-present check and a CC-rendering test in a staging LMS environment.

2. The script-deviance failure: Notes CC text that doesn't match the narration

Storyline's built-in CC derives from the Notes panel text. When a narrator deviates from the approved script — adding asides, rephrasing sentences, or skipping a section — the Notes CC text does not match the narration audio. The technical precision of WCAG SC 1.2.2 requires captions that accurately represent the audio, including all narration. Script-deviance failures are common in courses that use live narration recorded outside a studio setting, where the narrator follows the script loosely. Fix: after live narration recording, run the audio through a captioning service (not the Notes CC), verify the caption output against the audio, and update the Notes text to match before republishing. Or: use an SRT import workflow rather than Notes CC for all live-narrated content.

3. The post-upload reprocessing failure: LMS modifications that break CC

Some LMS platforms — particularly older Moodle 3.x installations and certain Cornerstone OnDemand configurations — apply post-upload processing to SCORM package contents, including minification of JavaScript, URL rewriting for internal CDN routing, or HTML sanitisation. Any of these processing steps can break the JavaScript event listeners that drive the CC toggle, remove inline caption text nodes that the CC engine references, or corrupt VTT file encoding. Fix: test CC in the target LMS after every upload, not only in the authoring tool's preview. A SCORM package that passes CC testing in Articulate Review 360 or SCORM Cloud is not verified in the target LMS until it is tested there specifically.

4. The iframe height crop failure: CC button invisible but present

The CC button exists in the SCO's HTML5 output but is cropped by the LMS iframe container. The learner cannot see or click the button. No error occurs; no error is logged. From the LRS's perspective, no caption Statements are sent — which is indistinguishable from the learner choosing not to use captions. Fix: configure the LMS SCORM player dimensions to match the SCO's designed output dimensions. For Storyline 360, the default player output dimensions are 720×540 for older courses and typically 1280×720 for newer 16:9 courses — check the specific course's player settings in Storyline before configuring the LMS.

5. The CSP block failure: xAPI Statement delivery silently fails

The custom xAPI caption tracking recipe is implemented in the SCO's JavaScript, but the LMS's Content Security Policy headers prevent the fetch() call to the LRS endpoint from completing. The caption tracking code executes silently — no error visible to the learner — but Statements never arrive in the LRS. Fix: verify that the LRS endpoint domain is in the LMS's CSP connect-src directive. If modifying the LMS CSP is not possible, proxy xAPI Statements through an endpoint on an allowed domain. For organisations using SCORM Cloud as an intermediate SCORM player with xAPI passthrough, the CSP issue may not apply — SCORM Cloud's player environment is its own domain with its own CSP.

6. The VTT encoding failure: caption file present but not renderable

A VTT file bundled in the SCORM package has a BOM (byte-order mark) at the start of the file, Windows CRLF line endings instead of Unix LF, or a malformed cue sequence (missing blank line between cues, timestamp separator using comma instead of period). The HTML5 video player's track element loads the file but cannot parse it — captions silently fail to render. The LRS receives a caption-track-present Statement (if one is sent at file load) but the learner sees no caption text. Fix: validate VTT files with a pre-delivery check (BOM detection, line-ending normalisation, cue count verification) before including them in the SCORM package at publish time. The caption API automation guide documents the five-point SRT/VTT pre-delivery validation suite that catches all common format errors.

7. The migration detachment failure: caption assets that don't travel with the package

Rise 360 courses that use direct MP4 upload (instead of video host embed) carry no caption assets — the captions were never there. Rise courses that use Vimeo or Wistia embed carry caption data at the video host, not in the SCORM package. When a Rise SCORM package is migrated between LMS platforms, the Rise HTML/JS content references the Vimeo/Wistia iframe by a URL that still works after migration — but if the Vimeo or Wistia video was also deleted, replaced, or had its caption configuration changed during the migration, the Rise course in the new LMS points to a video that no longer has captions. Fix: include video host caption verification as part of any Rise content migration. For each Rise course, verify that the embedded video URL is still accessible and that the video host caption configuration is intact after migration. The LMS migration caption checklist covers this as part of the Rise-specific migration verification protocol.

8. The actor identification failure: LRS Statements that can't be linked to learner records

Caption tracking Statements are arriving in the LRS, but the actor identification method used in the Statements (mbox, SHA1 hash of mbox, account, or openid) does not match the identification method used by the LMS for completion reporting. The result: caption tracking data in the LRS cannot be linked to the same learner's completion record because the actor identifiers are different. This makes it impossible to answer the question "did this learner have functional captions when they completed this course?" — the completion record is in the LMS (or via the SCORM CMI), and the caption record is in the LRS, but they refer to different learner identifiers. Fix: standardise actor identification across all xAPI Statement sources. Use the same actor identification method (mbox or account) consistently in both the SCORM CMI data model (cmi.learner_id) and the custom xAPI Statement recipe. For organisations using a corporate SSO or directory, the actor identifier should map directly to the SSO user identifier to enable cross-system linking.

FAQ

Our SCORM library has 800 packages from the past 10 years. We don't have the original Storyline project files for the older ones. What can we do?

For packages where the original project file is unavailable, your options for adding captions are limited but not zero. Option 1: rebuild the course in the current authoring tool from the course content (slides, scripts, narration recordings) — often faster than expected if the source media is available, even without the .story file. Option 2: wrap the SCORM package content in a new delivery layer that adds a separate caption track. This requires extracting the SCORM ZIP, identifying the narration audio assets, running them through a captioning service, creating HTML5 player code around the existing content, and re-packaging. This is a significant engineering effort and may produce a non-conforming SCORM package depending on how the original content was structured. Option 3: use an external caption overlay service that injects a caption panel into the LMS iframe independently of the SCORM package — some commercial accessibility overlay services offer this for SCORM content. This approach carries the same risks as any accessibility overlay (it may fail when the SCORM player updates) and is not a substitute for correct caption implementation at the authoring tool level. Prioritise the oldest, highest-enrollment courses for rebuild; use the large-scale caption backlog remediation playbook framework to sequence the work.

Can we use SCORM Cloud as an intermediary to add captions to SCORM 1.2 content we don't control?

SCORM Cloud's player provides a wrapper around the SCO content but cannot inject caption data into a SCORM package's published HTML5 output. If the original SCO contains no caption assets, SCORM Cloud cannot add them. SCORM Cloud does have an accessibility player mode that renders certain UI elements with improved keyboard navigation, but this does not address the absence of caption tracks in the underlying content. For third-party SCORM content that lacks captions, the correct remediation path is to request a captioned version from the content provider. The obligation to provide captions for WCAG 2.1 AA content rests with the content producer — if you are the employer requiring a learner to complete this content, you are responsible for ensuring the content meets accessibility standards regardless of who produced it. See the third-party compliance training captioning guide for the contractual framework.

We're evaluating a new LMS and want to make sure it handles SCORM captions correctly. What should we test?

Run a standardised SCORM caption test suite against every LMS candidate before selection. The suite should include: a Storyline 360 SCORM 1.2 package with Notes CC (verify CC button visible and functional), a Storyline 360 SCORM 2004 package with Notes CC (verify same), a Captivate SCORM 1.2 package with SRT import (verify VTT track loads and renders), a Rise SCORM package with Vimeo embed (verify Vimeo iframe loads and CC is accessible), and a Rise SCORM package with direct MP4 upload (verify you can identify this as the uncaptioned architecture during evaluation). Test each package in the browsers your learner population uses. Test with the LMS's maximum and minimum player window size settings. Test CC button interaction — click to enable, verify text appears, click to disable, verify text disappears. Any LMS that fails to render captions from a correctly published Storyline or Captivate SCORM package in this controlled test has a SCORM player incompatibility that will affect your production library. Do not accept vendor assurances about SCORM compliance without testing; the SCORM 1.2 standard is old enough that LMS implementations vary significantly in ways that specifically affect CSS and JavaScript execution in the SCO iframe.

What does xAPI "caption-enabled" tracking look like from a legal/audit perspective?

xAPI caption tracking Statements can serve as audit evidence that captions were available and that learners with disability accommodations were able to access them. A Statement showing that a learner whose ADA accommodation record includes a captioning requirement sent an enabled-captions Statement at the start of a mandatory compliance training module is meaningful audit evidence. However, xAPI Statements are not tamper-evident in the same way as a signed digital document — the LRS does not inherently prevent modification of Statements after submission (some LRS implementations enforce immutability; verify with your LRS vendor). For high-stakes accommodation audits (DOJ complaint investigations, ADA Title II enforcement), consider supplementing LRS data with a signed attestation mechanism or a compliance event log that is separately archived. The xAPI data is probative evidence, not conclusive evidence by itself. For the governance policy framework that should surround caption compliance documentation, see the caption programme governance policy template.

We use Articulate Rise with SCORM output. Some courses use Vimeo, some use direct MP4. How do we audit which ones have captions?

Extract each Rise SCORM ZIP and search the package content for video iframes. Rise packages with Vimeo embeds contain an iframe element with player.vimeo.com in the src attribute. Rise packages with direct MP4 upload contain an HTML5 <video> element with an internal package path as the src attribute. Any package containing a <video> element with an internal src (not a Vimeo/Wistia/YouTube URL) has a direct MP4 upload — these packages are uncaptioned and need remediation. For the Vimeo-embedded packages, verify that the Vimeo video ID in the iframe src still exists and that the Vimeo video has captions configured by checking the Vimeo API: GET https://api.vimeo.com/videos/{video_id}/texttracks returns the caption tracks available on the video. Any empty result set means the Vimeo video has no caption track — the Rise course is uncaptioned even though it uses a video host. This audit can be automated with a script that extracts all Rise ZIPs, identifies video elements, classifies them as Vimeo/Wistia/direct-upload, and queries the Vimeo API for each identified video ID.

We're planning to move from SCORM 1.2 to xAPI for all new content. Does this solve the caption delivery problem?

Moving from SCORM 1.2 to xAPI for content delivery does not by itself solve the caption delivery problem. xAPI is a reporting format — it records what learners do. Caption delivery is a content publishing problem — captions must be in the content before it is published. An xAPI-launched HTML5 course with no caption assets is no better captioned than a SCORM 1.2 course with no caption assets. What the xAPI transition enables is caption usage tracking via custom Statements (as documented in this guide), which gives you visibility into caption delivery failures that SCORM 1.2's opaque runtime cannot provide. The content production workflow — ensuring every narrated course has a verified caption track before it is published and deployed — must be solved at the authoring tool level regardless of the packaging format. If your team is planning a cmi5 migration, use the transition as an opportunity to require caption verification as a prerequisite for any course being published in the new format, so the cmi5 library starts clean.

We send our SCORM content to channel partners who host it in their own LMS. Who is responsible for caption compliance?

Caption compliance for SCORM content distributed to channel partners depends on the contractual relationship and the applicable accessibility framework. Under ADA Title I and WCAG 2.1 AA, the employer requiring learners to complete training is responsible for ensuring accessible format delivery — including captions. If your SCORM package contains correct captions and the channel partner's LMS breaks CC rendering (due to iframe configuration, CSP headers, or player reprocessing), the compliance obligation has been complicated by a delivery failure on the partner side. The channel partner agreement should include a clause requiring WCAG 2.1 AA-compliant SCORM player configuration. Publish SCORM packages only after verifying CC functionality in SCORM Cloud (a neutral test environment) and document that the package passes the SCORM Cloud CC test at publication time. If a channel partner's LMS breaks captioning, that documentation supports your position that you delivered a compliant package and the delivery failure is on the partner's side. See the extended enterprise and channel partner training captioning guide for the contractual provisions that make this defensible.

Caption delivery verification for SCORM libraries at scale

GlossCap's API integrates with SCORM production workflows — generating verified caption assets, validating VTT format before package publish, and sending xAPI Statements to your LRS when caption delivery is confirmed. The audit methodology in this guide can be automated against your LMS library using GlossCap's batch pipeline.

See how it works →

Other tools from the same factory: