document-media-extractor
v0.1.2
Published
Local-first extraction of embedded media from document and ZIP containers.
Downloads
448
Maintainers
Readme
Document Media Extractor
Extract original embedded media locally from OOXML, OpenDocument, EPUB, CBZ, and ZIP containers—no uploads or backend required.
What it supports
The stable release supports the local ZIP-based document and archive formats below through a Node API and CLI. It is deliberately local-first: no backend, account, upload, or remote URL is involved.
| Input | Embedded media path | Provenance recorded |
| --- | --- | --- |
| Word OOXML: DOCX, DOCM, DOTX, DOTM | word/media/ | Word accessibility descriptions, where relationship mapping is reliable |
| PowerPoint OOXML: PPTX, PPTM, POTX, POTM | ppt/media/ | slide number and OOXML relationship |
| Excel OOXML: XLSX, XLSM, XLTX, XLTM | xl/media/ | workbook, worksheet, drawing, and OOXML relationship |
| OpenDocument: ODT, ODS, ODP | embedded image paths | original archive path |
| EPUB 2 / EPUB 3 | cover and illustration paths | original archive path |
| CBZ | comic page paths, ordered naturally | original archive path |
| ZIP | image files in nested folders | original archive path |
Legacy binary Office formats (.doc, .ppt, .xls), PDF, iWork, and DRM-protected ebook formats are intentionally not supported yet. Convert legacy Office files to OOXML first.
Need a no-install, browser-only workflow for one Office document? Use the matching local browser tool: Word image extractor, PPT image extractor, or Excel image extractor. Browser-only equivalents for OpenDocument, EPUB, CBZ, and ZIP archives are available on the same site.
Install from npm
npm install document-media-extractorRun the CLI without cloning the repository:
npx document-media-extractor ./brief.docx --out ./extractedThe CLI accepts every format in the table above. It writes retained original media files and a manifest.json, and refuses to overwrite an existing output directory.
Develop from GitHub
git clone https://github.com/WanderZil/document-media-extractor.git
cd document-media-extractor
pnpm install
pnpm build
node dist/cli.js ./brief.docx --out ./extractedFor a policy file:
node dist/cli.js ./brief.xlsx --out ./extracted --policy ./policy.jsonTo process every supported document directly inside one folder (non-recursive), use batch mode. Each successful input gets its own numbered output folder, and batch-manifest.json records both successes and isolated failures.
node dist/cli.js --batch ./documents --out ./extracted-batch --policy ./policy.jsonNode API
import { readFile } from "node:fs/promises";
import { extractDocumentMedia } from "document-media-extractor";
const result = await extractDocumentMedia({
sourceName: "book.epub", // see the supported-format table above
bytes: new Uint8Array(await readFile("book.epub")),
policy: {
minWidth: 320,
minPixels: 100_000,
exactDuplicates: "exclude",
namingTemplate: "{source}-{index}-{name}",
},
});result.assets contains only retained original media bytes. result.manifest retains every discovered item with source provenance, SHA-256, measurements, export name, and an INCLUDED or exclusion decision. The default policy retains every media file.
Image dimensions are read without decoding pixels for PNG, GIF, and baseline/progressive JPEG. Other media remains extractable, but dimension filters mark it UNREADABLE_DIMENSIONS instead of guessing.
{name} uses a Word accessibility description only when its OOXML relationship maps it reliably to one media part; otherwise it falls back to the embedded filename. Names are sanitized and collision-resolved deterministically.
Safety and batches
Callers can opt into bounded work for CI or user-supplied files. Limit errors are explicit (for example, LIMIT_EXPANDED_BYTES), and AbortSignal cancellation reports CANCELLED rather than returning partial results. extractDocumentMediaBatch(inputs) isolates failures: successful inputs retain their results while other items report a stable error code.
policy: {
limits: {
maxInputBytes: 50_000_000,
maxArchiveEntries: 2_000,
maxExpandedBytes: 200_000_000,
maxMediaCount: 500,
maxMediaBytes: 20_000_000,
maxTotalMediaBytes: 100_000_000,
},
}Local review UI
Start a static server from this checkout, then open it in a modern Chromium browser:
python3 -m http.server 4173 --directory reviewChoose a CLI output folder in the browser. The UI reads manifest.json and the exported files directly from the local file picker. It shows every Manifest decision; only retained files have a selectable preview because excluded originals are not written to the output folder.
It uses Canvas dHash (Hamming distance ≤ 8) to mark possible visual matches among browser-decodable retained images. This is an advisory UI feature, capped at 250 items to keep the browser responsive; it never changes the extractor’s exact-byte duplicate decision or removes files. Reviewers can select retained assets and download a new ZIP containing the original files plus a review annotation in its Manifest.
For the most useful review, extract with the default preservation policy so all media remains available to inspect.
Scope and privacy
Processing is local. The project does not use a backend, upload documents, require an account, or fetch remote URLs. The browser UI is optional: the Node API and CLI are the primary extraction interfaces, while the UI is for manual visual review before a ZIP export.
Related workflow
Need images from webpages rather than local document containers? Bulk Image Download handles URL-based, browser-aware collection.
Contributing
See CONTRIBUTING.md. All fixtures must be safe to redistribute.
