{"_id":"@audio/decode-ape","name":"@audio/decode-ape","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@audio/decode-ape","version":"1.0.0","description":"Decode Monkey's Audio (APE) with FFmpeg's ape decoder, WASM","type":"module","main":"decode-ape.js","types":"decode-ape.d.ts","exports":{".":"./decode-ape.js","./audio":{"types":"./audio.d.ts","default":"./audio.js"},"./package.json":"./package.json"},"publishConfig":{"access":"public"},"scripts":{"build":"bash build.sh","prepack":"npm run build","test":"node test.js"},"devDependencies":{"tst":"^9.2.2"},"engines":{"node":">=18"},"keywords":["ape","monkeys audio","monkey's audio","lossless","audio","decode","decoder","wasm","ffmpeg","libavcodec"],"license":"LGPL-2.1-or-later","author":{"name":"audiojs"},"homepage":"https://github.com/audiojs/decode/tree/main/packages/decode-ape","repository":{"type":"git","url":"git+https://github.com/audiojs/decode.git","directory":"packages/decode-ape"},"bugs":{"url":"https://github.com/audiojs/decode/issues"},"audio":"./audio.js","sideEffects":false,"funding":"https://github.com/sponsors/audiojs","gitHead":"c227363046dc3a0308c95ee112f22795c0ac04ca","_id":"@audio/decode-ape@1.0.0","_nodeVersion":"25.9.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-kvLN1R0bxU1yiaCko2iW1xjQ56nR9+QpZZxrbP+s3/RAyVFnCNlG8wsNmLcLnky3l4iZ4mRtbu0DVvCipdL5/A==","shasum":"fd5c6f44958343a2cc2be3fa8d74e25cdffaf25b","tarball":"https://registry.npmjs.org/@audio/decode-ape/-/decode-ape-1.0.0.tgz","fileCount":9,"unpackedSize":315840,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIAe9k2QeIAB2KiCG7bAzlqgd3bdr1o6ZAFArloWZhJ6EAiBcBSuo/T9EpV1Bjc92mcESlXj4/xaPewj5kGUV9Dn72Q=="}]},"_npmUser":{"name":"dy","email":"df.creative@gmail.com"},"directories":{},"maintainers":[{"name":"jamen","email":"jamenmarz@gmail.com"},{"name":"dfcreative","email":"df.creative@gmail.com"},{"name":"dy","email":"df.creative@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/decode-ape_1.0.0_1787966875806_0.7662017325936676"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-29T01:27:55.673Z","1.0.0":"2026-08-29T01:27:55.949Z","modified":"2026-08-29T01:27:56.135Z"},"maintainers":[{"name":"jamen","email":"jamenmarz@gmail.com"},{"name":"dfcreative","email":"df.creative@gmail.com"},{"name":"dy","email":"df.creative@gmail.com"}],"description":"Decode Monkey's Audio (APE) with FFmpeg's ape decoder, WASM","homepage":"https://github.com/audiojs/decode/tree/main/packages/decode-ape","keywords":["ape","monkeys audio","monkey's audio","lossless","audio","decode","decoder","wasm","ffmpeg","libavcodec"],"repository":{"type":"git","url":"git+https://github.com/audiojs/decode.git","directory":"packages/decode-ape"},"author":{"name":"audiojs"},"bugs":{"url":"https://github.com/audiojs/decode/issues"},"license":"LGPL-2.1-or-later","readme":"# @audio/decode-ape\n\nDecode Monkey's Audio (APE) to PCM float samples.<br>\nFFmpeg's `ape` decoder — a slim LGPL-2.1-or-later `libavcodec`/`libavutil` build (no GPL components) — compiled to a single-file WASM ES module. No side files, loads from any CDN, Node, workers and AudioWorklets.\n\n[![npm install @audio/decode-ape](https://nodei.co/npm/@audio/decode-ape.png?mini=true)](https://npmjs.org/package/@audio/decode-ape/)\n\n```js\nimport decode, { decoder } from '@audio/decode-ape'\n\nlet { channelData, sampleRate } = await decode(apeBytes)\n\nlet dec = await decoder()\nlet head = dec.decode(chunk1)   // synchronous; EMPTY until the header + seek table are complete\nlet tail = dec.flush()          // decodes the final frame — its length isn't known until here\ndec.free()\n```\n\nMonkey's Audio (`.ape`) is a lossless predictive codec — [monkeysaudio.com](https://monkeysaudio.com), file versions 3.80 through 3.99. FFmpeg ships no APE *demuxer* library to link against (only the format-agnostic `libavformat`, which this build excludes), so the container — descriptor/header block, seek table, per-frame packet layout — is parsed here in JS, replicating `libavformat/ape.c`'s `ape_read_header`/`ape_read_packet` exactly (field layout, skip/size arithmetic, the `[nblocks, skip, data]` packet shape `apedec.c` expects); decoding itself is FFmpeg's own `ape` decoder. Mono or stereo, 8/16/24-bit, any compression level (fast/normal/high/extra high/insane) — the decoder rejects anything else (`avcodec/apedec.c` only supports ≤ 2 channels and those three bit depths).\n\nFrame boundaries come entirely from the header's seek table, so `decoder()` decodes each frame as soon as its bytes are fully buffered — no need to wait for a container-level end marker. The one exception is the **last** frame: its byte length isn't in the seek table (only the *next* frame's position bounds a frame, and there is no next for the last one) — FFmpeg's demuxer derives it from the total file size once known, so this decoder does the same at `flush()`, using the total byte count fed to it as that \"file size\". A stream that ends mid-frame (truncated source) still decodes whatever's decodable — matching `libavformat`'s own short-read tolerance (`ape_read_packet`'s `avio_read` can return fewer bytes than requested; the decoder just decodes less).\n\n## API\n\n### `decode(src: Uint8Array | ArrayBuffer): Promise<AudioData>`\n\nDecode a complete `.ape` file.\n\n### `decoder(): Promise<APEDecoder>`\n\nSynchronous streaming decoder: `decode(chunk)` returns every frame's samples once its bytes are buffered (`EMPTY` while the header/seek table or a frame's data is still incomplete), `flush()` decodes the final frame, `free()` releases WASM memory. `errors` counts frames that failed to decode.\n\n### `AudioData`\n\n```ts\n{ channelData: Float32Array[], sampleRate: number }\n```\n\n**Use when:** you need to play or transcode `.ape` files in the browser or Node without shelling out to `ffmpeg`/`mac`.\n\n## Fixtures\n\nTest fixtures at [1000, 2000, 3000, 4000, 5000] compression, mono, 24-bit and 8-bit were generated with the [Monkey's Audio SDK](https://monkeysaudio.com/developers.html) reference `mac` CLI (Monkey's Audio Source Code License — used only to produce test data, nothing from the SDK is ported or shipped) and checked **bit-exact** against `ffmpeg -i x.ape -f s16le/s32le/u8 -`. Three additional fixtures are real files from FFmpeg's own FATE test suite (`rsync://samples.ffmpeg.org/fate-suite/lossless-audio/`) — needed because the reference encoder here only produces the modern (≥ 3.98) header; the FATE samples cover the legacy 3.80/3.94 header format and short-read/truncation handling.\n\n## License\n\n[ॐ](https://github.com/krishnized/license/) · [LGPL-2.1-or-later](./LICENSE), inherited from the bundled [FFmpeg](https://ffmpeg.org/legal.html) `ape` decoder (built without `--enable-gpl` — see [`build.sh`](./build.sh) and [`LICENSE.ffmpeg`](./LICENSE.ffmpeg)). FFmpeg source: the shared [`lib/ffmpeg`](../../lib/ffmpeg) submodule (`release/7.1`), also used by [`@audio/decode-eac3`](../decode-eac3).\n","readmeFilename":"README.md","_rev":"1-8a5e2540a8e3719ca87eafd1c46e21a5"}