SCORM package too large? How to shrink it

SCORM package too large for your LMS? Find what is actually heavy, compress or externalise media, strip unused assets, and keep tracking intact.

Why is my SCORM package too large?

A SCORM package is too large when the zip exceeds the upload limit your LMS or its web server enforces. SCORM itself sets no size cap. Almost always the weight is media rather than code: video, uncompressed audio, and full-resolution images. Shrink those three and the package fits without changing a single line of the course.

The limit you hit is rarely a SCORM rule. It is the hosting stack: a maximum upload size in the web server configuration, a matching limit in PHP or the application runtime, a request timeout that fires before a slow upload finishes, or a per-course quota an administrator set. Those numbers vary by platform and by installation, which is why the same package uploads to one LMS and is rejected by another.

Size costs you twice. The first cost is the upload, which you notice. The second is every learner, which you do not: the browser downloads those assets over whatever connection the learner has, so a heavy package means a slow first page, stalled video, and learners closing the tab before the runtime has committed anything. A package that is small for the LMS is also faster for the person taking it.

Find what is heavy

Do not guess, and do not start by re-zipping. Unzip the package and measure it, because the fix for 400 MB of video is nothing like the fix for 4,000 tiny files.

unzip -l course.zip | sort -k1 -rn | head -20     # biggest entries, uncompressed
unzip -q course.zip -d course/
du -sh course/*                                   # where the weight sits by folder
find course/ -type f -printf '%s\t%p\n' | sort -rn | head -20

Two minutes of that usually ends the investigation. The distribution is almost always lopsided: one or two media files account for most of the package, and everything else is noise.

What you findTypical causeWhat actually works
One or two very large .mp4 filesExported at source resolution and bitrateRe-encode, or externalise and stream
Many .wav or high-bitrate .mp3 filesNarration exported uncompressed, per slideRe-encode to mono at a speech bitrate
Large .png screenshots and photosPNG used for everything by defaultResize to display size; JPEG for photos
A big fonts or lib folderWhole icon and font families shippedSubset to the weights you actually use
Source files: .pptx, .psd, .ai, .movAuthoring tool exported its working filesRemove — they are never served

One thing that will not work: compressing harder. MP4, MP3, JPEG and PNG are already compressed, so a package that is mostly media gains a few percent from a better zip setting and no more. The size has to come out of the assets themselves.

Compress and re-encode media

Re-encoding is where the large wins are, and for most courses it is invisible to the learner.

  • Video. H.264 in an MP4 container plays everywhere. Screen recordings and talking heads rarely need 1080p — 720p is usually indistinguishable at the size the player actually renders. Encode with a quality target rather than a fixed bitrate so simple footage gets smaller automatically, and cap the frame rate at 30 unless the content is genuinely motion-heavy.
  • Audio. Narration is speech, and speech is mono. Exporting voice-over as stereo doubles the data for no audible gain; a modest mono bitrate is transparent for a human voice and a fraction of the size of the WAV it came from.
  • Images. Resize to the pixel dimensions the layout displays, then choose format by content: JPEG for photographs and screenshots, PNG only where you need flat colour or transparency. A 4,000-pixel-wide photo shown in a 800-pixel column is carrying five times the data it needs.
  • Fonts. Ship the weights the course uses, not the family. Subsetting a font to the characters and weights present in the content routinely removes hundreds of kilobytes.

Re-encode from the highest-quality source you still have, not from the file already in the package — compressing an already-compressed file twice produces visible artefacts for very little extra saving. Then replace the asset in place, keeping the same filename, so nothing in the HTML or the manifest has to change.

Externalise large video

When one video is most of the package, the fastest fix is to stop shipping it. Leave the SCO in the zip and point the player at a URL instead of a bundled file, so the package carries the course and the network carries the media.

<!-- was -->
<video src="media/module-01.mp4"></video>

<!-- now -->
<video src="https://media.example.org/courses/module-01.mp4"
       preload="metadata" playsinline></video>

Tracking is unaffected. The runtime conversation happens between the SCO and the LMS in JavaScript; it does not care where a video file came from. Status, score, bookmark and commit behave exactly as before.

Serve external media over HTTPS, from a host that allows it. An LMS page loaded over HTTPS will block media requested over plain HTTP, and the learner sees an empty player with no error they can act on. Check too that the host does not block hotlinking or require a signed URL that expires, and remember that an externalised video is unavailable to anyone on a restricted or offline network — if your learners include those, the file has to stay in the package.

The trade is self-containment. A package with bundled media is one artefact that works anywhere; a package with external media depends on a URL staying alive for the life of the course. Version the media path rather than overwriting files at the same URL, so an updated video never silently appears inside an old course. Converting video to SCORM covers the packaging side of the same decision.

Strip unused assets

Authoring tools export generously. It is common to find unused themes and templates, locale files for languages the course does not offer, several copies of the same JavaScript library, and the original source documents sitting beside their published output. None of it is served and all of it is in the zip.

Find what is genuinely referenced before deleting anything:

grep -rlio 'bigfile\.png' course/ --include=*.html --include=*.css --include=*.js
grep -rhoE '(src|href)="[^"]+"' course/ --include=*.html | sort -u
Do not delete by manifest alone. imsmanifest.xml is supposed to declare every file a resource needs, but plenty of authoring tools list only the launch page and leave images, stylesheets and scripts undeclared. A file missing from the manifest is not proof it is unused — it may be referenced from CSS, injected by script, or loaded by a name the exporter built at runtime. Search the content, keep anything you cannot account for, and re-zip from a copy so the original is always recoverable.

When you re-zip, build the archive from inside the course folder so imsmanifest.xml sits at the root of the zip and not inside a wrapper directory. A manifest one level down is the single most common reason a freshly rebuilt package is rejected on import. Then run the shrunk package before it goes anywhere near a cohort — testing SCORM before upload walks the checks that catch a stripped file the course still wanted.

When to host instead of embed

If you are trimming the same course every few months, the size is a symptom. At that point the question is not how to compress harder but whether the content should live in the package at all.

The alternative is a thin launcher: a small package that contains the manifest and a launch page, with the course itself hosted elsewhere and loaded at run time. The zip becomes trivial in size, and updating the course no longer means re-importing a zip into every LMS that has a copy. Dispatch explained covers how that launcher reports back to the LMS.

It is not a free win. Hosting means you now run something: a server, a domain, TLS certificates, and an availability problem that belongs to you rather than to the LMS vendor. Learners on restricted networks may be unable to reach it. And the LMS records only what the launcher reports, so a broken connection is a lost attempt rather than a slow one.

  • Compress when one export was careless and the course is otherwise fine — the common case, and the cheapest.
  • Externalise media when a single course is dominated by video and your learners are reliably online.
  • Host the course when the content changes often, is distributed to several LMSs, or is large in ways that compression cannot reach.
  • Split into modules when none of the above helps: several smaller packages import where one large one will not, and learners resume more reliably in shorter sessions.

Where SCORM Central fits

SCORM Central converts files you already have — PDF, PowerPoint, Word, or video — into SCORM 1.2, SCORM 2004, cmi5, or xAPI, and shows you the manifest, the full runtime log, and a conformance report on every build, so you can see exactly what a package will report before an LMS does. See how it works, or start with one file.

Keep reading

How-to4 min Convert SCORM to video or PowerPoint? Can you convert SCORM to MP4, HTML5 or PowerPoint? What is inside a package, the routes that work, and what you lose with each one. Explainer4 min Does your LMS support xAPI? How to check What xAPI LMS support really means: launching xAPI content, a built-in LRS, or forwarding statements. The questions to ask and a quick test to run. Explainer4 min LMS vs LRS: what is the difference? LMS vs LRS: an LMS runs courses and learners; an LRS stores xAPI statements. Why SCORM does not use an LRS, and when you need both.

Start with one file.

Upload something you already have and see it as a package, with the conformance report and the runtime log alongside it.

→ upload  handbook.pdf
  parsing … 14 sections
  building manifest …
  validating … 0 errors, 2 notes
✓ handbook-scorm2004.zip
✓ preview link ready