@metatell/bot-realtime 0.0.9 → 0.0.10
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/create-transport.d.ts +21 -0
- package/dist/create-transport.d.ts.map +1 -0
- package/dist/create-transport.js +26 -0
- package/dist/create-transport.js.map +1 -0
- package/dist/create-transport.spec.d.ts +2 -0
- package/dist/create-transport.spec.d.ts.map +1 -0
- package/dist/create-transport.spec.js +70 -0
- package/dist/create-transport.spec.js.map +1 -0
- package/dist/errors.d.ts +6 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +5 -0
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/livekit.d.ts.map +1 -1
- package/dist/livekit.js +57 -5
- package/dist/livekit.js.map +1 -1
- package/dist/voice/agent-bridge.d.ts +13 -0
- package/dist/voice/agent-bridge.d.ts.map +1 -0
- package/dist/voice/agent-bridge.js +199 -0
- package/dist/voice/agent-bridge.js.map +1 -0
- package/dist/voice/agent-bridge.spec.d.ts +2 -0
- package/dist/voice/agent-bridge.spec.d.ts.map +1 -0
- package/dist/voice/agent-bridge.spec.js +339 -0
- package/dist/voice/agent-bridge.spec.js.map +1 -0
- package/dist/voice/frame-utils.d.ts +30 -0
- package/dist/voice/frame-utils.d.ts.map +1 -0
- package/dist/voice/frame-utils.js +63 -0
- package/dist/voice/frame-utils.js.map +1 -0
- package/dist/voice/frame-utils.spec.d.ts +2 -0
- package/dist/voice/frame-utils.spec.d.ts.map +1 -0
- package/dist/voice/frame-utils.spec.js +82 -0
- package/dist/voice/frame-utils.spec.js.map +1 -0
- package/dist/voice/types.d.ts +69 -0
- package/dist/voice/types.d.ts.map +1 -0
- package/dist/voice/types.js +2 -0
- package/dist/voice/types.js.map +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { InvalidAudioFrameError } from '../errors.js';
|
|
3
|
+
import { MockAdapter } from '../mock.js';
|
|
4
|
+
import { attachVoice } from './agent-bridge.js';
|
|
5
|
+
// Mock VoiceCapableClient
|
|
6
|
+
function createMockAgent() {
|
|
7
|
+
return {
|
|
8
|
+
sendVoiceFrame: vi.fn().mockRejectedValue(new Error('Voice not implemented')),
|
|
9
|
+
muteVoice: vi.fn().mockResolvedValue(undefined),
|
|
10
|
+
getSessionId: vi.fn().mockReturnValue('test-session-id'),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
describe('agent-bridge', () => {
|
|
14
|
+
let agent;
|
|
15
|
+
let transport;
|
|
16
|
+
let handlers;
|
|
17
|
+
beforeEach(async () => {
|
|
18
|
+
agent = createMockAgent();
|
|
19
|
+
transport = new MockAdapter();
|
|
20
|
+
// Spy on transport methods
|
|
21
|
+
vi.spyOn(transport, 'pushPcmFrame');
|
|
22
|
+
vi.spyOn(transport, 'startAudioPublisher');
|
|
23
|
+
vi.spyOn(transport, 'stopAudioPublisher');
|
|
24
|
+
// Connect transport for tests that need it
|
|
25
|
+
await transport.connect({
|
|
26
|
+
url: 'wss://test',
|
|
27
|
+
tokenProvider: async () => 'test-token',
|
|
28
|
+
});
|
|
29
|
+
handlers = {
|
|
30
|
+
onRemotePcm: vi.fn(),
|
|
31
|
+
getLocalPcmStream: vi.fn(),
|
|
32
|
+
};
|
|
33
|
+
});
|
|
34
|
+
afterEach(async () => {
|
|
35
|
+
await transport.disconnect();
|
|
36
|
+
vi.clearAllMocks();
|
|
37
|
+
});
|
|
38
|
+
describe('attachVoice', () => {
|
|
39
|
+
it('should return detach function', async () => {
|
|
40
|
+
const attachment = attachVoice(agent, transport, handlers);
|
|
41
|
+
expect(attachment).toHaveProperty('detach');
|
|
42
|
+
expect(typeof attachment.detach).toBe('function');
|
|
43
|
+
await attachment.detach();
|
|
44
|
+
});
|
|
45
|
+
it('should add audio topic if not present', async () => {
|
|
46
|
+
// MockAdapter has activeTopics
|
|
47
|
+
const mockTransport = transport;
|
|
48
|
+
const activeTopics = mockTransport.activeTopics;
|
|
49
|
+
activeTopics.delete('audio');
|
|
50
|
+
expect(activeTopics.has('audio')).toBe(false);
|
|
51
|
+
const attachment = attachVoice(agent, transport, handlers);
|
|
52
|
+
expect(activeTopics.has('audio')).toBe(true);
|
|
53
|
+
await attachment.detach();
|
|
54
|
+
});
|
|
55
|
+
it('should not add audio topic if disabled', async () => {
|
|
56
|
+
const mockTransport = transport;
|
|
57
|
+
const activeTopics = mockTransport.activeTopics;
|
|
58
|
+
activeTopics.delete('audio');
|
|
59
|
+
const attachment = attachVoice(agent, transport, handlers, {
|
|
60
|
+
enableTopicAutoAdd: false,
|
|
61
|
+
});
|
|
62
|
+
expect(activeTopics.has('audio')).toBe(false);
|
|
63
|
+
await attachment.detach();
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe('receive processing', () => {
|
|
67
|
+
it('should call onRemotePcm when audio data received', async () => {
|
|
68
|
+
const attachment = attachVoice(agent, transport, handlers);
|
|
69
|
+
// Wait for mock audio to be emitted (participant joins after 100ms, then audio starts)
|
|
70
|
+
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
71
|
+
expect(handlers.onRemotePcm).toHaveBeenCalled();
|
|
72
|
+
const mockHandler = handlers.onRemotePcm;
|
|
73
|
+
const call = mockHandler.mock.calls[0];
|
|
74
|
+
expect(call[0]).toBeInstanceOf(Int16Array);
|
|
75
|
+
expect(call[0].length).toBe(960); // 20ms at 48kHz
|
|
76
|
+
expect(call[1]).toMatchObject({ fromIdentity: 'mock-participant' });
|
|
77
|
+
await attachment.detach();
|
|
78
|
+
});
|
|
79
|
+
it('should handle onRemotePcm errors gracefully', async () => {
|
|
80
|
+
handlers.onRemotePcm = vi.fn().mockRejectedValue(new Error('Handler error'));
|
|
81
|
+
const attachment = attachVoice(agent, transport, handlers);
|
|
82
|
+
// Should not throw even if handler fails
|
|
83
|
+
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
84
|
+
expect(handlers.onRemotePcm).toHaveBeenCalled();
|
|
85
|
+
await attachment.detach();
|
|
86
|
+
});
|
|
87
|
+
it('should not setup receive if no handler', async () => {
|
|
88
|
+
delete handlers.onRemotePcm;
|
|
89
|
+
const mockTransport = transport;
|
|
90
|
+
const listenersCount = mockTransport.listeners.size;
|
|
91
|
+
const attachment = attachVoice(agent, transport, handlers);
|
|
92
|
+
// No new listener should be added
|
|
93
|
+
expect(mockTransport.listeners.size).toBe(listenersCount);
|
|
94
|
+
await attachment.detach();
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
describe('send patching', () => {
|
|
98
|
+
it('should patch sendVoiceFrame to use transport', async () => {
|
|
99
|
+
// Set autoStartPublish to true and provide a stream
|
|
100
|
+
handlers.getLocalPcmStream = vi.fn().mockImplementation(async function* () {
|
|
101
|
+
yield new Int16Array(960);
|
|
102
|
+
});
|
|
103
|
+
const attachment = attachVoice(agent, transport, handlers, {
|
|
104
|
+
autoStartPublish: true,
|
|
105
|
+
});
|
|
106
|
+
// Wait for auto publish to start
|
|
107
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
108
|
+
// Start audio publisher first
|
|
109
|
+
await transport.startAudioPublisher();
|
|
110
|
+
const pcm = new Int16Array(960); // 20ms frame
|
|
111
|
+
await agent.sendVoiceFrame?.(pcm);
|
|
112
|
+
expect(transport.pushPcmFrame).toHaveBeenCalledWith(pcm);
|
|
113
|
+
await attachment.detach();
|
|
114
|
+
});
|
|
115
|
+
it('should validate frame size for 20ms', async () => {
|
|
116
|
+
const attachment = attachVoice(agent, transport, handlers, {
|
|
117
|
+
frameDurationMs: 20,
|
|
118
|
+
});
|
|
119
|
+
const invalidPcm = new Int16Array(480); // Wrong size for 20ms
|
|
120
|
+
await expect(agent.sendVoiceFrame?.(invalidPcm)).rejects.toThrow(InvalidAudioFrameError);
|
|
121
|
+
await expect(agent.sendVoiceFrame?.(invalidPcm)).rejects.toThrow('expected=960');
|
|
122
|
+
await attachment.detach();
|
|
123
|
+
});
|
|
124
|
+
it('should validate frame size for 10ms', async () => {
|
|
125
|
+
const attachment = attachVoice(agent, transport, handlers, {
|
|
126
|
+
frameDurationMs: 10,
|
|
127
|
+
});
|
|
128
|
+
await transport.startAudioPublisher();
|
|
129
|
+
const validPcm = new Int16Array(480); // Correct for 10ms
|
|
130
|
+
await agent.sendVoiceFrame?.(validPcm);
|
|
131
|
+
expect(transport.pushPcmFrame).toHaveBeenCalledWith(validPcm);
|
|
132
|
+
const invalidPcm = new Int16Array(960); // Wrong size for 10ms
|
|
133
|
+
await expect(agent.sendVoiceFrame?.(invalidPcm)).rejects.toThrow('expected=480');
|
|
134
|
+
await attachment.detach();
|
|
135
|
+
});
|
|
136
|
+
it('should restore original sendVoiceFrame after detach', async () => {
|
|
137
|
+
const _originalSendVoice = agent.sendVoiceFrame;
|
|
138
|
+
const attachment = attachVoice(agent, transport, handlers);
|
|
139
|
+
await transport.startAudioPublisher();
|
|
140
|
+
// Patched version works
|
|
141
|
+
const pcm = new Int16Array(960);
|
|
142
|
+
await agent.sendVoiceFrame?.(pcm);
|
|
143
|
+
expect(transport.pushPcmFrame).toHaveBeenCalled();
|
|
144
|
+
await attachment.detach();
|
|
145
|
+
// Original throws again
|
|
146
|
+
await expect(agent.sendVoiceFrame?.(pcm)).rejects.toThrow('Voice not implemented');
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
describe('mute control', () => {
|
|
150
|
+
it('should patch muteVoice to use transport', async () => {
|
|
151
|
+
transport.setMicEnabled = vi.fn();
|
|
152
|
+
const attachment = attachVoice(agent, transport, handlers);
|
|
153
|
+
await agent.muteVoice?.(true);
|
|
154
|
+
expect(transport.setMicEnabled).toHaveBeenCalledWith(false);
|
|
155
|
+
await agent.muteVoice?.(false);
|
|
156
|
+
expect(transport.setMicEnabled).toHaveBeenCalledWith(true);
|
|
157
|
+
await attachment.detach();
|
|
158
|
+
});
|
|
159
|
+
it('should fallback to original if no setMicEnabled', async () => {
|
|
160
|
+
// Create a transport without setMicEnabled
|
|
161
|
+
const transportNoMic = new MockAdapter();
|
|
162
|
+
await transportNoMic.connect({
|
|
163
|
+
url: 'wss://test',
|
|
164
|
+
tokenProvider: async () => 'test-token',
|
|
165
|
+
});
|
|
166
|
+
// Spy on transport to verify setMicEnabled is not called
|
|
167
|
+
const setMicSpy = vi.spyOn(transportNoMic, 'setMicEnabled');
|
|
168
|
+
delete transportNoMic
|
|
169
|
+
.setMicEnabled;
|
|
170
|
+
const attachment = attachVoice(agent, transportNoMic, handlers);
|
|
171
|
+
// muteVoice should work without error (fallback to original)
|
|
172
|
+
await expect(agent.muteVoice?.(true)).resolves.toBeUndefined();
|
|
173
|
+
// Verify setMicEnabled was not called (it doesn't exist)
|
|
174
|
+
expect(setMicSpy).not.toHaveBeenCalled();
|
|
175
|
+
// Verify function was patched (it's a different function now)
|
|
176
|
+
const patchedFunction = agent.muteVoice;
|
|
177
|
+
await attachment.detach();
|
|
178
|
+
// Verify function was restored
|
|
179
|
+
expect(agent.muteVoice).not.toBe(patchedFunction);
|
|
180
|
+
await transportNoMic.disconnect();
|
|
181
|
+
});
|
|
182
|
+
it('should restore original muteVoice after detach', async () => {
|
|
183
|
+
transport.setMicEnabled = vi.fn();
|
|
184
|
+
const originalMute = agent.muteVoice;
|
|
185
|
+
const attachment = attachVoice(agent, transport, handlers);
|
|
186
|
+
await agent.muteVoice?.(true);
|
|
187
|
+
expect(transport.setMicEnabled).toHaveBeenCalled();
|
|
188
|
+
await attachment.detach();
|
|
189
|
+
// Clear previous calls
|
|
190
|
+
vi.clearAllMocks();
|
|
191
|
+
await agent.muteVoice?.(false);
|
|
192
|
+
expect(transport.setMicEnabled).not.toHaveBeenCalled();
|
|
193
|
+
expect(originalMute).toHaveBeenCalledWith(false);
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
describe('auto publish', () => {
|
|
197
|
+
it('should start publisher when autoStartPublish is true', async () => {
|
|
198
|
+
handlers.getLocalPcmStream = vi.fn().mockImplementation(async function* () {
|
|
199
|
+
yield new Int16Array(960);
|
|
200
|
+
});
|
|
201
|
+
const attachment = attachVoice(agent, transport, handlers, {
|
|
202
|
+
autoStartPublish: true,
|
|
203
|
+
});
|
|
204
|
+
// Give time for async start
|
|
205
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
206
|
+
expect(transport.startAudioPublisher).toHaveBeenCalled();
|
|
207
|
+
expect(handlers.getLocalPcmStream).toHaveBeenCalled();
|
|
208
|
+
await attachment.detach();
|
|
209
|
+
});
|
|
210
|
+
it('should not start publisher when autoStartPublish is false', async () => {
|
|
211
|
+
const attachment = attachVoice(agent, transport, handlers, {
|
|
212
|
+
autoStartPublish: false,
|
|
213
|
+
});
|
|
214
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
215
|
+
expect(transport.startAudioPublisher).not.toHaveBeenCalled();
|
|
216
|
+
await attachment.detach();
|
|
217
|
+
});
|
|
218
|
+
it('should handle stream chunks with different sizes', async () => {
|
|
219
|
+
const frames = [];
|
|
220
|
+
transport.pushPcmFrame = vi.fn().mockImplementation(async (frame) => {
|
|
221
|
+
frames.push(frame);
|
|
222
|
+
});
|
|
223
|
+
handlers.getLocalPcmStream = vi.fn().mockImplementation(async function* () {
|
|
224
|
+
yield new Int16Array(1920); // 40ms - will be chunked
|
|
225
|
+
yield new Int16Array(480); // 10ms - will be padded
|
|
226
|
+
yield new Int16Array(960); // 20ms - exact
|
|
227
|
+
});
|
|
228
|
+
const attachment = attachVoice(agent, transport, handlers, {
|
|
229
|
+
frameDurationMs: 20,
|
|
230
|
+
});
|
|
231
|
+
// Wait for processing
|
|
232
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
233
|
+
// Should have received proper frames
|
|
234
|
+
expect(frames.length).toBeGreaterThanOrEqual(3);
|
|
235
|
+
expect(frames.every((f) => f.length === 960)).toBe(true);
|
|
236
|
+
await attachment.detach();
|
|
237
|
+
});
|
|
238
|
+
it('should stop on detach', async () => {
|
|
239
|
+
let keepRunning = true;
|
|
240
|
+
handlers.getLocalPcmStream = vi.fn().mockImplementation(async function* () {
|
|
241
|
+
while (keepRunning) {
|
|
242
|
+
yield new Int16Array(960);
|
|
243
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
const attachment = attachVoice(agent, transport, handlers);
|
|
247
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
248
|
+
const mockPushPcm = transport.pushPcmFrame;
|
|
249
|
+
const callCount = mockPushPcm.mock.calls.length;
|
|
250
|
+
expect(callCount).toBeGreaterThan(0);
|
|
251
|
+
keepRunning = false;
|
|
252
|
+
await attachment.detach();
|
|
253
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
254
|
+
expect(transport.stopAudioPublisher).toHaveBeenCalled();
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
describe('multiple attachments', () => {
|
|
258
|
+
it('should detach previous when attaching again', async () => {
|
|
259
|
+
// This test verifies that multiple attachments are properly managed
|
|
260
|
+
// and the previous attachment is auto-detached
|
|
261
|
+
// First attachment
|
|
262
|
+
const attachment1 = attachVoice(agent, transport, handlers);
|
|
263
|
+
// Verify patching occurred
|
|
264
|
+
const patchedFunction1 = agent.sendVoiceFrame;
|
|
265
|
+
// Second attachment - should auto-detach first
|
|
266
|
+
const attachment2 = attachVoice(agent, transport, handlers);
|
|
267
|
+
// Verify it's a new patched function
|
|
268
|
+
const patchedFunction2 = agent.sendVoiceFrame;
|
|
269
|
+
expect(patchedFunction2).not.toBe(patchedFunction1);
|
|
270
|
+
// Manually detach second attachment
|
|
271
|
+
await attachment2.detach();
|
|
272
|
+
// Verify detach is idempotent (safe to call multiple times)
|
|
273
|
+
await attachment1.detach();
|
|
274
|
+
await attachment2.detach();
|
|
275
|
+
// Function should be restored (will throw original error)
|
|
276
|
+
// Note: The restored function is a bound version, not the exact original reference
|
|
277
|
+
const restoredFunction = agent.sendVoiceFrame;
|
|
278
|
+
expect(restoredFunction).not.toBe(patchedFunction1);
|
|
279
|
+
expect(restoredFunction).not.toBe(patchedFunction2);
|
|
280
|
+
});
|
|
281
|
+
it('should handle multiple agents independently', async () => {
|
|
282
|
+
const agent2 = createMockAgent();
|
|
283
|
+
const transport2 = new MockAdapter();
|
|
284
|
+
vi.spyOn(transport2, 'pushPcmFrame');
|
|
285
|
+
await transport2.connect({
|
|
286
|
+
url: 'wss://test',
|
|
287
|
+
tokenProvider: async () => 'test-token',
|
|
288
|
+
});
|
|
289
|
+
const attachment1 = attachVoice(agent, transport, handlers);
|
|
290
|
+
const attachment2 = attachVoice(agent2, transport2, handlers);
|
|
291
|
+
await transport.startAudioPublisher();
|
|
292
|
+
await transport2.startAudioPublisher();
|
|
293
|
+
const pcm = new Int16Array(960);
|
|
294
|
+
await agent.sendVoiceFrame?.(pcm);
|
|
295
|
+
await agent2.sendVoiceFrame?.(pcm);
|
|
296
|
+
expect(transport.pushPcmFrame).toHaveBeenCalledWith(pcm);
|
|
297
|
+
expect(transport2.pushPcmFrame).toHaveBeenCalledWith(pcm);
|
|
298
|
+
await attachment1.detach();
|
|
299
|
+
// agent1 restored, agent2 still patched
|
|
300
|
+
await expect(agent.sendVoiceFrame?.(pcm)).rejects.toThrow('Voice not implemented');
|
|
301
|
+
await agent2.sendVoiceFrame?.(pcm);
|
|
302
|
+
await attachment2.detach();
|
|
303
|
+
await transport2.disconnect();
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
describe('error handling', () => {
|
|
307
|
+
it('should handle publisher start failure', async () => {
|
|
308
|
+
transport.startAudioPublisher = vi.fn().mockRejectedValue(new Error('Start failed'));
|
|
309
|
+
handlers.getLocalPcmStream = vi.fn().mockImplementation(async function* () {
|
|
310
|
+
yield new Int16Array(960);
|
|
311
|
+
});
|
|
312
|
+
// Should not throw
|
|
313
|
+
const attachment = attachVoice(agent, transport, handlers);
|
|
314
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
315
|
+
await attachment.detach();
|
|
316
|
+
});
|
|
317
|
+
it('should handle stream errors', async () => {
|
|
318
|
+
handlers.getLocalPcmStream = vi.fn().mockImplementation(async function* () {
|
|
319
|
+
yield new Int16Array(960);
|
|
320
|
+
throw new Error('Stream error');
|
|
321
|
+
});
|
|
322
|
+
const attachment = attachVoice(agent, transport, handlers);
|
|
323
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
324
|
+
// Should have processed first frame before error
|
|
325
|
+
expect(transport.pushPcmFrame).toHaveBeenCalledTimes(1);
|
|
326
|
+
await attachment.detach();
|
|
327
|
+
});
|
|
328
|
+
it('should handle detach errors gracefully', async () => {
|
|
329
|
+
transport.stopAudioPublisher = vi.fn().mockRejectedValue(new Error('Stop failed'));
|
|
330
|
+
const attachment = attachVoice(agent, transport, handlers);
|
|
331
|
+
await transport.startAudioPublisher();
|
|
332
|
+
// Should not throw
|
|
333
|
+
await attachment.detach();
|
|
334
|
+
// Methods should still be restored
|
|
335
|
+
await expect(agent.sendVoiceFrame?.(new Int16Array(960))).rejects.toThrow('Voice not implemented');
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
//# sourceMappingURL=agent-bridge.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-bridge.spec.js","sourceRoot":"","sources":["../../src/voice/agent-bridge.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* フレーム処理ユーティリティ
|
|
3
|
+
* ブリッジ内でのフレーム整形(chunk/pad/truncate)を提供
|
|
4
|
+
* resampleは行わない(SDK側のpcm-utilsを利用してもらう)
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Uint8Array → Int16Array のビュー化(コピー回避, LE前提)
|
|
8
|
+
* @param u8 - 入力バイト配列
|
|
9
|
+
* @returns Int16Arrayビュー
|
|
10
|
+
*/
|
|
11
|
+
export declare function toInt16View(u8: Uint8Array): Int16Array;
|
|
12
|
+
/**
|
|
13
|
+
* 入力 Int16Array を expectedSamples のフレーム群に整える
|
|
14
|
+
* - 短い:zero-pad
|
|
15
|
+
* - 長い:切り出し(余りもpadして出力)
|
|
16
|
+
* - ちょうど:そのまま
|
|
17
|
+
*
|
|
18
|
+
* @param src - 入力PCMデータ
|
|
19
|
+
* @param expectedSamples - 期待されるサンプル数(480 or 960)
|
|
20
|
+
* @yields 整形されたフレーム
|
|
21
|
+
*/
|
|
22
|
+
export declare function chunkToFrames(src: Int16Array, expectedSamples: number): Generator<Int16Array, void, unknown>;
|
|
23
|
+
/**
|
|
24
|
+
* フレーム検証用ヘルパー
|
|
25
|
+
* @param frame - 検証対象のフレーム
|
|
26
|
+
* @param expectedSamples - 期待されるサンプル数
|
|
27
|
+
* @returns 有効なフレームかどうか
|
|
28
|
+
*/
|
|
29
|
+
export declare function isValidFrame(frame: Int16Array, expectedSamples: number): boolean;
|
|
30
|
+
//# sourceMappingURL=frame-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame-utils.d.ts","sourceRoot":"","sources":["../../src/voice/frame-utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,UAAU,GAAG,UAAU,CAItD;AAED;;;;;;;;;GASG;AACH,wBAAiB,aAAa,CAC5B,GAAG,EAAE,UAAU,EACf,eAAe,EAAE,MAAM,GACtB,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CA4BtC;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAEhF"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* フレーム処理ユーティリティ
|
|
3
|
+
* ブリッジ内でのフレーム整形(chunk/pad/truncate)を提供
|
|
4
|
+
* resampleは行わない(SDK側のpcm-utilsを利用してもらう)
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Uint8Array → Int16Array のビュー化(コピー回避, LE前提)
|
|
8
|
+
* @param u8 - 入力バイト配列
|
|
9
|
+
* @returns Int16Arrayビュー
|
|
10
|
+
*/
|
|
11
|
+
export function toInt16View(u8) {
|
|
12
|
+
// バイト長が奇数の場合は最後の1バイトを切り捨て
|
|
13
|
+
const length = Math.floor(u8.byteLength / 2);
|
|
14
|
+
return new Int16Array(u8.buffer, u8.byteOffset, length);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* 入力 Int16Array を expectedSamples のフレーム群に整える
|
|
18
|
+
* - 短い:zero-pad
|
|
19
|
+
* - 長い:切り出し(余りもpadして出力)
|
|
20
|
+
* - ちょうど:そのまま
|
|
21
|
+
*
|
|
22
|
+
* @param src - 入力PCMデータ
|
|
23
|
+
* @param expectedSamples - 期待されるサンプル数(480 or 960)
|
|
24
|
+
* @yields 整形されたフレーム
|
|
25
|
+
*/
|
|
26
|
+
export function* chunkToFrames(src, expectedSamples) {
|
|
27
|
+
// ちょうどの場合
|
|
28
|
+
if (src.length === expectedSamples) {
|
|
29
|
+
yield src;
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
// 長い場合:切り出し
|
|
33
|
+
if (src.length > expectedSamples) {
|
|
34
|
+
for (let i = 0; i < src.length; i += expectedSamples) {
|
|
35
|
+
const end = i + expectedSamples;
|
|
36
|
+
if (end <= src.length) {
|
|
37
|
+
// 完全なフレーム
|
|
38
|
+
yield src.subarray(i, end);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
// 最後の端数:zero-pad
|
|
42
|
+
const out = new Int16Array(expectedSamples);
|
|
43
|
+
out.set(src.subarray(i));
|
|
44
|
+
yield out;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
// 短い場合:zero-pad
|
|
50
|
+
const out = new Int16Array(expectedSamples);
|
|
51
|
+
out.set(src);
|
|
52
|
+
yield out;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* フレーム検証用ヘルパー
|
|
56
|
+
* @param frame - 検証対象のフレーム
|
|
57
|
+
* @param expectedSamples - 期待されるサンプル数
|
|
58
|
+
* @returns 有効なフレームかどうか
|
|
59
|
+
*/
|
|
60
|
+
export function isValidFrame(frame, expectedSamples) {
|
|
61
|
+
return frame.length === expectedSamples;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=frame-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame-utils.js","sourceRoot":"","sources":["../../src/voice/frame-utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,EAAc;IACxC,0BAA0B;IAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,UAAU,GAAG,CAAC,CAAC,CAAA;IAC5C,OAAO,IAAI,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;AACzD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,SAAS,CAAC,CAAC,aAAa,CAC5B,GAAe,EACf,eAAuB;IAEvB,UAAU;IACV,IAAI,GAAG,CAAC,MAAM,KAAK,eAAe,EAAE,CAAC;QACnC,MAAM,GAAG,CAAA;QACT,OAAM;IACR,CAAC;IAED,YAAY;IACZ,IAAI,GAAG,CAAC,MAAM,GAAG,eAAe,EAAE,CAAC;QACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,eAAe,EAAE,CAAC;YACrD,MAAM,GAAG,GAAG,CAAC,GAAG,eAAe,CAAA;YAC/B,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;gBACtB,UAAU;gBACV,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;YAC5B,CAAC;iBAAM,CAAC;gBACN,iBAAiB;gBACjB,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,eAAe,CAAC,CAAA;gBAC3C,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;gBACxB,MAAM,GAAG,CAAA;YACX,CAAC;QACH,CAAC;QACD,OAAM;IACR,CAAC;IAED,gBAAgB;IAChB,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,eAAe,CAAC,CAAA;IAC3C,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACZ,MAAM,GAAG,CAAA;AACX,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,KAAiB,EAAE,eAAuB;IACrE,OAAO,KAAK,CAAC,MAAM,KAAK,eAAe,CAAA;AACzC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame-utils.spec.d.ts","sourceRoot":"","sources":["../../src/voice/frame-utils.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { chunkToFrames, isValidFrame, toInt16View } from './frame-utils.js';
|
|
3
|
+
describe('frame-utils', () => {
|
|
4
|
+
describe('toInt16View', () => {
|
|
5
|
+
it('should convert Uint8Array to Int16Array view', () => {
|
|
6
|
+
const u8 = new Uint8Array([0x00, 0x01, 0x00, 0x02]);
|
|
7
|
+
const i16 = toInt16View(u8);
|
|
8
|
+
expect(i16.length).toBe(2);
|
|
9
|
+
expect(i16[0]).toBe(256); // 0x0100 in LE
|
|
10
|
+
expect(i16[1]).toBe(512); // 0x0200 in LE
|
|
11
|
+
});
|
|
12
|
+
it('should handle odd byte length by truncating', () => {
|
|
13
|
+
const u8 = new Uint8Array([0x00, 0x01, 0xff]); // 3 bytes
|
|
14
|
+
const i16 = toInt16View(u8);
|
|
15
|
+
expect(i16.length).toBe(1); // 最後の1バイトは切り捨て
|
|
16
|
+
expect(i16[0]).toBe(256);
|
|
17
|
+
});
|
|
18
|
+
it('should work with buffer offsets', () => {
|
|
19
|
+
const buffer = new ArrayBuffer(8);
|
|
20
|
+
const u8 = new Uint8Array(buffer, 2, 4); // offset=2, length=4
|
|
21
|
+
u8.set([0x00, 0x01, 0x00, 0x02]);
|
|
22
|
+
const i16 = toInt16View(u8);
|
|
23
|
+
expect(i16.length).toBe(2);
|
|
24
|
+
expect(i16.byteOffset).toBe(2);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
describe('chunkToFrames', () => {
|
|
28
|
+
it('should yield as-is when exact match', () => {
|
|
29
|
+
const src = new Int16Array(960); // 20ms frame
|
|
30
|
+
const frames = [...chunkToFrames(src, 960)];
|
|
31
|
+
expect(frames.length).toBe(1);
|
|
32
|
+
expect(frames[0]).toBe(src);
|
|
33
|
+
});
|
|
34
|
+
it('should zero-pad when shorter', () => {
|
|
35
|
+
const src = new Int16Array([1, 2, 3]); // 3 samples
|
|
36
|
+
const frames = [...chunkToFrames(src, 480)]; // expects 480
|
|
37
|
+
expect(frames.length).toBe(1);
|
|
38
|
+
expect(frames[0].length).toBe(480);
|
|
39
|
+
expect(frames[0][0]).toBe(1);
|
|
40
|
+
expect(frames[0][1]).toBe(2);
|
|
41
|
+
expect(frames[0][2]).toBe(3);
|
|
42
|
+
expect(frames[0][3]).toBe(0); // padded
|
|
43
|
+
expect(frames[0][479]).toBe(0); // padded
|
|
44
|
+
});
|
|
45
|
+
it('should chunk when longer', () => {
|
|
46
|
+
const src = new Int16Array(2400); // 50ms worth
|
|
47
|
+
for (let i = 0; i < src.length; i++) {
|
|
48
|
+
src[i] = i; // 識別用の値
|
|
49
|
+
}
|
|
50
|
+
const frames = [...chunkToFrames(src, 480)]; // 10ms chunks
|
|
51
|
+
expect(frames.length).toBe(5);
|
|
52
|
+
// 各フレームの検証
|
|
53
|
+
for (let i = 0; i < 5; i++) {
|
|
54
|
+
expect(frames[i].length).toBe(480);
|
|
55
|
+
expect(frames[i][0]).toBe(i * 480);
|
|
56
|
+
expect(frames[i][479]).toBe(i * 480 + 479);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
it('should pad remainder when not divisible', () => {
|
|
60
|
+
const src = new Int16Array(1000); // 960 + 40
|
|
61
|
+
const frames = [...chunkToFrames(src, 960)];
|
|
62
|
+
expect(frames.length).toBe(2);
|
|
63
|
+
expect(frames[0].length).toBe(960);
|
|
64
|
+
expect(frames[1].length).toBe(960); // 40 samples + 920 zeros
|
|
65
|
+
// 2番目のフレームの最後はゼロ
|
|
66
|
+
expect(frames[1][40]).toBe(0);
|
|
67
|
+
expect(frames[1][959]).toBe(0);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
describe('isValidFrame', () => {
|
|
71
|
+
it('should validate frame size', () => {
|
|
72
|
+
const valid480 = new Int16Array(480);
|
|
73
|
+
const valid960 = new Int16Array(960);
|
|
74
|
+
const invalid = new Int16Array(500);
|
|
75
|
+
expect(isValidFrame(valid480, 480)).toBe(true);
|
|
76
|
+
expect(isValidFrame(valid960, 960)).toBe(true);
|
|
77
|
+
expect(isValidFrame(invalid, 480)).toBe(false);
|
|
78
|
+
expect(isValidFrame(invalid, 960)).toBe(false);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
//# sourceMappingURL=frame-utils.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame-utils.spec.js","sourceRoot":"","sources":["../../src/voice/frame-utils.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { VoiceCapableClient } from '@metatell/bot-core';
|
|
2
|
+
import type { RealtimeTransport } from '../transport.js';
|
|
3
|
+
/**
|
|
4
|
+
* 音声メタデータ
|
|
5
|
+
*/
|
|
6
|
+
export interface VoiceMetadata {
|
|
7
|
+
/** 送信者のidentity */
|
|
8
|
+
fromIdentity?: string;
|
|
9
|
+
/** 送信者のSID(将来拡張) */
|
|
10
|
+
fromSid?: string;
|
|
11
|
+
/** トラックSID(将来拡張) */
|
|
12
|
+
trackSid?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 音声ハンドラー
|
|
16
|
+
*/
|
|
17
|
+
export interface VoiceHandlers {
|
|
18
|
+
/**
|
|
19
|
+
* 受信PCM処理(48kHz/PCM16/mono)
|
|
20
|
+
* @param pcm - 受信したPCMデータ
|
|
21
|
+
* @param meta - メタデータ
|
|
22
|
+
*/
|
|
23
|
+
onRemotePcm?: (pcm: Int16Array, meta: VoiceMetadata) => Promise<void> | void;
|
|
24
|
+
/**
|
|
25
|
+
* ローカルPCM供給元(TTS など)
|
|
26
|
+
* @returns 10ms/20ms のPCMフレームを返すAsyncIterable
|
|
27
|
+
*/
|
|
28
|
+
getLocalPcmStream?: () => AsyncIterable<Int16Array>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* attachVoice のオプション
|
|
32
|
+
*/
|
|
33
|
+
export interface AttachVoiceOptions {
|
|
34
|
+
/** フレーム長(ミリ秒) default: 20 */
|
|
35
|
+
frameDurationMs?: 10 | 20;
|
|
36
|
+
/** サンプルレート(情報目的、内部は48kHz固定) default: 48000 */
|
|
37
|
+
sampleRate?: 48000 | 24000 | 16000;
|
|
38
|
+
/** チャンネル数(送信は1ch必須) default: 1 */
|
|
39
|
+
channels?: 1 | 2;
|
|
40
|
+
/** 自動パブリッシュ開始 default: true */
|
|
41
|
+
autoStartPublish?: boolean;
|
|
42
|
+
/** audioトピックの自動追加 default: true */
|
|
43
|
+
enableTopicAutoAdd?: boolean;
|
|
44
|
+
/** ログタグ default: 'voice.bridge' */
|
|
45
|
+
loggerTag?: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* VoiceAttachment インターフェース
|
|
49
|
+
*/
|
|
50
|
+
export interface VoiceAttachment {
|
|
51
|
+
/** ブリッジを解除する */
|
|
52
|
+
detach(): Promise<void>;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 内部状態管理用(エクスポートしない)
|
|
56
|
+
*/
|
|
57
|
+
export interface AttachmentState {
|
|
58
|
+
agent: VoiceCapableClient;
|
|
59
|
+
transport: RealtimeTransport;
|
|
60
|
+
original: {
|
|
61
|
+
sendVoiceFrame?: VoiceCapableClient['sendVoiceFrame'];
|
|
62
|
+
muteVoice?: VoiceCapableClient['muteVoice'];
|
|
63
|
+
};
|
|
64
|
+
removeListener?: () => void;
|
|
65
|
+
abortController?: AbortController;
|
|
66
|
+
isPublishing: boolean;
|
|
67
|
+
expectedSamples: 480 | 960;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/voice/types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAExD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,mBAAmB;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,oBAAoB;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,oBAAoB;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAE5E;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,aAAa,CAAC,UAAU,CAAC,CAAA;CACpD;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,6BAA6B;IAC7B,eAAe,CAAC,EAAE,EAAE,GAAG,EAAE,CAAA;IACzB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAA;IAClC,kCAAkC;IAClC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;IAChB,+BAA+B;IAC/B,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,mCAAmC;IACnC,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,gBAAgB;IAChB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,kBAAkB,CAAA;IACzB,SAAS,EAAE,iBAAiB,CAAA;IAC5B,QAAQ,EAAE;QACR,cAAc,CAAC,EAAE,kBAAkB,CAAC,gBAAgB,CAAC,CAAA;QACrD,SAAS,CAAC,EAAE,kBAAkB,CAAC,WAAW,CAAC,CAAA;KAC5C,CAAA;IACD,cAAc,CAAC,EAAE,MAAM,IAAI,CAAA;IAC3B,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,YAAY,EAAE,OAAO,CAAA;IACrB,eAAe,EAAE,GAAG,GAAG,GAAG,CAAA;CAC3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/voice/types.ts"],"names":[],"mappings":""}
|