@ikonai/sdk 0.0.40 → 0.0.42
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/assets/{audio-capture-worker-Bnqb8-xb.js → audio-capture-worker-zx_Os6ad.js} +85 -85
- package/assets/{audio-playback-worker-CXmAFv0O.js → audio-playback-worker-CYoIqiGJ.js} +4 -2
- package/assets/index-Cns_7uAI.js +119 -0
- package/assets/index-D2GAzJKe.js +131 -0
- package/assets/libopus-BEPFPIM_.js +139 -0
- package/client/ikon-client-config.d.ts +3 -3
- package/index.js +961 -913
- package/media/ikon-audio-capture.d.ts +5 -3
- package/media/ikon-audio-playback.d.ts +14 -2
- package/media/ikon-video-playback.d.ts +2 -2
- package/package.json +1 -1
- package/utils/platform.d.ts +5 -0
- package/assets/index-C-9F_--I.js +0 -186
- package/assets/index-C3ZAK5YF.js +0 -170
- package/assets/libopus-BBY7KH2-.js +0 -169
- package/assets/libopus-simd-CQXMVirP.js +0 -169
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { IkonClient } from '../client/ikon-client';
|
|
2
2
|
export interface IkonAudioCaptureConfig {
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
* These mirror the playback
|
|
4
|
+
* Performance preferences for audio capture.
|
|
5
|
+
* These mirror the playback performance options where applicable.
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
performance?: {
|
|
8
8
|
/** Prefer WebCodecs AudioEncoder over WASM Opus. Default: false */
|
|
9
9
|
preferWebCodecs?: boolean;
|
|
10
10
|
};
|
|
@@ -18,6 +18,8 @@ export interface IkonAudioCaptureRequest {
|
|
|
18
18
|
}
|
|
19
19
|
export interface IkonAudioCaptureHandle {
|
|
20
20
|
captureId: string;
|
|
21
|
+
/** Whether the capture is still active (not stopped). On iOS, this becomes false after endSegment. */
|
|
22
|
+
readonly isActive: boolean;
|
|
21
23
|
startSegment(): void;
|
|
22
24
|
endSegment(): void;
|
|
23
25
|
stop(): Promise<void>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { IkonClient } from '../client/ikon-client';
|
|
2
2
|
export interface IkonAudioPlaybackConfig {
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Performance preferences for audio processing.
|
|
5
5
|
*
|
|
6
6
|
* The SDK prefers:
|
|
7
7
|
* - decode in a worker
|
|
@@ -10,7 +10,7 @@ export interface IkonAudioPlaybackConfig {
|
|
|
10
10
|
*
|
|
11
11
|
* All of these have fallbacks for restrictive embed environments.
|
|
12
12
|
*/
|
|
13
|
-
|
|
13
|
+
performance?: {
|
|
14
14
|
preferSharedArrayBuffer?: boolean;
|
|
15
15
|
preferAudioWorklet?: boolean;
|
|
16
16
|
preferWebCodecs?: boolean;
|
|
@@ -115,6 +115,18 @@ export declare class IkonAudioPlayback {
|
|
|
115
115
|
* Fast operation - reconnects nodes to destination.
|
|
116
116
|
*/
|
|
117
117
|
resume(): void;
|
|
118
|
+
/**
|
|
119
|
+
* Request recovery of the AudioContext. Call this when external factors
|
|
120
|
+
* (like audio capture stopping on iOS) may have disrupted playback.
|
|
121
|
+
*
|
|
122
|
+
* IMPORTANT: On iOS, this must be called synchronously from a user gesture handler
|
|
123
|
+
* (e.g., button click/release) to ensure the AudioContext can be recreated.
|
|
124
|
+
*/
|
|
125
|
+
requestRecovery(): void;
|
|
126
|
+
/**
|
|
127
|
+
* Set up audio worklet after recreating AudioContext on iOS.
|
|
128
|
+
*/
|
|
129
|
+
private setupAudioGraphAfterRecreate;
|
|
118
130
|
/**
|
|
119
131
|
* Dispose of resources. After calling this, the instance should not be reused.
|
|
120
132
|
*/
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { IkonClient } from '../client/ikon-client';
|
|
2
2
|
export interface IkonVideoPlaybackConfig {
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Performance preferences for video processing.
|
|
5
5
|
*
|
|
6
6
|
* The preferred path is decode + render inside a dedicated worker using OffscreenCanvas,
|
|
7
7
|
* which avoids scheduling heavy work on the UI thread during high-frequency streaming.
|
|
8
8
|
*/
|
|
9
|
-
|
|
9
|
+
performance?: {
|
|
10
10
|
preferOffscreenCanvas?: boolean;
|
|
11
11
|
};
|
|
12
12
|
}
|
package/package.json
CHANGED
package/assets/index-C-9F_--I.js
DELETED
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
let n = null, s = null;
|
|
2
|
-
const h = new Uint8Array([
|
|
3
|
-
0,
|
|
4
|
-
97,
|
|
5
|
-
115,
|
|
6
|
-
109,
|
|
7
|
-
// magic
|
|
8
|
-
1,
|
|
9
|
-
0,
|
|
10
|
-
0,
|
|
11
|
-
0,
|
|
12
|
-
// version
|
|
13
|
-
1,
|
|
14
|
-
5,
|
|
15
|
-
1,
|
|
16
|
-
96,
|
|
17
|
-
0,
|
|
18
|
-
1,
|
|
19
|
-
123,
|
|
20
|
-
// type section: () -> v128
|
|
21
|
-
3,
|
|
22
|
-
2,
|
|
23
|
-
1,
|
|
24
|
-
0,
|
|
25
|
-
// function section
|
|
26
|
-
10,
|
|
27
|
-
10,
|
|
28
|
-
1,
|
|
29
|
-
8,
|
|
30
|
-
0,
|
|
31
|
-
// code section start
|
|
32
|
-
65,
|
|
33
|
-
0,
|
|
34
|
-
// i32.const 0
|
|
35
|
-
253,
|
|
36
|
-
15,
|
|
37
|
-
// v128.load (SIMD)
|
|
38
|
-
253,
|
|
39
|
-
98,
|
|
40
|
-
// i32x4.extract_lane 0
|
|
41
|
-
11
|
|
42
|
-
// end
|
|
43
|
-
]);
|
|
44
|
-
async function d() {
|
|
45
|
-
try {
|
|
46
|
-
return WebAssembly.validate(h);
|
|
47
|
-
} catch {
|
|
48
|
-
return !1;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
async function m() {
|
|
52
|
-
return s || (n || (n = (async () => {
|
|
53
|
-
const r = await d();
|
|
54
|
-
let t;
|
|
55
|
-
r ? t = (await import("./libopus-simd-CQXMVirP.js")).default : t = (await import("./libopus-BBY7KH2-.js")).default;
|
|
56
|
-
const i = r ? "../wasm/libopus-simd.wasm" : "../wasm/libopus.wasm";
|
|
57
|
-
return s = await t({
|
|
58
|
-
locateFile: (e) => e.endsWith(".wasm") ? new URL(i, import.meta.url).href : e
|
|
59
|
-
}), s;
|
|
60
|
-
})()), n);
|
|
61
|
-
}
|
|
62
|
-
async function f() {
|
|
63
|
-
return d();
|
|
64
|
-
}
|
|
65
|
-
const p = 2048, u = 4002, a = 4010, _ = 4028, c = 4e3, l = 2880;
|
|
66
|
-
class P {
|
|
67
|
-
module = null;
|
|
68
|
-
encoder = 0;
|
|
69
|
-
channels;
|
|
70
|
-
sampleRate;
|
|
71
|
-
bitrate;
|
|
72
|
-
application;
|
|
73
|
-
// Pre-allocated WASM heap pointers
|
|
74
|
-
inputPtr = 0;
|
|
75
|
-
outputPtr = 0;
|
|
76
|
-
ready;
|
|
77
|
-
constructor(t) {
|
|
78
|
-
this.channels = t.channels, this.sampleRate = t.sampleRate, this.bitrate = t.bitrate ?? 32e3, this.application = t.application ?? p, this.ready = this.initialize(t);
|
|
79
|
-
}
|
|
80
|
-
async initialize(t) {
|
|
81
|
-
this.module = await m();
|
|
82
|
-
const i = this.module._malloc(4);
|
|
83
|
-
this.encoder = this.module._opus_encoder_create(
|
|
84
|
-
this.sampleRate,
|
|
85
|
-
this.channels,
|
|
86
|
-
this.application,
|
|
87
|
-
i
|
|
88
|
-
);
|
|
89
|
-
const e = new DataView(this.module.HEAPU8.buffer).getInt32(i, !0);
|
|
90
|
-
if (this.module._free(i), e !== 0)
|
|
91
|
-
throw new Error(`opus_encoder_create failed with error code ${e}`);
|
|
92
|
-
this.setEncoderCtl(u, this.bitrate), t.complexity !== void 0 && this.setEncoderCtl(a, t.complexity), this.inputPtr = this.module._malloc(l * this.channels * 4), this.outputPtr = this.module._malloc(c);
|
|
93
|
-
}
|
|
94
|
-
setEncoderCtl(t, i) {
|
|
95
|
-
if (!this.module || !this.encoder)
|
|
96
|
-
return;
|
|
97
|
-
const e = this.module._malloc(4);
|
|
98
|
-
new DataView(this.module.HEAPU8.buffer).setInt32(e, i, !0), this.module._opus_encoder_ctl(this.encoder, t, e), this.module._free(e);
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Encode PCM float samples to Opus.
|
|
102
|
-
*
|
|
103
|
-
* Returns a view into a pre-allocated buffer. The returned Uint8Array is reused
|
|
104
|
-
* on each call, so callers MUST copy the data if it needs to persist beyond
|
|
105
|
-
* the next encode call.
|
|
106
|
-
*
|
|
107
|
-
* @param pcmFloat - Interleaved float PCM samples (-1.0 to 1.0)
|
|
108
|
-
* @returns Opus-encoded audio data (view into internal buffer)
|
|
109
|
-
*/
|
|
110
|
-
encode(t) {
|
|
111
|
-
if (!this.module || !this.encoder)
|
|
112
|
-
throw new Error("Encoder not initialized");
|
|
113
|
-
const i = t.length / this.channels;
|
|
114
|
-
if (i > l)
|
|
115
|
-
throw new Error(`Frame size too large: ${i} > ${l} samples`);
|
|
116
|
-
const e = this.inputPtr / 4;
|
|
117
|
-
this.module.HEAPF32.set(t, e);
|
|
118
|
-
const o = this.module._opus_encode_float(
|
|
119
|
-
this.encoder,
|
|
120
|
-
this.inputPtr,
|
|
121
|
-
i,
|
|
122
|
-
this.outputPtr,
|
|
123
|
-
c
|
|
124
|
-
);
|
|
125
|
-
if (o < 0)
|
|
126
|
-
throw new Error(`opus_encode_float failed with error code ${o}`);
|
|
127
|
-
return new Uint8Array(this.module.HEAPU8.buffer, this.outputPtr, o);
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Encode and copy the result (when caller needs ownership).
|
|
131
|
-
* Use this when you need the encoded audio to persist, e.g., when sending to another thread.
|
|
132
|
-
*/
|
|
133
|
-
encodeAndCopy(t) {
|
|
134
|
-
return this.encode(t).slice();
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
|
-
* Reset the encoder state.
|
|
138
|
-
* Call this when there's a discontinuity in the audio stream.
|
|
139
|
-
*/
|
|
140
|
-
reset() {
|
|
141
|
-
this.module && this.encoder && this.module._opus_encoder_ctl(this.encoder, _);
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Set the encoder bitrate.
|
|
145
|
-
* @param bitrate - Target bitrate in bits per second
|
|
146
|
-
*/
|
|
147
|
-
setBitrate(t) {
|
|
148
|
-
this.setEncoderCtl(u, t);
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Set the encoder complexity (0-10, higher = better quality but more CPU).
|
|
152
|
-
* @param complexity - Complexity value (0-10)
|
|
153
|
-
*/
|
|
154
|
-
setComplexity(t) {
|
|
155
|
-
this.setEncoderCtl(a, t);
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Get the number of channels this encoder was created with.
|
|
159
|
-
*/
|
|
160
|
-
getChannels() {
|
|
161
|
-
return this.channels;
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* Get the sample rate this encoder was created with.
|
|
165
|
-
*/
|
|
166
|
-
getSampleRate() {
|
|
167
|
-
return this.sampleRate;
|
|
168
|
-
}
|
|
169
|
-
/**
|
|
170
|
-
* Release all resources.
|
|
171
|
-
* The encoder cannot be used after calling destroy().
|
|
172
|
-
*/
|
|
173
|
-
destroy() {
|
|
174
|
-
this.module && (this.encoder && this.module._opus_encoder_destroy(this.encoder), this.inputPtr && this.module._free(this.inputPtr), this.outputPtr && this.module._free(this.outputPtr)), this.encoder = 0, this.inputPtr = 0, this.outputPtr = 0, this.module = null;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
export {
|
|
178
|
-
c as MAX_PACKET_SIZE,
|
|
179
|
-
p as OPUS_APPLICATION_VOIP,
|
|
180
|
-
_ as OPUS_RESET_STATE,
|
|
181
|
-
u as OPUS_SET_BITRATE_REQUEST,
|
|
182
|
-
a as OPUS_SET_COMPLEXITY_REQUEST,
|
|
183
|
-
P as OpusEncoder,
|
|
184
|
-
m as getOpusModule,
|
|
185
|
-
f as isSimdSupported
|
|
186
|
-
};
|
package/assets/index-C3ZAK5YF.js
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
let a = null, i = null;
|
|
2
|
-
const c = new Uint8Array([
|
|
3
|
-
0,
|
|
4
|
-
97,
|
|
5
|
-
115,
|
|
6
|
-
109,
|
|
7
|
-
// magic
|
|
8
|
-
1,
|
|
9
|
-
0,
|
|
10
|
-
0,
|
|
11
|
-
0,
|
|
12
|
-
// version
|
|
13
|
-
1,
|
|
14
|
-
5,
|
|
15
|
-
1,
|
|
16
|
-
96,
|
|
17
|
-
0,
|
|
18
|
-
1,
|
|
19
|
-
123,
|
|
20
|
-
// type section: () -> v128
|
|
21
|
-
3,
|
|
22
|
-
2,
|
|
23
|
-
1,
|
|
24
|
-
0,
|
|
25
|
-
// function section
|
|
26
|
-
10,
|
|
27
|
-
10,
|
|
28
|
-
1,
|
|
29
|
-
8,
|
|
30
|
-
0,
|
|
31
|
-
// code section start
|
|
32
|
-
65,
|
|
33
|
-
0,
|
|
34
|
-
// i32.const 0
|
|
35
|
-
253,
|
|
36
|
-
15,
|
|
37
|
-
// v128.load (SIMD)
|
|
38
|
-
253,
|
|
39
|
-
98,
|
|
40
|
-
// i32x4.extract_lane 0
|
|
41
|
-
11
|
|
42
|
-
// end
|
|
43
|
-
]);
|
|
44
|
-
async function u() {
|
|
45
|
-
try {
|
|
46
|
-
return WebAssembly.validate(c);
|
|
47
|
-
} catch {
|
|
48
|
-
return !1;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
async function m() {
|
|
52
|
-
return i || (a || (a = (async () => {
|
|
53
|
-
const l = await u();
|
|
54
|
-
let e;
|
|
55
|
-
l ? e = (await import("./libopus-simd-CQXMVirP.js")).default : e = (await import("./libopus-BBY7KH2-.js")).default;
|
|
56
|
-
const t = l ? "../wasm/libopus-simd.wasm" : "../wasm/libopus.wasm";
|
|
57
|
-
return i = await e({
|
|
58
|
-
locateFile: (s) => s.endsWith(".wasm") ? new URL(t, import.meta.url).href : s
|
|
59
|
-
}), i;
|
|
60
|
-
})()), a);
|
|
61
|
-
}
|
|
62
|
-
const p = 4028, n = 5760, d = 4e3;
|
|
63
|
-
class f {
|
|
64
|
-
module = null;
|
|
65
|
-
decoder = 0;
|
|
66
|
-
channels;
|
|
67
|
-
sampleRate;
|
|
68
|
-
// Pre-allocated WASM heap pointers (allocated once, reused)
|
|
69
|
-
inputPtr = 0;
|
|
70
|
-
outputPtr = 0;
|
|
71
|
-
// Pre-allocated output arrays (reused, caller must copy if needed)
|
|
72
|
-
channelBuffers;
|
|
73
|
-
ready;
|
|
74
|
-
constructor(e) {
|
|
75
|
-
this.channels = e.channels, this.sampleRate = e.sampleRate, this.channelBuffers = Array.from({ length: this.channels }, () => new Float32Array(n)), this.ready = this.initialize();
|
|
76
|
-
}
|
|
77
|
-
async initialize() {
|
|
78
|
-
this.module = await m();
|
|
79
|
-
const e = this.module._malloc(4);
|
|
80
|
-
this.decoder = this.module._opus_decoder_create(this.sampleRate, this.channels, e);
|
|
81
|
-
const t = new DataView(this.module.HEAPU8.buffer).getInt32(e, !0);
|
|
82
|
-
if (this.module._free(e), t !== 0)
|
|
83
|
-
throw new Error(`opus_decoder_create failed with error code ${t}`);
|
|
84
|
-
this.inputPtr = this.module._malloc(d), this.outputPtr = this.module._malloc(n * this.channels * 4);
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Decode an Opus frame.
|
|
88
|
-
*
|
|
89
|
-
* Returns views into pre-allocated buffers. The channelData arrays are reused
|
|
90
|
-
* on each call, so callers MUST copy the data if it needs to persist beyond
|
|
91
|
-
* the next decode call.
|
|
92
|
-
*
|
|
93
|
-
* @param opusData - The Opus-encoded audio frame
|
|
94
|
-
* @returns Decoded audio with channel data and sample count
|
|
95
|
-
*/
|
|
96
|
-
decodeFrame(e) {
|
|
97
|
-
if (!this.module || !this.decoder)
|
|
98
|
-
throw new Error("Decoder not initialized");
|
|
99
|
-
if (e.length > d)
|
|
100
|
-
throw new Error(`Opus packet too large: ${e.length} > ${d}`);
|
|
101
|
-
this.module.HEAPU8.set(e, this.inputPtr);
|
|
102
|
-
const t = this.module._opus_decode_float(
|
|
103
|
-
this.decoder,
|
|
104
|
-
this.inputPtr,
|
|
105
|
-
e.length,
|
|
106
|
-
this.outputPtr,
|
|
107
|
-
n,
|
|
108
|
-
0
|
|
109
|
-
// decodeFec = false
|
|
110
|
-
);
|
|
111
|
-
if (t < 0)
|
|
112
|
-
throw new Error(`opus_decode_float failed with error code ${t}`);
|
|
113
|
-
const s = this.outputPtr / 4;
|
|
114
|
-
for (let r = 0; r < this.channels; r++) {
|
|
115
|
-
const h = this.channelBuffers[r];
|
|
116
|
-
for (let o = 0; o < t; o++)
|
|
117
|
-
h[o] = this.module.HEAPF32[s + o * this.channels + r];
|
|
118
|
-
}
|
|
119
|
-
return {
|
|
120
|
-
channelData: this.channelBuffers,
|
|
121
|
-
samplesDecoded: t,
|
|
122
|
-
sampleRate: this.sampleRate
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Decode a frame and copy the result (when caller needs ownership).
|
|
127
|
-
* Use this when you need the decoded audio to persist.
|
|
128
|
-
*/
|
|
129
|
-
decodeFrameAndCopy(e) {
|
|
130
|
-
const t = this.decodeFrame(e);
|
|
131
|
-
return {
|
|
132
|
-
channelData: t.channelData.map((s) => s.slice(0, t.samplesDecoded)),
|
|
133
|
-
samplesDecoded: t.samplesDecoded,
|
|
134
|
-
sampleRate: t.sampleRate
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Reset the decoder state.
|
|
139
|
-
* Call this when there's a discontinuity in the audio stream.
|
|
140
|
-
*/
|
|
141
|
-
reset() {
|
|
142
|
-
this.module && this.decoder && this.module._opus_decoder_ctl(this.decoder, p);
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* Get the number of channels this decoder was created with.
|
|
146
|
-
*/
|
|
147
|
-
getChannels() {
|
|
148
|
-
return this.channels;
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Get the sample rate this decoder was created with.
|
|
152
|
-
*/
|
|
153
|
-
getSampleRate() {
|
|
154
|
-
return this.sampleRate;
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Release all resources.
|
|
158
|
-
* The decoder cannot be used after calling destroy().
|
|
159
|
-
*/
|
|
160
|
-
destroy() {
|
|
161
|
-
this.module && (this.decoder && this.module._opus_decoder_destroy(this.decoder), this.inputPtr && this.module._free(this.inputPtr), this.outputPtr && this.module._free(this.outputPtr)), this.decoder = 0, this.inputPtr = 0, this.outputPtr = 0, this.module = null;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
export {
|
|
165
|
-
n as MAX_FRAME_SIZE,
|
|
166
|
-
d as MAX_PACKET_SIZE,
|
|
167
|
-
p as OPUS_RESET_STATE,
|
|
168
|
-
f as OpusDecoder,
|
|
169
|
-
m as getOpusModule
|
|
170
|
-
};
|