feat: 添加自定义 TTS 和设备唤醒指令选项,fix #5

This commit is contained in:
WJG 2024-05-21 22:46:24 +08:00
parent 4061b44c84
commit 8f50c0c6e4
No known key found for this signature in database
GPG Key ID: 258474EF8590014A
3 changed files with 72 additions and 29 deletions

View File

@ -17,6 +17,15 @@ export default {
userId: process.env.MI_USER, userId: process.env.MI_USER,
password: process.env.MI_PASS, password: process.env.MI_PASS,
did: process.env.MI_DID, did: process.env.MI_DID,
/**
* 小米音箱 TTS 指令
*
* 比如小爱音箱 Prolx06 -> [5, 1]
*
* 不同设备的具体指令可在此网站查询https://home.miot-spec.com
*/
ttsCommand: [5, 1],
wakeUpCommand: [5, 3],
}, },
bot: { bot: {
name: botName, name: botName,

View File

@ -96,30 +96,32 @@ main();
然后,将里面的配置参数修改成你自己的,参数含义如下: 然后,将里面的配置参数修改成你自己的,参数含义如下:
| 参数名称 | 描述 | 示例 | | 参数名称 | 描述 | 示例 |
| -------------------- | ------------------------------------------------------------ | -------------------------------------------------- | | -------------------- | ------------------------------------------------------------- | -------------------------------------------------- |
| **bot** | | | | **bot** | | |
| `name` | 对方名称(小爱音箱) | `"傻妞"` | | `name` | 对方名称(小爱音箱) | `"傻妞"` |
| `profile` | 对方的个人简介/人设 | `"性别女,性格乖巧可爱,喜欢搞怪,爱吃醋。"` | | `profile` | 对方的个人简介/人设 | `"性别女,性格乖巧可爱,喜欢搞怪,爱吃醋。"` |
| **master** | | | | **master** | | |
| `name` | 主人名称(我自己) | `"陆小千"` | | `name` | 主人名称(我自己) | `"陆小千"` |
| `profile` | 主人的个人简介/人设 | `"性别男,善良正直,总是舍己为人,是傻妞的主人。"` | | `profile` | 主人的个人简介/人设 | `"性别男,善良正直,总是舍己为人,是傻妞的主人。"` |
| **room** | | | | **room** | | |
| `name` | 会话群名称 | `"魔幻手机"` | | `name` | 会话群名称 | `"魔幻手机"` |
| `description` | 会话群简介 | `"傻妞和陆小千的私聊"` | | `description` | 会话群简介 | `"傻妞和陆小千的私聊"` |
| **speaker** | | | | **speaker** | | |
| `userId` | 小米账户 | `"12345678901"` | | `userId` | 小米账户 | `"12345678901"` |
| `password` | 账户密码 | `"123456"` | | `password` | 账户密码 | `"123456"` |
| `did` | 小爱音箱 ID 或名称 | `"小爱音箱 Pro"` | | `did` | 小爱音箱 ID 或名称 | `"小爱音箱 Pro"` |
| **其他(可选)** | | | | `ttsCommand` | 小米音箱 TTS 指令([可在此查询](https://home.miot-spec.com) | `[5, 1]` |
| `callAIPrefix` | 当消息以召唤关键词开头时,会调用 AI 来响应用户消息 | `["请","傻妞"]` | | `wakeUpCommand` | 小米音箱唤醒指令([可在此查询](https://home.miot-spec.com) | `[5, 3]` |
| `wakeUpKeywords` | 当消息中包含唤醒关键词时,会进入 AI 唤醒状态 | `["召唤傻妞","打开傻妞"]` | | **其他(可选)** | | |
| `exitKeywords` | 当消息中包含退出关键词时,会退出 AI 唤醒状态 | `["退出傻妞","关闭傻妞"]` | | `callAIPrefix` | 当消息以召唤关键词开头时,会调用 AI 来响应用户消息 | `["请","傻妞"]` |
| `onEnterAI` | 进入 AI 模式的欢迎语 | `["你好,我是傻妞,请问有什么能够帮你的吗?"]` | | `wakeUpKeywords` | 当消息中包含唤醒关键词时,会进入 AI 唤醒状态 | `["召唤傻妞","打开傻妞"]` |
| `onExitAI` | 退出 AI 模式的提示语 | `["傻妞已退出"]` | | `exitKeywords` | 当消息中包含退出关键词时,会退出 AI 唤醒状态 | `["退出傻妞","关闭傻妞"]` |
| `onAIAsking` | AI 开始回答时的提示语 | `["请稍等,让我想想"]` | | `onEnterAI` | 进入 AI 模式的欢迎语 | `["你好,我是傻妞,请问有什么能够帮你的吗?"]` |
| `onAIError` | AI 回答异常时的提示语 | `["出错了,请稍后再试吧!"]` | | `onExitAI` | 退出 AI 模式的提示语 | `["傻妞已退出"]` |
| `exitKeepAliveAfter` | 无响应一段时间后,多久自动退出唤醒模式(单位秒,默认 30 秒) | `30` | | `onAIAsking` | AI 开始回答时的提示语 | `["请稍等,让我想想"]` |
| `onAIError` | AI 回答异常时的提示语 | `["出错了,请稍后再试吧!"]` |
| `exitKeepAliveAfter` | 无响应一段时间后,多久自动退出唤醒模式(单位秒,默认 30 秒) | `30` |
## 💬 常见问题 ## 💬 常见问题

View File

@ -19,10 +19,32 @@ type Speaker = {
speaker: string; speaker: string;
}; };
type ActionCommand = [number, number];
export type BaseSpeakerConfig = MiServiceConfig & { export type BaseSpeakerConfig = MiServiceConfig & {
// 语音合成服务商 /**
*
*/
tts?: TTSProvider; tts?: TTSProvider;
// 检测间隔(单位毫秒,默认 100 毫秒) /**
* TTS command
*
* Prolx06 -> [5, 1]
*
* https://home.miot-spec.com
*/
ttsCommand?: ActionCommand;
/**
* command
*
* Prolx06 -> [5, 3]
*
* https://home.miot-spec.com
*/
wakeUpCommand?: ActionCommand;
/**
* 100
*/
interval?: number; interval?: number;
/** /**
* TTS / * TTS /
@ -37,17 +59,23 @@ export class BaseSpeaker {
interval: number; interval: number;
tts: TTSProvider; tts: TTSProvider;
ttsCommand: ActionCommand;
wakeUpCommand: ActionCommand;
config: MiServiceConfig; config: MiServiceConfig;
constructor(config: BaseSpeakerConfig) { constructor(config: BaseSpeakerConfig) {
this.config = config; this.config = config;
const { const {
interval = 100, interval = 100,
tts = "xiaoai", tts = "xiaoai",
ttsCommand = [5, 1],
wakeUpCommand = [5, 3],
audio_beep = process.env.AUDIO_BEEP, audio_beep = process.env.AUDIO_BEEP,
} = config; } = config;
this.audio_beep = audio_beep; this.audio_beep = audio_beep;
this.interval = interval; this.interval = interval;
this.tts = tts; this.tts = tts;
this.ttsCommand = ttsCommand;
this.wakeUpCommand = wakeUpCommand;
} }
async initMiServices() { async initMiServices() {
@ -57,13 +85,13 @@ export class BaseSpeaker {
} }
wakeUp() { wakeUp() {
return this.MiIOT!.doAction(5, 3); return this.MiIOT!.doAction(...this.wakeUpCommand);
} }
async unWakeUp() { async unWakeUp() {
// 通过 TTS 不发音文本,使小爱退出唤醒状态 // 通过 TTS 不发音文本,使小爱退出唤醒状态
await this.MiNA!.pause(); await this.MiNA!.pause();
await this.MiIOT!.doAction(5, 1, kAreYouOK); await this.MiIOT!.doAction(...this.ttsCommand, kAreYouOK);
} }
audio_beep?: string; audio_beep?: string;
@ -186,7 +214,11 @@ export class BaseSpeaker {
if (ttsNotXiaoai) { if (ttsNotXiaoai) {
await this.unWakeUp(); await this.unWakeUp();
} }
await this.MiNA!.play(args); if (args?.tts) {
await this.MiIOT!.doAction(...this.ttsCommand, args.tts);
} else {
await this.MiNA!.play(args);
}
this.logger.log("🔊 " + (ttsText ?? audio)); this.logger.log("🔊 " + (ttsText ?? audio));
// 等待回答播放完毕 // 等待回答播放完毕
while (true) { while (true) {