[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-80217":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":15,"stars7d":16,"stars30d":17,"stars90d":15,"forks30d":15,"starsTrendScore":15,"compositeScore":18,"rankGlobal":10,"rankLanguage":10,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":22,"hasPages":22,"topics":23,"createdAt":10,"pushedAt":10,"updatedAt":24,"readmeContent":25,"aiSummary":26,"trendingCount":15,"starSnapshotCount":15,"syncStatus":14,"lastSyncTime":27,"discoverSource":28},80217,"libopus-wasm","openclaw\u002Flibopus-wasm","openclaw","Small, modern WASM bindings for libopus raw packet encode\u002Fdecode.","https:\u002F\u002Flibopus-wasm.dev",null,"JavaScript",83,3,2,0,1,15,43.81,"MIT License",false,"main",true,[],"2026-06-12 04:01:27","# libopus-wasm\n\n![libopus-wasm banner](docs\u002Fassets\u002Freadme-banner.jpg)\n\n[![CI](https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Flibopus-wasm\u002Factions\u002Fworkflows\u002Fci.yml\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002Fopenclaw\u002Flibopus-wasm\u002Factions\u002Fworkflows\u002Fci.yml)\n[![Docs](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fdocs-libopus--wasm.dev-6d4aff)](https:\u002F\u002Flibopus-wasm.dev)\n\nSmall, modern WebAssembly bindings for [libopus](https:\u002F\u002Fopus-codec.org\u002F) raw\npacket encode\u002Fdecode. One single-file ES module that runs unchanged in browsers\nand Node — no `locateFile` hook, no second `.wasm` request, no native build step.\n\nThe default path is realtime voice: 48 kHz, stereo, 20 ms frames, raw Opus\npackets, no Ogg\u002FWebM container layer.\n\n- **Browser and Node** from one import. Bundles cleanly with Vite, webpack, esbuild.\n- **Int16 and Float32 PCM** — use whatever your pipeline already speaks.\n- **Loss-resilient** — in-band FEC and packet-loss concealment.\n- **Tunable** — bitrate, VBR\u002FCBR, complexity, signal, bandwidth, DTX, plus a curated CTL passthrough.\n- **Drop-in `@discordjs\u002Fopus` adapter** — same method shape, no node-gyp.\n\n📖 **Full documentation: [libopus-wasm.dev](https:\u002F\u002Flibopus-wasm.dev)**\n\n## Install\n\n```bash\nnpm install libopus-wasm\n```\n\nESM-only; Node 20+ or any current browser. No `@types` install needed.\n\n## Quick start\n\n```ts\nimport { createDecoder, createEncoder, getPacketInfo } from \"libopus-wasm\";\n\nconst encoder = await createEncoder(); \u002F\u002F 48 kHz, stereo, 20 ms, audio\nconst decoder = await createDecoder();\n\nconst pcm = new Int16Array(encoder.frameSize * encoder.channels); \u002F\u002F 960 * 2\nconst packet = encoder.encode(pcm);    \u002F\u002F Uint8Array — one raw Opus packet\nconst info = await getPacketInfo(packet); \u002F\u002F duration, frames, bandwidth\nconst frame = decoder.decode(packet);  \u002F\u002F Int16Array — interleaved PCM\n\nencoder.free();\ndecoder.free();\n```\n\nBoth factories share one lazily-loaded WASM module; the first call pays the load\ncost and the rest are cheap.\n\n## Examples\n\n### Float32 PCM\n\nEncode and decode floats directly — ideal for Web Audio:\n\n```ts\nconst frame = new Float32Array(encoder.frameSize * encoder.channels); \u002F\u002F [-1, 1]\nconst packet = encoder.encodeFloat(frame);\nconst decoded = decoder.decodeFloat(packet); \u002F\u002F Float32Array\n```\n\n### Batches\n\n```ts\nconst packets = encoder.encodeFrames([frameA, frameB, frameC]); \u002F\u002F Uint8Array[]\nconst frames = decoder.decodeFrames(packets);                   \u002F\u002F Int16Array[]\n```\n\n### Packet loss: FEC + concealment\n\n```ts\n\u002F\u002F Encoder: enable in-band FEC and declare the expected loss rate.\nconst encoder = await createEncoder({ fec: true, packetLossPercent: 15 });\n\n\u002F\u002F Decoder: a packet is lost. If the next packet is in hand, recover from its\n\u002F\u002F FEC data; otherwise synthesize a concealment frame.\nconst recovered = decoder.decode(nextPacket, { decodeFec: true, frameSize: 960 });\nconst concealed = decoder.decodePacketLoss(960); \u002F\u002F == decode(null, { frameSize: 960 })\n```\n\nSee [Packet loss](https:\u002F\u002Flibopus-wasm.dev\u002Fpacket-loss.html) for the full receive loop.\n\n### Tuning the encoder\n\n```ts\nconst encoder = await createEncoder({\n  application: Application.Audio,\n  bitrate: 96000,        \u002F\u002F or \"auto\" \u002F \"max\"\n  complexity: 10,        \u002F\u002F 0..10\n  signal: Signal.Music,\n  vbr: true,\n});\n\nencoder.setBitrate(128000);\nencoder.setMaxBandwidth(Bandwidth.Wideband);\nencoder.getBitrate();    \u002F\u002F 128000\n```\n\n### Deterministic cleanup with `using`\n\n```ts\n{\n  using encoder = await createEncoder();\n  using decoder = await createDecoder();\n  decoder.decode(encoder.encode(new Int16Array(960 * 2)));\n} \u002F\u002F both freed automatically at scope exit\n```\n\n## discord.js compatibility\n\n`libopus-wasm\u002Fdiscordjs` matches the [`@discordjs\u002Fopus`](https:\u002F\u002Fgithub.com\u002Fdiscordjs\u002Fopus)\nmethod shape, minus the native toolchain. It is Node-only (uses `Buffer`) and\nloads asynchronously:\n\n```ts\nimport { OpusEncoder } from \"libopus-wasm\u002Fdiscordjs\";\n\nconst opus = await OpusEncoder.create(48000, 2);\nconst packet = opus.encode(pcmBuffer);\nconst decoded = opus.decode(packet);\nopus.setBitrate(64000);\nopus.setFEC(true);\nopus.free();\n```\n\nOr construct directly and await `ready` to keep existing call sites:\n\n```ts\nconst opus = new OpusEncoder(48000, 2);\nawait opus.ready;\n```\n\nMore in [discord.js compatibility](https:\u002F\u002Flibopus-wasm.dev\u002Fdiscordjs.html).\n\n## Browser\n\nThe main entry inlines the WASM, so it bundles with no plugins and needs no\ncross-origin isolation. Web Audio delivers Float32 samples that go straight into\n`encodeFloat` — see [Browser usage](https:\u002F\u002Flibopus-wasm.dev\u002Fbrowser.html) for a\nmicrophone-capture walkthrough.\n\n## API overview\n\nFull reference with every option and constant lives at\n[libopus-wasm.dev\u002Fapi-reference](https:\u002F\u002Flibopus-wasm.dev\u002Fapi-reference.html).\n\n### Top-level\n\n| Function | Returns | Description |\n| --- | --- | --- |\n| `loadLibopus()` | `Promise\u003C{ version }>` | Loads the module; returns the bundled libopus version. |\n| `createEncoder(options?)` | `Promise\u003COpusEncoderHandle>` | Create a raw-packet encoder. |\n| `createDecoder(options?)` | `Promise\u003COpusDecoderHandle>` | Create a raw-packet decoder. |\n| `getPacketInfo(packet, options?)` | `Promise\u003COpusPacketInfo>` | Validate a raw packet and return duration, frame count, channels, and bandwidth. |\n\n### Encoder\n\n| Member | Description |\n| --- | --- |\n| `encode(pcm, options?)` | Encode one Int16 frame (`Int16Array \\| Uint8Array`) → `Uint8Array`. |\n| `encodeFloat(pcm, options?)` | Encode one `Float32Array` frame → `Uint8Array`. |\n| `encodeFrames` \u002F `encodeFloatFrames` | Batch variants → `Uint8Array[]`. |\n| `setBitrate` \u002F `getBitrate` | Bitrate (`number \\| \"auto\" \\| \"max\"`). |\n| `setComplexity` `setSignal` `setMaxBandwidth` | Quality and bandwidth controls. |\n| `setVbr` `setVbrConstraint` `setDtx` | Rate-mode controls. |\n| `setFec` `setPacketLossPercent` | Loss-resilience controls. |\n| `getLookahead` `getInDtx` | Encoder state. |\n| `encoderCtl(request, value)` | Curated integer-setter [CTL passthrough](https:\u002F\u002Flibopus-wasm.dev\u002Fctl.html). |\n| `free()` \u002F `[Symbol.dispose]()` | Release WASM memory. |\n\nRead-only: `application`, `channels`, `frameSize`, `sampleRate`.\n\n### Decoder\n\n| Member | Description |\n| --- | --- |\n| `decode(packet, options?)` | Decode a packet (or `null` for PLC) → `Int16Array`. |\n| `decodeFloat(packet, options?)` | Decode → `Float32Array`. |\n| `decodeFrames` \u002F `decodeFloatFrames` | Batch variants; `null` entries are concealed. |\n| `decodePacketLoss(frameSize?)` | Synthesize one concealment frame. |\n| `decodePacketLossFloat(frameSize?)` | Float32 variant. |\n| `decoderCtl(request, value)` | Integer-setter CTL passthrough. |\n| `free()` \u002F `[Symbol.dispose]()` | Release WASM memory. |\n\nRead-only: `channels`, `maxFrameSize`, `sampleRate`.\n\n### Constants\n\n`Application` (`Voip`, `Audio`, `RestrictedLowDelay`) ·\n`Signal` (`Auto`, `Voice`, `Music`) ·\n`Bitrate` (`Auto`, `Max`) ·\n`Bandwidth` (`Narrowband`…`Fullband`) ·\n`EncoderCtl` \u002F `DecoderCtl` request codes ·\n`OpusError` (`code`, `operation`).\n\n### Supported formats\n\n| Constraint | Allowed values |\n| --- | --- |\n| Sample rate | `8000`, `12000`, `16000`, `24000`, `48000` Hz |\n| Channels | `1` (mono), `2` (stereo) |\n| Encode frame duration | `2.5`, `5`, `10`, `20`, `40`, `60` ms |\n| Decode output capacity | up to `120` ms |\n| PLC \u002F FEC frame size | multiples of `2.5` ms, up to `120` ms |\n\nValidation errors (wrong frame size, out-of-range option, empty packet,\nnon-allow-listed CTL) throw a `RangeError` before reaching WASM; libopus errors\nsurface as `OpusError`.\n\n## Build from source\n\nThe npm package ships compiled output, so using it needs no toolchain. Building\nfrom source requires Emscripten (`emcc`) on `PATH`:\n\n```bash\npnpm install\npnpm build\npnpm test\n```\n\n`pnpm build` downloads `libopus 1.6.1` from Xiph.Org, verifies the pinned\nSHA-256, compiles it with Emscripten, and emits a single-file ES module under\n`dist\u002Fgenerated\u002F`. See [Building from source](https:\u002F\u002Flibopus-wasm.dev\u002Fbuilding.html).\n\n## Benchmark\n\nNative comparison requires `@discordjs\u002Fopus` to build on the host:\n\n```bash\npnpm benchmark\n```\n\nApple Silicon, Node 26, 20k iterations, 48 kHz stereo, 20 ms frames:\n\n```text\nwasm encode:   15,304 ops\u002Fsec\nnative encode: 15,741 ops\u002Fsec\nwasm decode:   38,416 ops\u002Fsec\nnative decode: 41,280 ops\u002Fsec\n```\n\nA regression check, not a portable score. CI also exposes a manual `Benchmark`\nworkflow. More in [Benchmark](https:\u002F\u002Flibopus-wasm.dev\u002Fbenchmark.html).\n\n## Documentation & license\n\nFull docs: **[libopus-wasm.dev](https:\u002F\u002Flibopus-wasm.dev)**. Released under the\n[MIT license](LICENSE); libopus carries its own BSD license, reproduced in\n[THIRD_PARTY_NOTICES](THIRD_PARTY_NOTICES.md). Not affiliated with Xiph.Org.\n","libopus-wasm 是一个轻量级的现代 WebAssembly 绑定库，用于 libopus 的原始数据包编码和解码。该项目提供了一个单一文件的 ES 模块，可以在浏览器和 Node.js 中无缝运行，无需额外的 `.wasm` 请求或本地构建步骤。它支持 Int16 和 Float32 PCM 格式，具有抗丢包特性（包括前向纠错和丢包隐藏），并且可调节比特率、复杂度等参数。此外，它还提供了一个与 `@discordjs\u002Fopus` 兼容的适配器，使得迁移更加方便。此项目适用于需要实时音频处理的应用场景，如在线会议、语音聊天或任何涉及 Opus 音频编解码的 Web 应用程序。","2026-06-11 03:59:42","CREATED_QUERY"]