Standalone SoundKit v2 frame-stream tooling.
This repo owns the durable web format we want for source-audio caches:
*.soundkitis a continuous SoundKit v2 frame stream.*.soundkit.idxis a compact sidecar byte-offset index.*.soundkit.jsonis optional metadata for object stores and players.
The player fetches the sidecar index first, binary-searches by target PCM frame, then range-fetches the stream from the indexed byte offset. To seek to an exact time, decode from the nearest earlier frame boundary and trim decoded samples to the requested target frame.
packages/soundkit-stream-js: JavaScript parser, frame scanner, sidecar index utilities, and WASM loader helpers.crates/soundkit-stream: Rust core encoder and index codec.crates/soundkit-stream-wasm:wasm-bindgenwrapper around the Rust encoder.
The first Rust encoder path accepts interleaved signed 16-bit PCM and writes:
- Opus payloads encoded with the sibling
libopus-rscrate. - SoundKit v2 headers from the sibling
frame-headercrate. - One sidecar index entry per SoundKit frame.
u64lebyte offsets andu64lestart PCM frames in the sidecar index.
The current Opus path intentionally requires 48 kHz, 1-2 channel PCM. Bitneedle's current shared source-audio worker already normalizes to this shape before Opus encoding, so this is the right first extraction point.
import {
decodeSoundKitIndex,
frameForTimeSeconds,
soundKitRangeRequestForFrame
} from "@wavey/soundkit-stream";
const indexBytes = new Uint8Array(await (await fetch("/audio.soundkit.idx")).arrayBuffer());
const index = decodeSoundKitIndex(indexBytes);
const targetFrame = frameForTimeSeconds(42.25, index.timescale);
const request = soundKitRangeRequestForFrame(index, targetFrame);
const streamResponse = await fetch("/audio.soundkit", {
headers: request.headers
});After building the WASM package:
import init, * as wasm from "./pkg/soundkit_stream_wasm.js";
import { encodePcmI16ToSoundKitOpusStreamWithWasm } from "@wavey/soundkit-stream/wasm";
await init();
const encoded = encodePcmI16ToSoundKitOpusStreamWithWasm(wasm, pcmInt16Array, {
sampleRate: 48_000,
channels: 2,
bitrate: 128_000,
frameSize: 960
});
const streamBytes = encoded.stream;
const indexBytes = encoded.index;
const metadata = JSON.parse(encoded.metadataJson());For arbitrary source files, compose the existing SoundKit decoder WASM with this repo's encoder WASM:
import {
transcodeSourceToSoundKitOpusStreamWithWasm
} from "@wavey/soundkit-stream/transcode";
const result = await transcodeSourceToSoundKitOpusStreamWithWasm({
decoderModule: soundkitDecoderWasm,
encoderModule: soundkitStreamWasm,
chunks: [sourceFileBytes],
sampleRate: 48_000,
bitrate: 128_000,
frameSize: 960
});The current transcode helper expects the decoder to emit 48 kHz 16-bit PCM. Bitneedle already has this normalization step; moving that resampler into this repo is the next extraction step.
This checkout is wired to sibling local Wavey crates:
../frame-header../libopus-rs
For a clean GitHub-only clone, switch those crate dependencies to their Wavey Git URLs or add a Cargo patch file in the consuming workspace.
Run:
npm run test:js
cargo test --workspace
cargo build -p soundkit-stream-wasm --target wasm32-unknown-unknownwasm-pack packaging is exposed as:
npm run build:wasm