@kmchai/cortico-world-voice 0.1.0 → 0.2.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/CHANGELOG.md +23 -0
- package/README.md +79 -70
- package/describe.json +2 -27
- package/package.json +25 -4
- package/src/ENV_PROMPT.md +6 -7
- package/src/audio/queue.ts +1 -1
- package/src/config.ts +46 -108
- package/src/definition.ts +3 -4
- package/src/options.ts +29 -8
- package/src/service.ts +290 -0
- package/src/speech/style.ts +2 -14
- package/src/speech/tags.ts +4 -7
- package/src/speech/text.ts +1 -1
- package/src/tools.ts +1 -16
- package/src/types.ts +17 -51
- package/src/world.ts +144 -242
- package/src/backends/audiocpp.ts +0 -98
- package/src/backends/custom.ts +0 -132
- package/src/backends/http.ts +0 -91
- package/src/backends/index.ts +0 -21
- package/src/backends/openai.ts +0 -51
- package/src/http.ts +0 -205
- package/src/sing.ts +0 -73
package/src/speech/tags.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* 情绪标记只是控制注释,合成前从文本里删掉。
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
/** Ming 3.0
|
|
8
|
+
/** Ming 3.0 系模型支持的副语言标签。 */
|
|
9
9
|
export const PARALINGUISTIC_TAGS: readonly string[] = [
|
|
10
10
|
'Breathing',
|
|
11
11
|
'Cough',
|
|
@@ -57,13 +57,10 @@ export function stripUnknownTags(text: string): string {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
/**
|
|
60
|
-
*
|
|
61
|
-
* OpenAI 兼容服务把它们当正文念,所以删掉。
|
|
60
|
+
* auto 保留标签,由服务里的模型决定演不演;keep 一律保留;strip 一律删掉。
|
|
62
61
|
*/
|
|
63
|
-
export function keepsParalinguistic(
|
|
64
|
-
|
|
65
|
-
if (mode === 'strip') return false;
|
|
66
|
-
return backend === 'audiocpp';
|
|
62
|
+
export function keepsParalinguistic(mode: 'auto' | 'keep' | 'strip'): boolean {
|
|
63
|
+
return mode !== 'strip';
|
|
67
64
|
}
|
|
68
65
|
|
|
69
66
|
const EMOTION_MARKERS: ReadonlyArray<RegExp> = [
|
package/src/speech/text.ts
CHANGED
|
@@ -86,7 +86,7 @@ export function filterSpeech(raw: string, cfg: VoiceConfigSection): FilteredSpee
|
|
|
86
86
|
|
|
87
87
|
text = canonicalizeTags(text);
|
|
88
88
|
text = stripUnknownTags(text);
|
|
89
|
-
if (!keepsParalinguistic(cfg.
|
|
89
|
+
if (!keepsParalinguistic(cfg.paralinguistic)) text = stripParalinguisticTags(text);
|
|
90
90
|
|
|
91
91
|
if (cfg.filterEmoji) text = text.replace(EMOJI_RE, '').replace(SYMBOL_RE, '');
|
|
92
92
|
|
package/src/tools.ts
CHANGED
|
@@ -8,7 +8,7 @@ export const VOICE_TOOL_DECLS: readonly ToolSpec[] = [
|
|
|
8
8
|
'Say a line aloud in your voice through the person\'s speakers, or only synthesize it when silent is true. '
|
|
9
9
|
+ 'Use it when the person asks for voice, when this line needs a specific emotion or voice, or when automatic reading is off. '
|
|
10
10
|
+ 'It only makes sound; the visible reply still goes through the channel\'s own send tool. '
|
|
11
|
-
+ 'When the
|
|
11
|
+
+ 'When the speech service supports paralinguistic tags, keep them inline in the text: [Laughter], [Sigh], [Breathing], [Uhm], [Question-ei] and the like are performed, not read out.',
|
|
12
12
|
tags: ['speak'],
|
|
13
13
|
parameters: {
|
|
14
14
|
type: 'object',
|
|
@@ -24,21 +24,6 @@ export const VOICE_TOOL_DECLS: readonly ToolSpec[] = [
|
|
|
24
24
|
required: ['text'],
|
|
25
25
|
},
|
|
26
26
|
},
|
|
27
|
-
{
|
|
28
|
-
name: 'voice_sing',
|
|
29
|
-
description:
|
|
30
|
-
'Sing a lyric line through the configured singing plugin. It only makes sound; the visible reply still goes through the channel\'s own send tool. '
|
|
31
|
-
+ 'If no singing plugin is configured, or it is not ready, the call fails instead of speaking the lyrics.',
|
|
32
|
-
tags: ['speak'],
|
|
33
|
-
parameters: {
|
|
34
|
-
type: 'object',
|
|
35
|
-
additionalProperties: false,
|
|
36
|
-
properties: {
|
|
37
|
-
lyrics: { type: 'string', maxLength: 2000, description: 'The lyric line to sing.' },
|
|
38
|
-
},
|
|
39
|
-
required: ['lyrics'],
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
27
|
{
|
|
43
28
|
name: 'voice_hush',
|
|
44
29
|
description: 'Stop the voice now: the line playing is cut and queued lines are dropped. It does not affect the visible reply.',
|
package/src/types.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
import type { Logger } from 'cortico/core/types.ts';
|
|
1
|
+
/** 共享类型:配置段、合成请求与音频、服务目录与健康。 */
|
|
3
2
|
|
|
4
|
-
export type BackendId = 'audiocpp' | 'openai' | 'custom';
|
|
5
3
|
export type AudioFormat = 'wav' | 'mp3';
|
|
6
|
-
/**
|
|
4
|
+
/** 情绪怎么发给服务。 */
|
|
7
5
|
export type EmotionMode = 'instruct' | 'categorical' | 'basic' | 'tags' | 'none';
|
|
8
6
|
/** 副语言标签(`[Laughter]` 等)怎么处理。 */
|
|
9
7
|
export type ParalinguisticMode = 'auto' | 'keep' | 'strip';
|
|
@@ -13,13 +11,13 @@ export type PlaybackMode = 'local' | 'event' | 'none';
|
|
|
13
11
|
export interface VoiceConfigSection {
|
|
14
12
|
enabled: boolean;
|
|
15
13
|
|
|
16
|
-
//
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
// 连接
|
|
15
|
+
/** Kmch AI · 服务 的网关地址。 */
|
|
16
|
+
serviceUrl: string;
|
|
17
|
+
/** 服务令牌的环境变量名;空表示服务不校验。 */
|
|
18
|
+
serviceTokenSecret: string;
|
|
19
19
|
model: string;
|
|
20
20
|
voice: string;
|
|
21
|
-
/** 密钥的环境变量名;空表示不需要。 */
|
|
22
|
-
apiKeySecret: string;
|
|
23
21
|
format: AudioFormat;
|
|
24
22
|
timeoutMs: number;
|
|
25
23
|
|
|
@@ -65,28 +63,6 @@ export interface VoiceConfigSection {
|
|
|
65
63
|
gapMs: number;
|
|
66
64
|
/** 工具回执带音频附件,渠道工具可用 `[blob …]` 句柄发送。 */
|
|
67
65
|
shareAudio: boolean;
|
|
68
|
-
|
|
69
|
-
// 本地语音接口
|
|
70
|
-
httpApi: boolean;
|
|
71
|
-
httpPort: number;
|
|
72
|
-
httpToken: string;
|
|
73
|
-
/** 经 HTTP 接口合成时是否也在本机播放。 */
|
|
74
|
-
httpPlay: boolean;
|
|
75
|
-
|
|
76
|
-
// 唱歌
|
|
77
|
-
singUrl: string;
|
|
78
|
-
singToken: string;
|
|
79
|
-
|
|
80
|
-
// custom 协议
|
|
81
|
-
customUrl: string;
|
|
82
|
-
customMethod: 'POST' | 'GET';
|
|
83
|
-
/** JSON 对象字符串,值里的 `${KEY}` 换成 apiKeySecret 读到的密钥。 */
|
|
84
|
-
customHeaders: string;
|
|
85
|
-
/** JSON 模板;占位符见 README。 */
|
|
86
|
-
customBody: string;
|
|
87
|
-
customResponse: 'audio' | 'base64' | 'url';
|
|
88
|
-
/** base64/url 回应里音频字段的点路径。 */
|
|
89
|
-
customAudioPath: string;
|
|
90
66
|
}
|
|
91
67
|
|
|
92
68
|
/** 一次合成。`text` 已经过过滤,不再含控制标记。 */
|
|
@@ -107,30 +83,20 @@ export interface TtsAudio {
|
|
|
107
83
|
seconds?: number;
|
|
108
84
|
}
|
|
109
85
|
|
|
110
|
-
|
|
86
|
+
/** 配置下拉的一项;`value` 写回配置,`label` 显示。 */
|
|
87
|
+
export interface SelectOption {
|
|
111
88
|
value: string;
|
|
112
89
|
label: string;
|
|
113
90
|
}
|
|
114
91
|
|
|
115
|
-
export
|
|
92
|
+
export type VoiceOption = SelectOption;
|
|
93
|
+
export type ModelOption = SelectOption;
|
|
94
|
+
|
|
95
|
+
/** `GET /health` 的摘要;`ok` 只表示网关有回应,`ready` 表示至少有一个服务能合成。 */
|
|
96
|
+
export interface ServiceHealth {
|
|
116
97
|
ok: boolean;
|
|
98
|
+
ready: boolean;
|
|
99
|
+
status: string;
|
|
117
100
|
detail?: string;
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
/** 适配器运行时可用的东西。 */
|
|
121
|
-
export interface BackendContext {
|
|
122
|
-
cfg: VoiceConfigSection;
|
|
123
|
-
secret(name: string): string;
|
|
124
|
-
fetch: typeof fetch;
|
|
125
|
-
log: Logger;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/** 一种语音合成协议。新增协议 = 实现这个接口,再在 registry 里登记。 */
|
|
129
|
-
export interface TtsBackend {
|
|
130
|
-
readonly id: BackendId;
|
|
131
|
-
readonly label: string;
|
|
132
|
-
synthesize(req: TtsRequest, ctx: BackendContext): Promise<TtsAudio>;
|
|
133
|
-
/** 后端能列出的音色;不支持时返回空数组。 */
|
|
134
|
-
listVoices(ctx: BackendContext): Promise<VoiceOption[]>;
|
|
135
|
-
health(ctx: BackendContext): Promise<BackendHealth>;
|
|
101
|
+
models?: number;
|
|
136
102
|
}
|