@harmonia-audio/codec 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +526 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +425 -0
- package/dist/index.d.ts +425 -0
- package/dist/index.js +512 -0
- package/dist/index.js.map +1 -0
- package/package.json +43 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
import { Transform, TransformCallback } from 'node:stream';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Opus application modes.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* const encoder = new OpusEncoder({
|
|
9
|
+
* sampleRate: 48000,
|
|
10
|
+
* channels: 2,
|
|
11
|
+
* application: 'audio',
|
|
12
|
+
* });
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
type OpusApplication = "voip" | "audio" | "restricted_lowdelay";
|
|
16
|
+
/**
|
|
17
|
+
* Opus signal type hints.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* encoder.setSignal('music');
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
type OpusSignalType = "voice" | "music";
|
|
25
|
+
/**
|
|
26
|
+
* Configuration options for creating an Opus encoder.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* const options: OpusEncoderOptions = {
|
|
31
|
+
* sampleRate: 48000,
|
|
32
|
+
* channels: 2,
|
|
33
|
+
* application: 'audio',
|
|
34
|
+
* bitrate: 128000,
|
|
35
|
+
* };
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
interface OpusEncoderOptions {
|
|
39
|
+
readonly sampleRate: (typeof OPUS_SAMPLE_RATES)[number];
|
|
40
|
+
readonly channels: (typeof OPUS_CHANNELS)[number];
|
|
41
|
+
readonly application: OpusApplication;
|
|
42
|
+
readonly bitrate?: number;
|
|
43
|
+
readonly complexity?: number;
|
|
44
|
+
readonly fec?: boolean;
|
|
45
|
+
readonly packetLossPercent?: number;
|
|
46
|
+
readonly dtx?: boolean;
|
|
47
|
+
readonly vbr?: boolean;
|
|
48
|
+
readonly signal?: OpusSignalType;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Configuration options for creating an Opus decoder.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* const decoder = new OpusDecoder({ sampleRate: 48000, channels: 2 });
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
interface OpusDecoderOptions {
|
|
59
|
+
readonly sampleRate: (typeof OPUS_SAMPLE_RATES)[number];
|
|
60
|
+
readonly channels: (typeof OPUS_CHANNELS)[number];
|
|
61
|
+
}
|
|
62
|
+
/** Valid Opus sample rates. */
|
|
63
|
+
declare const OPUS_SAMPLE_RATES: readonly [8000, 12000, 16000, 24000, 48000];
|
|
64
|
+
/** Valid Opus channel counts. */
|
|
65
|
+
declare const OPUS_CHANNELS: readonly [1, 2];
|
|
66
|
+
/** Valid Opus frame durations in milliseconds. */
|
|
67
|
+
declare const OPUS_FRAME_DURATIONS: readonly [2.5, 5, 10, 20, 40, 60];
|
|
68
|
+
/** Discord's required Opus sample rate. */
|
|
69
|
+
declare const DISCORD_OPUS_SAMPLE_RATE: 48000;
|
|
70
|
+
/** Discord's required Opus channel count (stereo). */
|
|
71
|
+
declare const DISCORD_OPUS_CHANNELS: 2;
|
|
72
|
+
/** Discord's standard Opus frame duration in milliseconds. */
|
|
73
|
+
declare const DISCORD_OPUS_FRAME_DURATION: 20;
|
|
74
|
+
/** Discord Opus frame size in samples per channel. */
|
|
75
|
+
declare const DISCORD_OPUS_FRAME_SIZE: 960;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* High-performance Opus encoder backed by native Rust bindings.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* import { OpusEncoder } from '@harmonia/codec';
|
|
83
|
+
*
|
|
84
|
+
* const encoder = new OpusEncoder({
|
|
85
|
+
* sampleRate: 48000,
|
|
86
|
+
* channels: 2,
|
|
87
|
+
* application: 'audio',
|
|
88
|
+
* });
|
|
89
|
+
*
|
|
90
|
+
* const encoded = encoder.encode(pcmBuffer);
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
declare class OpusEncoder {
|
|
94
|
+
private readonly native;
|
|
95
|
+
private readonly _sampleRate;
|
|
96
|
+
private readonly _channels;
|
|
97
|
+
private readonly _application;
|
|
98
|
+
constructor(options: OpusEncoderOptions);
|
|
99
|
+
/**
|
|
100
|
+
* Encode 16-bit PCM audio to Opus.
|
|
101
|
+
*
|
|
102
|
+
* @param pcm - Buffer containing interleaved 16-bit signed integer PCM samples
|
|
103
|
+
* @returns Encoded Opus packet
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```ts
|
|
107
|
+
* const opus = encoder.encode(pcmBuffer);
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
encode(pcm: Buffer): Buffer;
|
|
111
|
+
/**
|
|
112
|
+
* Encode 32-bit float PCM audio to Opus.
|
|
113
|
+
*
|
|
114
|
+
* @param pcm - Buffer containing interleaved 32-bit float PCM samples
|
|
115
|
+
* @returns Encoded Opus packet
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```ts
|
|
119
|
+
* const opus = encoder.encodeFloat(floatPcmBuffer);
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
encodeFloat(pcm: Buffer): Buffer;
|
|
123
|
+
/**
|
|
124
|
+
* Set the encoder bitrate in bits per second.
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```ts
|
|
128
|
+
* encoder.setBitrate(128000);
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
setBitrate(bitrate: number): void;
|
|
132
|
+
/**
|
|
133
|
+
* Get the current encoder bitrate.
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```ts
|
|
137
|
+
* const bitrate = encoder.getBitrate();
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
getBitrate(): number;
|
|
141
|
+
/**
|
|
142
|
+
* Set encoding complexity (0-10, higher = better quality but slower).
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```ts
|
|
146
|
+
* encoder.setComplexity(10);
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
setComplexity(complexity: number): void;
|
|
150
|
+
/**
|
|
151
|
+
* Get the current encoding complexity.
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* ```ts
|
|
155
|
+
* const complexity = encoder.getComplexity();
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
getComplexity(): number;
|
|
159
|
+
/**
|
|
160
|
+
* Enable or disable forward error correction.
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```ts
|
|
164
|
+
* encoder.setFec(true);
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
setFec(enabled: boolean): void;
|
|
168
|
+
/**
|
|
169
|
+
* Check if FEC is enabled.
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```ts
|
|
173
|
+
* const fecEnabled = encoder.getFec();
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
getFec(): boolean;
|
|
177
|
+
/**
|
|
178
|
+
* Set expected packet loss percentage for FEC optimization.
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* ```ts
|
|
182
|
+
* encoder.setPacketLossPercent(10);
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
185
|
+
setPacketLossPercent(percent: number): void;
|
|
186
|
+
/**
|
|
187
|
+
* Enable or disable discontinuous transmission.
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* ```ts
|
|
191
|
+
* encoder.setDtx(true);
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
setDtx(enabled: boolean): void;
|
|
195
|
+
/**
|
|
196
|
+
* Enable or disable variable bitrate.
|
|
197
|
+
*
|
|
198
|
+
* @example
|
|
199
|
+
* ```ts
|
|
200
|
+
* encoder.setVbr(true);
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
setVbr(enabled: boolean): void;
|
|
204
|
+
/**
|
|
205
|
+
* Set the signal type hint.
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* ```ts
|
|
209
|
+
* encoder.setSignal('music');
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
setSignal(signal: OpusSignalType): void;
|
|
213
|
+
/**
|
|
214
|
+
* Reset the encoder state.
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* ```ts
|
|
218
|
+
* encoder.reset();
|
|
219
|
+
* ```
|
|
220
|
+
*/
|
|
221
|
+
reset(): void;
|
|
222
|
+
/** The sample rate this encoder operates at. */
|
|
223
|
+
get sampleRate(): number;
|
|
224
|
+
/** The number of channels this encoder operates with. */
|
|
225
|
+
get channels(): number;
|
|
226
|
+
/** The application mode this encoder was configured with. */
|
|
227
|
+
get application(): OpusApplication;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* High-performance Opus decoder backed by native Rust bindings.
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```ts
|
|
235
|
+
* import { OpusDecoder } from '@harmonia/codec';
|
|
236
|
+
*
|
|
237
|
+
* const decoder = new OpusDecoder({ sampleRate: 48000, channels: 2 });
|
|
238
|
+
* const pcm = decoder.decode(opusPacket);
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
declare class OpusDecoder {
|
|
242
|
+
private readonly native;
|
|
243
|
+
private readonly _sampleRate;
|
|
244
|
+
private readonly _channels;
|
|
245
|
+
constructor(options: OpusDecoderOptions);
|
|
246
|
+
/**
|
|
247
|
+
* Decode an Opus packet to 16-bit PCM.
|
|
248
|
+
*
|
|
249
|
+
* @param opusData - The Opus-encoded packet
|
|
250
|
+
* @returns Buffer containing decoded 16-bit PCM samples
|
|
251
|
+
*
|
|
252
|
+
* @example
|
|
253
|
+
* ```ts
|
|
254
|
+
* const pcm = decoder.decode(opusPacket);
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
257
|
+
decode(opusData: Buffer): Buffer;
|
|
258
|
+
/**
|
|
259
|
+
* Decode an Opus packet to 32-bit float PCM.
|
|
260
|
+
*
|
|
261
|
+
* @param opusData - The Opus-encoded packet
|
|
262
|
+
* @returns Buffer containing decoded 32-bit float PCM samples
|
|
263
|
+
*
|
|
264
|
+
* @example
|
|
265
|
+
* ```ts
|
|
266
|
+
* const pcm = decoder.decodeFloat(opusPacket);
|
|
267
|
+
* ```
|
|
268
|
+
*/
|
|
269
|
+
decodeFloat(opusData: Buffer): Buffer;
|
|
270
|
+
/**
|
|
271
|
+
* Decode with forward error correction from a previous packet.
|
|
272
|
+
*
|
|
273
|
+
* @param opusData - The Opus packet to attempt FEC recovery from
|
|
274
|
+
* @param frameSize - Number of samples per channel expected
|
|
275
|
+
* @returns Buffer containing recovered PCM
|
|
276
|
+
*
|
|
277
|
+
* @example
|
|
278
|
+
* ```ts
|
|
279
|
+
* const recovered = decoder.decodeFec(previousPacket, 960);
|
|
280
|
+
* ```
|
|
281
|
+
*/
|
|
282
|
+
decodeFec(opusData: Buffer, frameSize: number): Buffer;
|
|
283
|
+
/**
|
|
284
|
+
* Perform packet loss concealment (no input packet available).
|
|
285
|
+
*
|
|
286
|
+
* @param frameSize - Number of samples per channel to generate
|
|
287
|
+
* @returns Buffer containing concealed PCM
|
|
288
|
+
*
|
|
289
|
+
* @example
|
|
290
|
+
* ```ts
|
|
291
|
+
* const concealed = decoder.decodePlc(960);
|
|
292
|
+
* ```
|
|
293
|
+
*/
|
|
294
|
+
decodePlc(frameSize: number): Buffer;
|
|
295
|
+
/**
|
|
296
|
+
* Reset the decoder state.
|
|
297
|
+
*
|
|
298
|
+
* @example
|
|
299
|
+
* ```ts
|
|
300
|
+
* decoder.reset();
|
|
301
|
+
* ```
|
|
302
|
+
*/
|
|
303
|
+
reset(): void;
|
|
304
|
+
/** The sample rate this decoder operates at. */
|
|
305
|
+
get sampleRate(): number;
|
|
306
|
+
/** The number of channels this decoder produces. */
|
|
307
|
+
get channels(): number;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Transform stream that encodes PCM to Opus.
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* ```ts
|
|
315
|
+
* import { OpusEncoderStream } from '@harmonia/codec';
|
|
316
|
+
*
|
|
317
|
+
* const stream = new OpusEncoderStream({
|
|
318
|
+
* sampleRate: 48000,
|
|
319
|
+
* channels: 2,
|
|
320
|
+
* application: 'audio',
|
|
321
|
+
* });
|
|
322
|
+
*
|
|
323
|
+
* pcmSource.pipe(stream).on('data', (opusPacket) => {
|
|
324
|
+
* // handle encoded packet
|
|
325
|
+
* });
|
|
326
|
+
* ```
|
|
327
|
+
*/
|
|
328
|
+
declare class OpusEncoderStream extends Transform {
|
|
329
|
+
private readonly encoder;
|
|
330
|
+
private readonly frameSize;
|
|
331
|
+
private readonly frameSizeBytes;
|
|
332
|
+
private pendingBuffer;
|
|
333
|
+
constructor(options: OpusEncoderOptions);
|
|
334
|
+
_transform(chunk: Buffer, _encoding: BufferEncoding, callback: TransformCallback): void;
|
|
335
|
+
_flush(callback: TransformCallback): void;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Transform stream that decodes Opus to PCM.
|
|
339
|
+
*
|
|
340
|
+
* @example
|
|
341
|
+
* ```ts
|
|
342
|
+
* import { OpusDecoderStream } from '@harmonia/codec';
|
|
343
|
+
*
|
|
344
|
+
* const stream = new OpusDecoderStream({ sampleRate: 48000, channels: 2 });
|
|
345
|
+
*
|
|
346
|
+
* opusSource.pipe(stream).on('data', (pcm) => {
|
|
347
|
+
* // handle decoded PCM
|
|
348
|
+
* });
|
|
349
|
+
* ```
|
|
350
|
+
*/
|
|
351
|
+
declare class OpusDecoderStream extends Transform {
|
|
352
|
+
private readonly decoder;
|
|
353
|
+
constructor(options: OpusDecoderOptions);
|
|
354
|
+
_transform(chunk: Buffer, _encoding: BufferEncoding, callback: TransformCallback): void;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Utilities for inspecting Opus packets without decoding.
|
|
359
|
+
*
|
|
360
|
+
* @example
|
|
361
|
+
* ```ts
|
|
362
|
+
* import { OpusPacket } from '@harmonia/codec';
|
|
363
|
+
*
|
|
364
|
+
* const channels = OpusPacket.getChannels(opusData);
|
|
365
|
+
* const frames = OpusPacket.getFrameCount(opusData);
|
|
366
|
+
* ```
|
|
367
|
+
*/
|
|
368
|
+
declare class OpusPacket {
|
|
369
|
+
/**
|
|
370
|
+
* Get the number of channels from an Opus packet header.
|
|
371
|
+
*
|
|
372
|
+
* @example
|
|
373
|
+
* ```ts
|
|
374
|
+
* const channels = OpusPacket.getChannels(opusPacket);
|
|
375
|
+
* ```
|
|
376
|
+
*/
|
|
377
|
+
static getChannels(packet: Buffer): number;
|
|
378
|
+
/**
|
|
379
|
+
* Get the number of frames in an Opus packet.
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* ```ts
|
|
383
|
+
* const frameCount = OpusPacket.getFrameCount(opusPacket);
|
|
384
|
+
* ```
|
|
385
|
+
*/
|
|
386
|
+
static getFrameCount(packet: Buffer): number;
|
|
387
|
+
/**
|
|
388
|
+
* Get samples per frame for a given sample rate.
|
|
389
|
+
*
|
|
390
|
+
* @example
|
|
391
|
+
* ```ts
|
|
392
|
+
* const spf = OpusPacket.getSamplesPerFrame(opusPacket, 48000);
|
|
393
|
+
* ```
|
|
394
|
+
*/
|
|
395
|
+
static getSamplesPerFrame(packet: Buffer, sampleRate: number): number;
|
|
396
|
+
private constructor();
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Error thrown by Opus codec operations.
|
|
401
|
+
*
|
|
402
|
+
* @example
|
|
403
|
+
* ```ts
|
|
404
|
+
* try {
|
|
405
|
+
* encoder.encode(buffer);
|
|
406
|
+
* } catch (error) {
|
|
407
|
+
* if (error instanceof HarmoniaCodecError) {
|
|
408
|
+
* console.error(error.code, error.message);
|
|
409
|
+
* }
|
|
410
|
+
* }
|
|
411
|
+
* ```
|
|
412
|
+
*/
|
|
413
|
+
declare class HarmoniaCodecError extends Error {
|
|
414
|
+
/**
|
|
415
|
+
* Machine-readable error code.
|
|
416
|
+
*/
|
|
417
|
+
readonly code: string;
|
|
418
|
+
/**
|
|
419
|
+
* Additional context about the error.
|
|
420
|
+
*/
|
|
421
|
+
readonly context: Record<string, unknown>;
|
|
422
|
+
constructor(code: string, message: string, context?: Record<string, unknown>);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
export { DISCORD_OPUS_CHANNELS, DISCORD_OPUS_FRAME_DURATION, DISCORD_OPUS_FRAME_SIZE, DISCORD_OPUS_SAMPLE_RATE, HarmoniaCodecError, OPUS_CHANNELS, OPUS_FRAME_DURATIONS, OPUS_SAMPLE_RATES, type OpusApplication, OpusDecoder, type OpusDecoderOptions, OpusDecoderStream, OpusEncoder, type OpusEncoderOptions, OpusEncoderStream, OpusPacket, type OpusSignalType };
|