UNPKG

stt-sdk

Version:

基于 LLMs 的语音转文本 SDK

182 lines (149 loc) 4.8 kB
import { BaseSTTClientHookType, STT_VOICE_STOP, type BaseSTTClient } from "../base/BaseSTTClient.js"; type ConfigOf<C> = C extends BaseSTTClient<infer X> ? X : never; /** * STS 应用 */ export class STTApplication<Cfg = never> { /** * 单例模式 */ private static singleton: STTApplication | null = null; /** * 客户端实例 */ private client: BaseSTTClient<Cfg> | null = null; /** * token 获取钩子 */ private tokenGetHook: (() => Promise<string>) | null = null; /** * 工厂函数 */ public static of(need_new?: boolean) { if (need_new) return new STTApplication(); return STTApplication.singleton ?? (STTApplication.singleton = new STTApplication()); } /** * 转译模式设置 * @param is_real 是否实时转译? */ public setTranslationMode(is_real?: boolean) { if (!this.client) { throw new Error("客户端未注入"); } this.client.setMode(is_real ? "rt" : "all"); return this; } /** * 客户端注入 * @param CC 客户端实现类(构造函数) */ public clientInject<C extends BaseSTTClient<any>>( CC: new () => C ): STTApplication<ConfigOf<C>> { // 复用当前实例也可以,这里演示就地赋值 + 类型收窄返回 (this as any).client = new CC() as BaseSTTClient<ConfigOf<C>>; return this as unknown as STTApplication<ConfigOf<C>>; } /** * token 获取钩子 */ public addTokenGetHook(token_or_func: string | (() => Promise<string>)) { if (!this.client) { throw new Error("客户端未注入"); } if (typeof token_or_func === "string") { this.client.setAccessToken(token_or_func); } else { this.tokenGetHook = async () => { return await token_or_func(); } } return this; } /** * 转译文本接收钩子 */ public addTextReceiveHook(func: (text: string) => void) { if (!this.client) { throw new Error("客户端未注入"); } this.client.addHook(BaseSTTClientHookType.TEXT_RECEIVE, async (text: string) => func(text)); return this; } /** * 客户端配置钩子 */ public setupClientConfig(config: Cfg) { if (!this.client) { throw new Error("客户端未注入"); } this.client.setClientConfig(config); return this; // 保持链式 } /** * 连接关闭钩子函数 */ public addConnectCloseHook(func: () => void) { if (!this.client) { throw new Error("客户端未注入"); } this.client.addHook(BaseSTTClientHookType.CONNECT_CLOSE_HANDLE, async () => func()); return this; } /** * 连接错误钩子函数 */ public addConnecErrorHook(func: (e?: any) => void) { if (!this.client) { throw new Error("客户端未注入"); } this.client.addHook(BaseSTTClientHookType.CONNECT_ERROR_HANDLE, async (e) => func(e)); return this; } /** * 音频输入设备获取授权失败钩子函数 */ public addOpenDeviceFailHook(func: (e?: any) => void) { if (!this.client) { throw new Error("客户端未注入"); } this.client.addHook(BaseSTTClientHookType.DEVICE_OPEN_FAIL_HANDLE, async (e) => func(e)); return this; } /** * 开始转译 */ public start() { if (!this.client) { throw new Error("客户端未注入"); } // hook 校验 this.client.checkRequiredHookIsAllRegister(); (async (context) => { if (!context || !context.client) throw new Error("客户端未知错误"); if (context.tokenGetHook) { const token = await context.tokenGetHook(); context.client.setAccessToken(token); } // 初始化连接 context.client.onConnectInit(); // 打开连接 context.client.onConnectOpen(); // 接收文本 context.client.onTextReceive(); })(this); return this; } /** * 结束转译 */ public stop() { if (!this.client) { throw new Error("客户端未注入"); } const event = new CustomEvent(STT_VOICE_STOP); window.dispatchEvent(event); this.client.closeConnection(); } }