UniApp / 小程序集成

支持微信小程序、H5、App (iOS/Android),兼容 Vue 3 和 Vue 2。提供流式消息、会话持久化、自动重试。

安装

安装依赖bash
1npm install @lingshuai/chat-uniapp

快速开始

pages/chat/index.vue(Vue 3 Composition API - 动态获取Token)vue
1<template>
2 <view class="chat-container">
3 <view v-if="!tempToken" class="loading">加载中...</view>
4 <template v-else>
5 <scroll-view scroll-y class="message-list">
6 <view v-for="msg in messages" :key="msg.id" class="message">
7 <text :class="msg.role">{{ msg.content }}</text>
8 </view>
9 </scroll-view>
10 <view class="input-bar">
11 <input v-model="inputText" placeholder="输入消息..." />
12 <button @tap="handleSend" :disabled="loading">发送</button>
13 </view>
14 </template>
15 </view>
16</template>
17
18<script setup lang="ts">
19import { ref, onMounted } from 'vue';
20import { useChat } from '@lingshuai/chat-uniapp';
21
22const inputText = ref('');
23const tempToken = ref('');
24
25// ⭐ 从后端动态获取临时Token
26onMounted(async () => {
27 const res = await uni.request({
28 url: 'https://your-backend.com/api/auth/temp-token',
29 method: 'POST',
30 header: { 'content-type': 'application/json' }
31 });
32 tempToken.value = res.data.tempToken;
33});
34
35const {
36 messages, // 消息列表
37 loading, // 发送中状态
38 error, // 错误信息
39 sendMessage, // 发送消息
40 resetConversation, // 重置会话
41 abort, // 中止请求
42} = useChat({
43 apiKey: tempToken, // ⭐ 使用动态获取的临时Token(tmp_live_xxx格式)
44 appId: 'your-app-id',
45 baseUrl: 'https://pinyou.xin/api',
46});
47
48const handleSend = async () => {
49 if (!inputText.value.trim()) return;
50 const content = inputText.value;
51 inputText.value = '';
52 await sendMessage(content);
53};
54</script>

App 端真流式传输(RenderJS)

App 端默认使用 plus.net 模拟流式。要启用真正的流式传输,需注册 RenderStreamWorker 组件。

1. 全局注册javascript
1// main.js
2import RenderStreamWorker from '@lingshuai/chat-uniapp/components/RenderStreamWorker';
3Vue.component('RenderStreamWorker', RenderStreamWorker);
2. 在聊天页面放置组件vue
1<template>
2 <view class="chat-page">
3 <RenderStreamWorker />
4 <!-- 你的聊天 UI -->
5 </view>
6</template>

多模态(图片 / 视频)

支持两种方式:直接传入自托管文件 URL(推荐),或通过平台上传。自动适配微信小程序 / App / H5 平台。

方式一:直接传 URL(推荐,文件自行存储)vue
1<script setup lang="ts">
2import { ref, onMounted } from 'vue';
3import { useChat } from '@lingshuai/chat-uniapp';
4
5const tempToken = ref('');
6
7// ⭐ 从后端动态获取临时Token
8onMounted(async () => {
9 const res = await uni.request({
10 url: 'https://your-backend.com/api/auth/temp-token',
11 method: 'POST'
12 });
13 tempToken.value = res.data.tempToken;
14});
15
16const { sendWithUrls } = useChat({
17 apiKey: tempToken, // ⭐ 使用动态获取的临时Token
18 appId: 'your-app-id',
19});
20
21// 直接传入您自己 OSS/CDN 上的文件 URL
22await sendWithUrls('请描述这张图片', [
23 { type: 'image', url: 'https://your-oss.com/photo.jpg', mimeType: 'image/jpeg' }
24]);
25</script>
方式二:通过平台上传(文件为临时存储,AI 处理后删除)vue
1<script setup lang="ts">
2import { ref, onMounted } from 'vue';
3import { useChat } from '@lingshuai/chat-uniapp';
4
5const tempToken = ref('');
6
7// ⭐ 从后端动态获取临时Token
8onMounted(async () => {
9 const res = await uni.request({
10 url: 'https://your-backend.com/api/auth/temp-token',
11 method: 'POST'
12 });
13 tempToken.value = res.data.tempToken;
14});
15
16const {
17 uploading,
18 sendImageFromAlbum,
19 sendVideo,
20} = useChat({
21 apiKey: tempToken, // ⭐ 使用动态获取的临时Token
22 appId: 'your-app-id',
23});
24
25const handlePickImage = async () => {
26 await sendImageFromAlbum('请分析这张图片');
27};
28</script>
29
30<template>
31 <view>
32 <button @tap="handlePickImage">选择图片</button>
33 <text v-if="uploading">上传中...</text>
34 </view>
35</template>

通过平台上传的文件为临时存储,AI 处理完成后即删除。SDK 会在本地缓存附件路径(localPath),当前设备可继续预览,但换设备后不可用。如需跨设备持久化,请使用方式一。

ASR 语音转文字(实时转写)

长按说话 → 边说边看到实时转写文字 → 松开后将转写文本作为普通文本消息发送。SDK 会根据运行平台自动选择最优识别模式。

语音输入(ASR 实时转写)vue
1<script setup lang="ts">
2import { ref, onMounted } from 'vue';
3import { useChat } from '@lingshuai/chat-uniapp';
4
5const tempToken = ref('');
6
7// ⭐ 从后端动态获取临时Token
8onMounted(async () => {
9 const res = await uni.request({
10 url: 'https://your-backend.com/api/auth/temp-token',
11 method: 'POST'
12 });
13 tempToken.value = res.data.tempToken;
14});
15
16const {
17 asrState, // 'idle' | 'connecting' | 'listening' | 'transcribing' | 'error'
18 asrText, // 已确认的转写文本
19 asrInterim, // 正在识别的临时文本(实时更新)
20 startVoiceInput,
21 stopVoiceInput,
22 cancelVoiceInput,
23} = useChat({
24 apiKey: tempToken, // ⭐ 使用动态获取的临时Token
25 appId: 'your-app-id',
26});
27
28// 长按开始
29const onTouchStart = () => startVoiceInput();
30
31// 松开结束 → 自动发送转写文本
32const onTouchEnd = async () => {
33 await stopVoiceInput();
34};
35
36// 上滑取消
37const onCancel = () => cancelVoiceInput();
38</script>
39
40<template>
41 <view>
42 <!-- 实时转写预览 -->
43 <view v-if="asrState !== 'idle'" class="asr-preview">
44 <text>{{ asrText }}{{ asrInterim }}</text>
45 <text v-if="asrState === 'connecting'" class="hint">连接中...</text>
46 <text v-if="asrState === 'transcribing'" class="hint">识别中...</text>
47 </view>
48
49 <!-- 长按说话按钮 -->
50 <button
51 @touchstart="onTouchStart"
52 @touchend="onTouchEnd"
53 :disabled="asrState === 'connecting' || asrState === 'transcribing'"
54 >
55 {{ asrState === 'listening' ? '松开发送' : '按住说话' }}
56 </button>
57 </view>
58</template>

工作流程

  1. 调用 startVoiceInput() → 建立 WebSocket 连接 → 收到 ready 后自动开始录音
  2. 录音过程中,音频帧实时发送到后端 → DashScope ASR 返回中间结果(partial)和确认结果(final) → asrInterim / asrText 实时更新
  3. 调用 stopVoiceInput() → 停止录音 → 等待最终结果 → 自动调用 sendMessage() 发送文本

各平台 ASR 模式

微信小程序

WebSocket 实时流式识别。原生 onFrameRecorded 支持 PCM 帧回调,边说边转写。

H5

文件上传模式。录完整段后上传转写,体验流畅。

App (iOS/Android)

默认文件上传模式。如需实时转写,可集成 Recorder-UniCore 插件(见下方)。

App 端实时 ASR:集成 Recorder-UniCore 插件

UniApp App 端原生 RecorderManager 不支持 onFrameRecorded,无法获取实时 PCM 帧。如需 App 端实时转写,推荐使用 Recorder-UniCore 插件,通过其 onProcess 回调获取实时 PCM 数据。

App 端实时 ASR 示例(Recorder-UniCore)typescript
1import { useChat } from '@lingshuai/chat-uniapp';
2import { Recorder } from 'recorder-uni-core'; // 需先安装插件
3
4const { asrText, asrInterim, asrState } = useChat({ ... });
5const client = /* 获取 ApiClient 实例 */;
6
7// 1. 建立 ASR WebSocket 连接
8client.startAsrSession({
9 format: 'pcm',
10 sampleRate: 16000,
11 onMessage: (msg) => {
12 if (msg.type === 'partial') asrInterim.value = msg.text || '';
13 if (msg.type === 'final') {
14 asrText.value += msg.text || '';
15 asrInterim.value = '';
16 }
17 if (msg.type === 'complete') asrState.value = 'idle';
18 },
19 onError: (err) => console.error(err),
20});
21
22// 2. 使用 Recorder-UniCore 录音,实时喂入音频帧
23const rec = Recorder({ type: 'pcm', sampleRate: 16000, bitRate: 16 });
24rec.open(() => {
25 rec.start();
26});
27rec.onProcess = (buffers, powerLevel, duration, sampleRate) => {
28 // buffers 是 PCM Int16 数据,转为 ArrayBuffer 发送
29 const pcm = buffers[buffers.length - 1];
30 const ab = new ArrayBuffer(pcm.length * 2);
31 const view = new DataView(ab);
32 for (let i = 0; i < pcm.length; i++) {
33 view.setInt16(i * 2, pcm[i], true);
34 }
35 client.sendAsrAudioChunk(ab);
36};
37
38// 3. 停止时
39rec.stop(() => {
40 client.stopAsrSession();
41});

注意:Recorder-UniCore 为第三方插件,SDK 不强制依赖。上述代码仅为集成参考,请根据实际项目调整。

TTS 语音播报

UniApp SDK 使用 WebSocket 流式 TTS,通过 PCM 实时播放,支持自动播报和单条消息播放。必须在页面中放置 <TtsAudioPlayer /> 组件才能正常播放音频!

⚠️ 重要:TtsAudioPlayer 组件

TTS 功能依赖 <TtsAudioPlayer /> 组件来处理跨端音频播放。如果不放置此组件,TTS 将无法播放音频!

TtsAudioPlayer 组件用法vue
1<template>
2 <view class="chat-page">
3 <!-- 必须放置 TtsAudioPlayer 组件! -->
4 <!-- 它会自动处理 App端 renderjs + Web Audio API 的 PCM 播放 -->
5 <TtsAudioPlayer />
6
7 <!-- 你的聊天内容 -->
8 <view v-for="msg in messages" :key="msg.id">
9 <text>{{ msg.content }}</text>
10 </view>
11 </view>
12</template>
13
14<script setup lang="ts">
15import { ref, onMounted } from 'vue';
16// 引入组件
17import { TtsAudioPlayer } from '@lingshuai/chat-uniapp/components/TtsAudioPlayer';
18import { useChat } from '@lingshuai/chat-uniapp';
19
20const tempToken = ref('');
21
22// ⭐ 从后端动态获取临时Token
23onMounted(async () => {
24 const res = await uni.request({
25 url: 'https://your-backend.com/api/auth/temp-token',
26 method: 'POST'
27 });
28 tempToken.value = res.data.tempToken;
29});
30
31const { messages, playTts, stopTts, ttsPlayingMessageId } = useChat({
32 apiKey: tempToken, // ⭐ 使用动态获取的临时Token
33 appId: 'your-app-id',
34});
35</script>
完整 TTS 示例vue
1<template>
2 <view class="chat-page">
3 <!-- 【必须】TTS 音频播放组件 -->
4 <TtsAudioPlayer />
5
6 <!-- TTS 控制按钮 -->
7 <view class="tts-controls">
8 <button @tap="toggleTts">
9 {{ ttsMuted ? '🔇 开启语音' : '🔊 关闭语音' }}
10 </button>
11 </view>
12
13 <!-- 消息列表 -->
14 <view v-for="msg in messages" :key="msg.id" class="message">
15 <text>{{ msg.content }}</text>
16 <!-- AI 消息显示播放按钮 -->
17 <view v-if="msg.role === 'assistant'" class="msg-actions">
18 <button @tap="handlePlay(msg)" :disabled="ttsPlayState === 'loading'">
19 <text v-if="ttsPlayingMessageId === msg.id">
20 {{ ttsPlayState === 'loading' ? '⏳ 加载中...' : '🔊 播放中...' }}
21 </text>
22 <text v-else>▶️ 播放</text>
23 </button>
24 <button v-if="ttsPlayingMessageId === msg.id" @tap="stopTts">⏹️ 停止</button>
25 </view>
26 </view>
27 </view>
28</template>
29
30<script setup lang="ts">
31import { ref, onMounted } from 'vue';
32import { TtsAudioPlayer } from '@lingshuai/chat-uniapp/components/TtsAudioPlayer';
33import { useChat } from '@lingshuai/chat-uniapp';
34
35const tempToken = ref('');
36
37// ⭐ 从后端动态获取临时Token
38onMounted(async () => {
39 const res = await uni.request({
40 url: 'https://your-backend.com/api/auth/temp-token',
41 method: 'POST'
42 });
43 tempToken.value = res.data.tempToken;
44});
45
46const {
47 messages,
48 ttsMuted,
49 setTtsMuted,
50 playTts,
51 stopTts,
52 ttsPlayingMessageId,
53 ttsPlayState, // 'idle' | 'loading' | 'playing' | 'paused' | 'error'
54} = useChat({
55 apiKey: tempToken, // ⭐ 使用动态获取的临时Token
56 appId: 'your-app-id',
57 ttsMode: 'websocket', // TTS 模式,默认 'websocket'(独立 WebSocket 双流实时合成)
58});
59
60// 切换自动播报
61const toggleTts = () => setTtsMuted(!ttsMuted.value);
62
63// 单条消息播放
64const handlePlay = (msg) => {
65 stopTts(); // 先停止当前播放
66 playTts(msg.id, msg.content);
67};
68</script>

跨端播放原理

平台播放方式说明
App (iOS/Android)renderjs + Web Audio API在 WebView 中使用 AudioContext 播放 PCM
微信小程序InnerAudioContext小程序原生音频 API(需转换为 MP3)
H5Web Audio API浏览器原生 AudioContext

💡 常见问题

  • Q: 点击播放没声音?
  • A: 检查是否在页面中放置了 <TtsAudioPlayer /> 组件
  • Q: App 端播放报错?
  • A: 确保 <TtsAudioPlayer /> 放在 template 根节点下,不要嵌套在条件渲染中
  • Q: 小程序播放有延迟?
  • A: 小程序需要先将 PCM 转换为 MP3 格式,会有一定延迟,属于正常现象

RTC 实时语音对话(ASR + 对话 + TTS + 打断)

全双工实时语音交互:按住说话 → 实时识别 → AI流式回复 → 边生成边播放 → 支持打断。完整集成预扣费、MCP工具调用、知识库检索、提示词模板等平台能力。

核心特性

  • ASR语音识别:用户说话实时转文字
  • 流式对话:AI流式生成回复文本
  • 流式TTS:边生成边合成语音,边播放
  • 打断机制:用户说话时自动打断AI播放
  • 预扣费/扣费:完整集成平台计费系统
  • 临时Token认证:安全的无状态认证
  • MCP工具调用:支持数据库查询、知识库检索、网页查询
  • 提示词模板:支持项目绑定的提示词模板
  • 用量统计:完整记录Token、TTS字符数、通话时长
RTC 实时语音对话示例(连续对话模式)vue
1<template>
2 <view class="rtc-chat-page">
3 <!-- 连接状态 -->
4 <view class="status-bar">
5 <view :class="['dot', isConnected ? 'connected' : 'disconnected']"></view>
6 <text>{{ isConnected ? '已连接' : '未连接' }}</text>
7 </view>
8
9 <!-- 识别结果 -->
10 <view v-if="transcription" class="bubble user">
11 <text class="label">你说:</text>
12 <text>{{ transcription }}</text>
13 </view>
14
15 <!-- AI响应 -->
16 <view v-if="aiResponse" class="bubble ai">
17 <text class="label">AI:</text>
18 <text>{{ aiResponse }}</text>
19 </view>
20
21 <!-- 状态指示器 -->
22 <view class="state-indicator">
23 <view v-if="isListening" class="listening-wave">
24 <view class="bar" v-for="i in 5" :key="i"></view>
25 </view>
26 <text v-if="isListening">正在聆听...</text>
27 <text v-else-if="isAiSpeaking">AI正在回复...</text>
28 <text v-else-if="isActive">等待说话...</text>
29 </view>
30
31 <!-- 一键开关按钮 -->
32 <view class="controls">
33 <button
34 :class="['main-btn', isActive ? 'active' : '']"
35 :disabled="!isConnected"
36 @click="toggleConversation"
37 >
38 {{ isActive ? '结束对话' : '开始对话' }}
39 </button>
40
41 <button v-if="isAiSpeaking" class="interrupt-btn" @click="interrupt">
42 打断
43 </button>
44 </view>
45
46 <!-- 使用提示 -->
47 <view v-if="!isActive" class="tips">
48 <text>💡 点击"开始对话"后直接说话,无需按住</text>
49 <text>🎤 1.5秒静音后自动发送</text>
50 <text>⚡ AI回复完成后自动继续监听</text>
51 </view>
52 </view>
53</template>
54
55<script setup lang="ts">
56import { onMounted, onUnmounted } from 'vue';
57import { useRtcChat } from '@lingshuai/chat-uniapp/composables/useRtcChat';
58
59const {
60 isConnected,
61 isActive,
62 isListening,
63 isAiSpeaking,
64 transcription,
65 aiResponse,
66 connect,
67 startConversation,
68 stopConversation,
69 interrupt,
70 disconnect
71} = useRtcChat({
72 projectId: 'your-project-id',
73 apiKey: 'sk_live_xxxxxxxxxxxxxx',
74 // ⭐ 生产环境推荐使用 tokenProvider 动态获取临时Token
75 // tokenProvider: async () => {
76 // const res = await uni.request({ url: 'https://your-backend.com/api/auth/temp-token' });
77 // return res.data.data.tempToken;
78 // },
79});
80
81onMounted(() => connect());
82onUnmounted(() => disconnect());
83
84const toggleConversation = () => {
85 isActive.value ? stopConversation() : startConversation();
86};
87</script>

WebSocket 协议

连接地址:wss://pinyou.xin/api/ws/rtc?token=tmp_xxx

客户端 → 服务端:

  • { action: 'start', projectId: 'xxx' } - 开始会话
  • { action: 'audio', data: 'base64...', end: false } - 发送音频
  • { action: 'interrupt' } - 打断对话
  • { action: 'end' } - 结束会话

服务端 → 客户端:

  • { type: 'ready', sessionId: 'xxx' } - 准备就绪
  • { type: 'transcription', text: '你好' } - ASR识别结果
  • { type: 'text', delta: '我是' } - AI流式文本
  • { type: 'audio', data: 'base64...', seq: 0 } - TTS音频流
  • { type: 'interrupted' } - 已打断
  • { type: 'complete', usage: {...} } - 对话完成
  • { type: 'error', message: 'xxx' } - 错误

⚠️ 音频格式要求

  • 格式:PCM
  • 采样率:16000 Hz
  • 声道:单声道
  • 位深:16 bit
  • 编码:Base64

💡 使用建议

  • Q: 如何获取临时Token?
  • A: 调用后端 /api/v1/auth/exchange-token 接口,传入API Key获取临时Token
  • Q: 打断机制如何工作?
  • A: 用户开始说话时,SDK自动检测并发送interrupt消息,停止当前TTS播放,清空音频队列
  • Q: 如何查看用量统计?
  • A: 会话结束后,数据自动保存到 rtc_sessions 表,包含Token数、TTS字符数、通话时长等
  • Q: 支持哪些平台?
  • A: 微信小程序、H5、App (iOS/Android),自动适配各平台录音和播放API

✅ 与普通ASR/TTS的区别

功能普通模式RTC模式
交互方式串行:说完 → 识别 → 对话 → 播放并行:边说边识别,边生成边播放
打断支持❌ 不支持✅ 支持
延迟较高(需等待完整流程)极低(流式处理)
适用场景文本聊天 + 语音输入/播报实时语音对话、语音助手

平台支持

微信小程序

enableChunked 流式传输,自动处理 UTF-8 多字节字符分片。

H5

Fetch API + ReadableStream 标准 SSE 流式传输。

App (iOS/Android)

RenderJS 真流式传输,未注册时自动降级为 plus.net 模拟。

高级配置

高级配置示例typescript
1import { useChat } from '@lingshuai/chat-uniapp';
2
3const {
4 messages, loading, sendMessage,
5 clearHistory, getStorageInfo, exportMessages, importMessages
6} = useChat({
7 apiKey: 'tmp_live_xxxxxxxxxxxxxx' // ⭐ 用临时Token,
8 appId: 'your-app-id',
9 maxRetries: 3, // 最大重试次数
10 retryDelay: 1000, // 重试间隔(毫秒)
11 maxStoredMessages: 200, // 本地最大存储消息数
12 autoCleanup: true, // 自动清理旧消息
13});
14
15// 查看存储信息
16const info = await getStorageInfo();
17console.log(`消息数: ${info.messageCount}, 占用: ${info.estimatedSize}`);
18
19// 导出 / 导入消息记录
20const json = await exportMessages();
21await importMessages(json);

API 参考

useChat 配置项、返回值、类型定义一览。

ChatConfig(初始化配置)

参数类型必填说明
apiKeystring临时Token(tmp_live_xxx)⭐ 不要用API Key
appIdstring项目 ID(UUID 格式)
baseUrlstringAPI 基础地址(默认 https://pinyou.xin/api)
timeoutnumber请求超时毫秒数(默认 30000)
userIdstring终端用户标识
sessionIdstring会话 ID(不传则自动生成)
maxRetriesnumber最大重试次数(默认 3)
retryDelaynumber重试间隔毫秒数(默认 1000)
maxStoredMessagesnumber本地最大存储消息数(默认 100)
autoCleanupboolean自动清理旧消息(默认 true)
ttsVoicestring默认 TTS 音色 ID
ttsMode'websocket' | 'stream'TTS 模式(默认 'websocket')。websocket = 独立 WebSocket 双流实时合成;stream = SSE 内嵌(已废弃)
tokenProvider() => Promise<string>临时 Token 动态获取函数。设置后优先使用 tokenProvider 返回的 Token 进行认证,适用于 Token 自动刷新场景。与 apiKey 二选一
voiceRecorderVoiceRecorderConfig语音录制配置(见下方)

响应式状态(Ref)

属性类型说明
messagesRef<Message[]>消息列表
loadingRef<boolean>是否正在发送消息
uploadingRef<boolean>是否正在上传文件
errorRef<string | null>错误信息
conversationIdRef<string | null>当前会话 ID
ttsPlayStateRef<TtsPlayState>播放状态:'idle' | 'loading' | 'playing' | 'paused' | 'error'
ttsPlayingMessageIdRef<string | null>正在播放的消息 ID
ttsMutedRef<boolean>是否静音(true = 关闭自动播报)
asrStateRef<AsrState>ASR 状态:'idle' | 'connecting' | 'listening' | 'transcribing' | 'error'
asrTextRef<string>ASR 已确认的转写文本
asrInterimRef<string>ASR 正在识别的临时文本(实时更新)

消息 / 文件方法

方法签名说明
sendMessage(content: string) => Promise<void>发送文本消息
sendWithAttachments(content, attachments) => Promise<void>发送带附件的消息
uploadFile(filePath, type) => Promise<UploadResult>上传文件,返回上传结果
sendImageFromAlbum(content?) => Promise<void>从相册选图并发送
sendImage(filePath, content?) => Promise<void>发送指定路径图片
sendVideo(filePath, content?) => Promise<void>发送视频
sendWithUrls(content, urls: MediaAttachment[]) => Promise<void>直接传入已有 URL(如自有 OSS/CDN),无需先上传
copyMessage(messageId: string) => Promise<void>将指定消息内容复制到剪贴板

ASR 语音输入方法

方法签名说明
startVoiceInput() => void开启 ASR 实时转写(WebSocket 连接 → 录音 → 实时识别)
stopVoiceInput() => Promise<void>停止录音并等待最终结果,自动发送转写文本
cancelVoiceInput() => void取消语音输入(不发送)

会话管理 / 本地存储

方法签名说明
resetConversation() => Promise<void>重置会话(开启新对话)
clearHistory() => Promise<void>清空本地消息记录
abort() => void中止当前流式请求
getStorageInfo() => Promise<StorageInfo>获取本地存储信息
exportMessages() => Promise<string>导出消息为 JSON 字符串
importMessages(json: string) => Promise<boolean>导入消息

TTS 语音播报方法

方法签名说明
playTts(messageId, text, options?) => Promise<void>播放单条消息语音
pauseTts() => void暂停播放
resumeTts() => void恢复播放
stopTts() => void停止播放
setTtsMuted(muted: boolean) => void开关流式自动播报
setTtsAutoPlay(enabled: boolean) => void开关自动播报(setTtsMuted 反向别名)
generateTts(text, options?) => Promise<TtsResult>仅合成音频,不播放
getTtsVoices() => Promise<TtsVoiceOption[]>获取可用音色列表

类型定义

1// 消息
2interface Message {
3 id: string; // 消息 ID
4 conversationId: string; // 所属会话 ID
5 role: 'user' | 'assistant' | 'system'; // 角色
6 content: string; // 消息内容
7 status: 'sending' | 'streaming' | 'success' | 'error'; // 消息状态
8 createdAt: Date; // 创建时间
9 error?: string; // 错误信息(status 为 error 时)
10 attachments?: MediaAttachment[]; // 多模态附件
11}
12
13// 媒体类型
14type MediaType = 'image' | 'audio' | 'video' | 'file';
15
16// 媒体附件
17interface MediaAttachment {
18 type: MediaType; // 附件类型
19 url: string; // 公网访问地址
20 mimeType?: string; // MIME 类型
21 name?: string; // 文件名
22 objectName?: string; // MinIO 对象名称(上传后自动返回)
23 size?: number; // 文件大小(字节)
24 duration?: number; // 时长(秒),音视频专用
25 localPath?: string; // 本地文件路径(UniApp 端离线预览用)
26}
27
28// 上传结果
29interface UploadResult {
30 url: string; // 公网 URL
31 objectName: string; // 对象存储路径
32 mimeType: string; // MIME 类型
33 size: number; // 文件大小(字节)
34 name?: string; // 文件名
35}
36
37// TTS 合成选项
38interface TtsOptions {
39 voice?: string; // 音色 ID
40 projectId?: string; // 项目 ID
41 conversationId?: string; // 会话 ID
42}
43
44// TTS 合成结果
45interface TtsResult {
46 audioUrl: string; // 音频文件 URL
47 characters: number; // 字符数
48 model: string; // TTS 模型名称
49 voice: string; // 使用的音色 ID
50}
51
52// TTS 播放状态
53type TtsPlayState = 'idle' | 'loading' | 'playing' | 'paused' | 'error';
54
55// TTS 音色选项
56interface TtsVoiceOption {
57 id: string; // 音色 ID
58 name: string; // 音色名称
59 description: string; // 音色描述
60 isDefault: boolean; // 是否默认音色
61}
62
63// 本地存储信息
64interface StorageInfo {
65 messageCount: number; // 已存储消息数
66 estimatedSize: string; // 预估占用空间(可读格式)
67 oldestMessageTime: number | null; // 最早消息时间戳(毫秒)
68 newestMessageTime: number | null; // 最新消息时间戳(毫秒)
69 conversationId: string | null; // 当前会话 ID
70}
71
72// 语音录制配置
73interface VoiceRecorderConfig {
74 maxDuration?: number; // 最大录制时长(秒,默认 60)
75 sampleRate?: number; // 采样率(Hz,各平台自动选择)
76 format?: string; // 录音格式(各平台自动选择)
77}
78
79// 录音结果
80interface RecordResult {
81 tempFilePath: string; // 临时文件路径
82 duration: number; // 时长(秒)
83 fileSize?: number; // 文件大小(字节)
84 format: string; // 音频格式
85 mimeType: string; // MIME 类型(用于上传)
86}
87
88// 录音状态
89type RecorderState = 'idle' | 'recording' | 'paused';
90
91// ASR 语音识别状态
92type AsrState = 'idle' | 'connecting' | 'listening' | 'transcribing' | 'error';
93
94// ASR WebSocket 消息
95interface AsrMessage {
96 type: 'ready' | 'partial' | 'final' | 'complete' | 'error' | 'cancelled';
97 text?: string; // 转写文本
98 index?: number; // 句子序号
99 message?: string; // 错误信息(type 为 error 时)
100}

SSE 事件类型

事件 type字段说明
initconversationId流式连接建立,返回会话 ID
messagedelta增量文本片段
analyzingmessage多模态内容分析中(视频/音频/图片),可用于展示加载提示
tts_starttext, seqTTS 合成开始(SSE 内嵌模式)
tts_chunkdata (base64), seqTTS 音频数据块(SSE 内嵌模式,base64 编码)
tts_endseq, characters单句 TTS 合成结束
tts_flush所有 TTS 合成完毕
done流式响应结束
errorerror, message服务端错误信息

文件上传限制

图片

最大 10MB

jpeg, png, gif, webp, bmp

音频

最大 25MB

mp3, wav, ogg, aac, webm, flac, amr, opus, silk

视频

最大 50MB

mp4, webm, quicktime

文件

最大 30MB

pdf, doc/docx, xls/xlsx, ppt/pptx, txt, csv, md, json, zip