@vapi-ai/web 1.0.7 → 1.0.9
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/player.d.ts +3 -6
- package/dist/player.js +15 -41
- package/package.json +1 -1
- package/player.ts +17 -65
package/dist/player.d.ts
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import EventEmitter from "events";
|
|
3
3
|
export declare class ContinuousPlayer extends EventEmitter {
|
|
4
|
-
private
|
|
5
|
-
private
|
|
6
|
-
|
|
7
|
-
private crossFadeDuration;
|
|
8
|
-
constructor(crossFadeDuration?: number);
|
|
9
|
-
private createQueue;
|
|
4
|
+
private mediaSource;
|
|
5
|
+
private sourceBuffer;
|
|
6
|
+
constructor();
|
|
10
7
|
playChunk(audioData: ArrayBuffer): void;
|
|
11
8
|
clear(): Promise<void>;
|
|
12
9
|
}
|
package/dist/player.js
CHANGED
|
@@ -13,55 +13,29 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.ContinuousPlayer = void 0;
|
|
16
|
-
const async_1 = require("async"); // You need to install the async package
|
|
17
16
|
const events_1 = __importDefault(require("events"));
|
|
18
17
|
class ContinuousPlayer extends events_1.default {
|
|
19
|
-
constructor(
|
|
18
|
+
constructor() {
|
|
20
19
|
super();
|
|
21
|
-
this.
|
|
22
|
-
this.
|
|
23
|
-
this.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
createQueue() {
|
|
27
|
-
const q = (0, async_1.queue)((audioPromise, callback) => __awaiter(this, void 0, void 0, function* () {
|
|
28
|
-
const audioBuffer = yield audioPromise;
|
|
29
|
-
const source = this.audioCtx.createBufferSource();
|
|
30
|
-
source.buffer = audioBuffer;
|
|
31
|
-
source.connect(this.audioCtx.destination);
|
|
32
|
-
// Create a gain node for crossfading
|
|
33
|
-
const gainNode = this.audioCtx.createGain();
|
|
34
|
-
source.connect(gainNode);
|
|
35
|
-
gainNode.connect(this.audioCtx.destination);
|
|
36
|
-
// Start the source at the next start time
|
|
37
|
-
source.start(this.nextStartTime);
|
|
38
|
-
// Schedule the crossfade
|
|
39
|
-
gainNode.gain.setValueAtTime(0, this.nextStartTime);
|
|
40
|
-
gainNode.gain.linearRampToValueAtTime(1, this.nextStartTime + this.crossFadeDuration);
|
|
41
|
-
gainNode.gain.setValueAtTime(1, this.nextStartTime + audioBuffer.duration - this.crossFadeDuration);
|
|
42
|
-
gainNode.gain.linearRampToValueAtTime(0, this.nextStartTime + audioBuffer.duration);
|
|
43
|
-
source.onended = () => {
|
|
44
|
-
this.nextStartTime += audioBuffer.duration;
|
|
45
|
-
callback();
|
|
46
|
-
};
|
|
47
|
-
}), 1);
|
|
48
|
-
q.drain(() => {
|
|
49
|
-
this.emit("speech-end");
|
|
50
|
-
});
|
|
51
|
-
q.saturated(() => {
|
|
52
|
-
this.emit("speech-start");
|
|
53
|
-
});
|
|
54
|
-
return q;
|
|
20
|
+
this.sourceBuffer = null;
|
|
21
|
+
this.mediaSource = new MediaSource();
|
|
22
|
+
this.mediaSource.onsourceopen = () => {
|
|
23
|
+
this.sourceBuffer = this.mediaSource.addSourceBuffer('audio/webm; codecs="opus"');
|
|
24
|
+
};
|
|
55
25
|
}
|
|
56
26
|
playChunk(audioData) {
|
|
57
|
-
|
|
58
|
-
|
|
27
|
+
if (!this.sourceBuffer)
|
|
28
|
+
return;
|
|
29
|
+
console.log(this.mediaSource.readyState, this.sourceBuffer.updating);
|
|
30
|
+
if (this.mediaSource.readyState === "open" && !this.sourceBuffer.updating) {
|
|
31
|
+
this.sourceBuffer.appendBuffer(audioData);
|
|
32
|
+
}
|
|
59
33
|
}
|
|
60
34
|
clear() {
|
|
61
35
|
return __awaiter(this, void 0, void 0, function* () {
|
|
62
|
-
this.
|
|
63
|
-
|
|
64
|
-
|
|
36
|
+
if (this.sourceBuffer && this.mediaSource.readyState === "open") {
|
|
37
|
+
this.sourceBuffer.remove(0, this.sourceBuffer.buffered.end(0));
|
|
38
|
+
}
|
|
65
39
|
});
|
|
66
40
|
}
|
|
67
41
|
}
|
package/package.json
CHANGED
package/player.ts
CHANGED
|
@@ -1,78 +1,30 @@
|
|
|
1
|
-
import { QueueObject, queue } from "async"; // You need to install the async package
|
|
2
|
-
|
|
3
1
|
import EventEmitter from "events";
|
|
4
2
|
|
|
5
3
|
export class ContinuousPlayer extends EventEmitter {
|
|
6
|
-
private
|
|
7
|
-
private
|
|
8
|
-
private audioQueue: QueueObject<Promise<AudioBuffer>>;
|
|
9
|
-
private crossFadeDuration: number; // Duration of the crossfade
|
|
4
|
+
private mediaSource: MediaSource;
|
|
5
|
+
private sourceBuffer: SourceBuffer | null = null;
|
|
10
6
|
|
|
11
|
-
constructor(
|
|
7
|
+
constructor() {
|
|
12
8
|
super();
|
|
13
|
-
this.
|
|
14
|
-
this.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
private createQueue() {
|
|
20
|
-
const q = queue(
|
|
21
|
-
async (audioPromise: Promise<AudioBuffer>, callback: Function) => {
|
|
22
|
-
const audioBuffer = await audioPromise;
|
|
23
|
-
const source = this.audioCtx.createBufferSource();
|
|
24
|
-
source.buffer = audioBuffer;
|
|
25
|
-
source.connect(this.audioCtx.destination);
|
|
26
|
-
|
|
27
|
-
// Create a gain node for crossfading
|
|
28
|
-
const gainNode = this.audioCtx.createGain();
|
|
29
|
-
source.connect(gainNode);
|
|
30
|
-
gainNode.connect(this.audioCtx.destination);
|
|
31
|
-
|
|
32
|
-
// Start the source at the next start time
|
|
33
|
-
source.start(this.nextStartTime);
|
|
34
|
-
|
|
35
|
-
// Schedule the crossfade
|
|
36
|
-
gainNode.gain.setValueAtTime(0, this.nextStartTime);
|
|
37
|
-
gainNode.gain.linearRampToValueAtTime(
|
|
38
|
-
1,
|
|
39
|
-
this.nextStartTime + this.crossFadeDuration
|
|
40
|
-
);
|
|
41
|
-
gainNode.gain.setValueAtTime(
|
|
42
|
-
1,
|
|
43
|
-
this.nextStartTime + audioBuffer.duration - this.crossFadeDuration
|
|
44
|
-
);
|
|
45
|
-
gainNode.gain.linearRampToValueAtTime(
|
|
46
|
-
0,
|
|
47
|
-
this.nextStartTime + audioBuffer.duration
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
source.onended = () => {
|
|
51
|
-
this.nextStartTime += audioBuffer.duration;
|
|
52
|
-
callback();
|
|
53
|
-
};
|
|
54
|
-
},
|
|
55
|
-
1
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
q.drain(() => {
|
|
59
|
-
this.emit("speech-end");
|
|
60
|
-
});
|
|
61
|
-
q.saturated(() => {
|
|
62
|
-
this.emit("speech-start");
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
return q;
|
|
9
|
+
this.mediaSource = new MediaSource();
|
|
10
|
+
this.mediaSource.onsourceopen = () => {
|
|
11
|
+
this.sourceBuffer = this.mediaSource.addSourceBuffer(
|
|
12
|
+
'audio/webm; codecs="opus"'
|
|
13
|
+
);
|
|
14
|
+
};
|
|
66
15
|
}
|
|
67
16
|
|
|
68
17
|
playChunk(audioData: ArrayBuffer) {
|
|
69
|
-
|
|
70
|
-
this.
|
|
18
|
+
if (!this.sourceBuffer) return;
|
|
19
|
+
console.log(this.mediaSource.readyState, this.sourceBuffer.updating);
|
|
20
|
+
if (this.mediaSource.readyState === "open" && !this.sourceBuffer.updating) {
|
|
21
|
+
this.sourceBuffer.appendBuffer(audioData);
|
|
22
|
+
}
|
|
71
23
|
}
|
|
72
24
|
|
|
73
25
|
async clear() {
|
|
74
|
-
this.
|
|
75
|
-
|
|
76
|
-
|
|
26
|
+
if (this.sourceBuffer && this.mediaSource.readyState === "open") {
|
|
27
|
+
this.sourceBuffer.remove(0, this.sourceBuffer.buffered.end(0));
|
|
28
|
+
}
|
|
77
29
|
}
|
|
78
30
|
}
|