@lokutor/sdk 1.1.12 → 1.1.15
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/chunk-SNNPJP5R.mjs +42 -0
- package/dist/index.mjs +6 -35
- package/dist/node-audio.d.mts +25 -0
- package/dist/node-audio.d.ts +25 -0
- package/dist/node-audio.js +132 -0
- package/dist/node-audio.mjs +88 -0
- package/package.json +17 -3
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// src/types.ts
|
|
2
|
+
var VoiceStyle = /* @__PURE__ */ ((VoiceStyle2) => {
|
|
3
|
+
VoiceStyle2["F1"] = "F1";
|
|
4
|
+
VoiceStyle2["F2"] = "F2";
|
|
5
|
+
VoiceStyle2["F3"] = "F3";
|
|
6
|
+
VoiceStyle2["F4"] = "F4";
|
|
7
|
+
VoiceStyle2["F5"] = "F5";
|
|
8
|
+
VoiceStyle2["M1"] = "M1";
|
|
9
|
+
VoiceStyle2["M2"] = "M2";
|
|
10
|
+
VoiceStyle2["M3"] = "M3";
|
|
11
|
+
VoiceStyle2["M4"] = "M4";
|
|
12
|
+
VoiceStyle2["M5"] = "M5";
|
|
13
|
+
return VoiceStyle2;
|
|
14
|
+
})(VoiceStyle || {});
|
|
15
|
+
var Language = /* @__PURE__ */ ((Language2) => {
|
|
16
|
+
Language2["ENGLISH"] = "en";
|
|
17
|
+
Language2["SPANISH"] = "es";
|
|
18
|
+
Language2["FRENCH"] = "fr";
|
|
19
|
+
Language2["PORTUGUESE"] = "pt";
|
|
20
|
+
Language2["KOREAN"] = "ko";
|
|
21
|
+
return Language2;
|
|
22
|
+
})(Language || {});
|
|
23
|
+
var AUDIO_CONFIG = {
|
|
24
|
+
SAMPLE_RATE: 16e3,
|
|
25
|
+
SPEAKER_SAMPLE_RATE: 44100,
|
|
26
|
+
CHANNELS: 1,
|
|
27
|
+
CHUNK_DURATION_MS: 20,
|
|
28
|
+
get CHUNK_SIZE() {
|
|
29
|
+
return Math.floor(this.SAMPLE_RATE * this.CHUNK_DURATION_MS / 1e3);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
var DEFAULT_URLS = {
|
|
33
|
+
VOICE_AGENT: "wss://api.lokutor.com/ws/agent",
|
|
34
|
+
TTS: "wss://api.lokutor.com/ws/tts"
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export {
|
|
38
|
+
VoiceStyle,
|
|
39
|
+
Language,
|
|
40
|
+
AUDIO_CONFIG,
|
|
41
|
+
DEFAULT_URLS
|
|
42
|
+
};
|
package/dist/index.mjs
CHANGED
|
@@ -1,38 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
VoiceStyle2["F5"] = "F5";
|
|
8
|
-
VoiceStyle2["M1"] = "M1";
|
|
9
|
-
VoiceStyle2["M2"] = "M2";
|
|
10
|
-
VoiceStyle2["M3"] = "M3";
|
|
11
|
-
VoiceStyle2["M4"] = "M4";
|
|
12
|
-
VoiceStyle2["M5"] = "M5";
|
|
13
|
-
return VoiceStyle2;
|
|
14
|
-
})(VoiceStyle || {});
|
|
15
|
-
var Language = /* @__PURE__ */ ((Language2) => {
|
|
16
|
-
Language2["ENGLISH"] = "en";
|
|
17
|
-
Language2["SPANISH"] = "es";
|
|
18
|
-
Language2["FRENCH"] = "fr";
|
|
19
|
-
Language2["PORTUGUESE"] = "pt";
|
|
20
|
-
Language2["KOREAN"] = "ko";
|
|
21
|
-
return Language2;
|
|
22
|
-
})(Language || {});
|
|
23
|
-
var AUDIO_CONFIG = {
|
|
24
|
-
SAMPLE_RATE: 16e3,
|
|
25
|
-
SPEAKER_SAMPLE_RATE: 44100,
|
|
26
|
-
CHANNELS: 1,
|
|
27
|
-
CHUNK_DURATION_MS: 20,
|
|
28
|
-
get CHUNK_SIZE() {
|
|
29
|
-
return Math.floor(this.SAMPLE_RATE * this.CHUNK_DURATION_MS / 1e3);
|
|
30
|
-
}
|
|
31
|
-
};
|
|
32
|
-
var DEFAULT_URLS = {
|
|
33
|
-
VOICE_AGENT: "wss://api.lokutor.com/ws/agent",
|
|
34
|
-
TTS: "wss://api.lokutor.com/ws/tts"
|
|
35
|
-
};
|
|
1
|
+
import {
|
|
2
|
+
AUDIO_CONFIG,
|
|
3
|
+
DEFAULT_URLS,
|
|
4
|
+
Language,
|
|
5
|
+
VoiceStyle
|
|
6
|
+
} from "./chunk-SNNPJP5R.mjs";
|
|
36
7
|
|
|
37
8
|
// src/audio-utils.ts
|
|
38
9
|
function pcm16ToFloat32(int16Data) {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js-only audio manager.
|
|
3
|
+
*
|
|
4
|
+
* This module is intentionally separate, and is not exported from the browser default
|
|
5
|
+
* entrypoint, so browser bundlers do not include Node-only dependencies.
|
|
6
|
+
*/
|
|
7
|
+
declare class NodeAudioManager {
|
|
8
|
+
private speaker;
|
|
9
|
+
private recorder;
|
|
10
|
+
private recordingStream;
|
|
11
|
+
private isMuted;
|
|
12
|
+
private isListening;
|
|
13
|
+
constructor();
|
|
14
|
+
init(): Promise<void>;
|
|
15
|
+
startMicrophone(onAudioInput: (pcm16Data: Uint8Array) => void): Promise<void>;
|
|
16
|
+
stopMicrophone(): void;
|
|
17
|
+
playAudio(pcm16Data: Uint8Array): Promise<void>;
|
|
18
|
+
stopPlayback(): void;
|
|
19
|
+
cleanup(): void;
|
|
20
|
+
isMicMuted(): boolean;
|
|
21
|
+
setMuted(muted: boolean): void;
|
|
22
|
+
getAmplitude(): number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { NodeAudioManager };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js-only audio manager.
|
|
3
|
+
*
|
|
4
|
+
* This module is intentionally separate, and is not exported from the browser default
|
|
5
|
+
* entrypoint, so browser bundlers do not include Node-only dependencies.
|
|
6
|
+
*/
|
|
7
|
+
declare class NodeAudioManager {
|
|
8
|
+
private speaker;
|
|
9
|
+
private recorder;
|
|
10
|
+
private recordingStream;
|
|
11
|
+
private isMuted;
|
|
12
|
+
private isListening;
|
|
13
|
+
constructor();
|
|
14
|
+
init(): Promise<void>;
|
|
15
|
+
startMicrophone(onAudioInput: (pcm16Data: Uint8Array) => void): Promise<void>;
|
|
16
|
+
stopMicrophone(): void;
|
|
17
|
+
playAudio(pcm16Data: Uint8Array): Promise<void>;
|
|
18
|
+
stopPlayback(): void;
|
|
19
|
+
cleanup(): void;
|
|
20
|
+
isMicMuted(): boolean;
|
|
21
|
+
setMuted(muted: boolean): void;
|
|
22
|
+
getAmplitude(): number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { NodeAudioManager };
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/node-audio.ts
|
|
31
|
+
var node_audio_exports = {};
|
|
32
|
+
__export(node_audio_exports, {
|
|
33
|
+
NodeAudioManager: () => NodeAudioManager
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(node_audio_exports);
|
|
36
|
+
|
|
37
|
+
// src/types.ts
|
|
38
|
+
var AUDIO_CONFIG = {
|
|
39
|
+
SAMPLE_RATE: 16e3,
|
|
40
|
+
SPEAKER_SAMPLE_RATE: 44100,
|
|
41
|
+
CHANNELS: 1,
|
|
42
|
+
CHUNK_DURATION_MS: 20,
|
|
43
|
+
get CHUNK_SIZE() {
|
|
44
|
+
return Math.floor(this.SAMPLE_RATE * this.CHUNK_DURATION_MS / 1e3);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// src/node-audio.ts
|
|
49
|
+
var NodeAudioManager = class {
|
|
50
|
+
speaker = null;
|
|
51
|
+
recorder = null;
|
|
52
|
+
recordingStream = null;
|
|
53
|
+
isMuted = false;
|
|
54
|
+
isListening = false;
|
|
55
|
+
constructor() {
|
|
56
|
+
}
|
|
57
|
+
async init() {
|
|
58
|
+
try {
|
|
59
|
+
const Speaker = await import("speaker").catch(() => null);
|
|
60
|
+
if (!Speaker) {
|
|
61
|
+
console.warn('\u26A0\uFE0F Package "speaker" is missing. Hardware output will be disabled.');
|
|
62
|
+
console.warn("\u{1F449} Run: npm install speaker");
|
|
63
|
+
}
|
|
64
|
+
} catch (e) {
|
|
65
|
+
console.error("Error initializing Node audio:", e);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async startMicrophone(onAudioInput) {
|
|
69
|
+
if (this.isListening) return;
|
|
70
|
+
const recorder = await import("node-record-lpcm16").catch(() => null);
|
|
71
|
+
if (!recorder) {
|
|
72
|
+
throw new Error('Package "node-record-lpcm16" is missing. Microphone input failed.\n\u{1F449} Run: npm install node-record-lpcm16');
|
|
73
|
+
}
|
|
74
|
+
this.recorder = recorder;
|
|
75
|
+
this.recordingStream = recorder.record({
|
|
76
|
+
sampleRate: AUDIO_CONFIG.SAMPLE_RATE,
|
|
77
|
+
threshold: 0,
|
|
78
|
+
verbose: false,
|
|
79
|
+
recordProgram: "sox"
|
|
80
|
+
});
|
|
81
|
+
this.recordingStream.stream().on("data", (chunk) => {
|
|
82
|
+
if (!this.isMuted && onAudioInput) {
|
|
83
|
+
onAudioInput(new Uint8Array(chunk));
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
this.isListening = true;
|
|
87
|
+
}
|
|
88
|
+
stopMicrophone() {
|
|
89
|
+
if (this.recordingStream) {
|
|
90
|
+
this.recordingStream.stop();
|
|
91
|
+
this.recordingStream = null;
|
|
92
|
+
}
|
|
93
|
+
this.isListening = false;
|
|
94
|
+
}
|
|
95
|
+
async playAudio(pcm16Data) {
|
|
96
|
+
try {
|
|
97
|
+
if (!this.speaker) {
|
|
98
|
+
const Speaker = (await import("speaker")).default;
|
|
99
|
+
this.speaker = new Speaker({
|
|
100
|
+
channels: AUDIO_CONFIG.CHANNELS,
|
|
101
|
+
bitDepth: 16,
|
|
102
|
+
sampleRate: AUDIO_CONFIG.SPEAKER_SAMPLE_RATE
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
this.speaker.write(Buffer.from(pcm16Data));
|
|
106
|
+
} catch {
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
stopPlayback() {
|
|
110
|
+
if (this.speaker) {
|
|
111
|
+
this.speaker.end();
|
|
112
|
+
this.speaker = null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
cleanup() {
|
|
116
|
+
this.stopMicrophone();
|
|
117
|
+
this.stopPlayback();
|
|
118
|
+
}
|
|
119
|
+
isMicMuted() {
|
|
120
|
+
return this.isMuted;
|
|
121
|
+
}
|
|
122
|
+
setMuted(muted) {
|
|
123
|
+
this.isMuted = muted;
|
|
124
|
+
}
|
|
125
|
+
getAmplitude() {
|
|
126
|
+
return 0;
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
130
|
+
0 && (module.exports = {
|
|
131
|
+
NodeAudioManager
|
|
132
|
+
});
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AUDIO_CONFIG
|
|
3
|
+
} from "./chunk-SNNPJP5R.mjs";
|
|
4
|
+
|
|
5
|
+
// src/node-audio.ts
|
|
6
|
+
var NodeAudioManager = class {
|
|
7
|
+
speaker = null;
|
|
8
|
+
recorder = null;
|
|
9
|
+
recordingStream = null;
|
|
10
|
+
isMuted = false;
|
|
11
|
+
isListening = false;
|
|
12
|
+
constructor() {
|
|
13
|
+
}
|
|
14
|
+
async init() {
|
|
15
|
+
try {
|
|
16
|
+
const Speaker = await import("speaker").catch(() => null);
|
|
17
|
+
if (!Speaker) {
|
|
18
|
+
console.warn('\u26A0\uFE0F Package "speaker" is missing. Hardware output will be disabled.');
|
|
19
|
+
console.warn("\u{1F449} Run: npm install speaker");
|
|
20
|
+
}
|
|
21
|
+
} catch (e) {
|
|
22
|
+
console.error("Error initializing Node audio:", e);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async startMicrophone(onAudioInput) {
|
|
26
|
+
if (this.isListening) return;
|
|
27
|
+
const recorder = await import("node-record-lpcm16").catch(() => null);
|
|
28
|
+
if (!recorder) {
|
|
29
|
+
throw new Error('Package "node-record-lpcm16" is missing. Microphone input failed.\n\u{1F449} Run: npm install node-record-lpcm16');
|
|
30
|
+
}
|
|
31
|
+
this.recorder = recorder;
|
|
32
|
+
this.recordingStream = recorder.record({
|
|
33
|
+
sampleRate: AUDIO_CONFIG.SAMPLE_RATE,
|
|
34
|
+
threshold: 0,
|
|
35
|
+
verbose: false,
|
|
36
|
+
recordProgram: "sox"
|
|
37
|
+
});
|
|
38
|
+
this.recordingStream.stream().on("data", (chunk) => {
|
|
39
|
+
if (!this.isMuted && onAudioInput) {
|
|
40
|
+
onAudioInput(new Uint8Array(chunk));
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
this.isListening = true;
|
|
44
|
+
}
|
|
45
|
+
stopMicrophone() {
|
|
46
|
+
if (this.recordingStream) {
|
|
47
|
+
this.recordingStream.stop();
|
|
48
|
+
this.recordingStream = null;
|
|
49
|
+
}
|
|
50
|
+
this.isListening = false;
|
|
51
|
+
}
|
|
52
|
+
async playAudio(pcm16Data) {
|
|
53
|
+
try {
|
|
54
|
+
if (!this.speaker) {
|
|
55
|
+
const Speaker = (await import("speaker")).default;
|
|
56
|
+
this.speaker = new Speaker({
|
|
57
|
+
channels: AUDIO_CONFIG.CHANNELS,
|
|
58
|
+
bitDepth: 16,
|
|
59
|
+
sampleRate: AUDIO_CONFIG.SPEAKER_SAMPLE_RATE
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
this.speaker.write(Buffer.from(pcm16Data));
|
|
63
|
+
} catch {
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
stopPlayback() {
|
|
67
|
+
if (this.speaker) {
|
|
68
|
+
this.speaker.end();
|
|
69
|
+
this.speaker = null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
cleanup() {
|
|
73
|
+
this.stopMicrophone();
|
|
74
|
+
this.stopPlayback();
|
|
75
|
+
}
|
|
76
|
+
isMicMuted() {
|
|
77
|
+
return this.isMuted;
|
|
78
|
+
}
|
|
79
|
+
setMuted(muted) {
|
|
80
|
+
this.isMuted = muted;
|
|
81
|
+
}
|
|
82
|
+
getAmplitude() {
|
|
83
|
+
return 0;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
export {
|
|
87
|
+
NodeAudioManager
|
|
88
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lokutor/sdk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.15",
|
|
4
4
|
"description": "JavaScript/TypeScript SDK for Lokutor Real-time Voice AI",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -8,9 +8,23 @@
|
|
|
8
8
|
"files": [
|
|
9
9
|
"dist"
|
|
10
10
|
],
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"import": "./dist/index.mjs",
|
|
14
|
+
"require": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./node-audio": {
|
|
17
|
+
"import": "./dist/node-audio.mjs",
|
|
18
|
+
"require": "./dist/node-audio.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"browser": {
|
|
22
|
+
"speaker": false,
|
|
23
|
+
"node-record-lpcm16": false
|
|
24
|
+
},
|
|
11
25
|
"scripts": {
|
|
12
|
-
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
13
|
-
"dev": "tsup src/index.ts --format cjs,esm --watch --dts",
|
|
26
|
+
"build": "tsup src/index.ts src/node-audio.ts --format cjs,esm --dts --clean",
|
|
27
|
+
"dev": "tsup src/index.ts src/node-audio.ts --format cjs,esm --watch --dts --clean",
|
|
14
28
|
"test": "vitest run",
|
|
15
29
|
"test:watch": "vitest",
|
|
16
30
|
"lint": "eslint src --ext .ts",
|