AI问诊助手开发经验总结:语音转文字与 Markdown 渲染实战
·
项目背景
在医疗信息系统的前端项目中,我们需要为 AI 助手模块实现语音交互和富文本展示功能。本文将重点分享 语音转文字 和 Markdown 渲染 两个核心功能的实现经验。
一、语音转文字功能实现
1.1 技术选型
经过调研对比,最终选择 recorder-core 作为录音库:
| 方案 | 优点 | 缺点 |
|---|---|---|
| 原生 MediaRecorder | 零依赖 | 不支持 MP3,格式受限 |
| recorder-core | 支持多种格式,轻量 | 需要额外加载编码器 |
| Web Audio API | 高度可控 | 复杂度高 |
1.2 核心实现
1.2.1 初始化配置
import Recorder from "recorder-core";
import "recorder-core/src/engine/mp3";
import "recorder-core/src/engine/mp3-engine";
// 创建录音实例
this.recorder = Recorder({
type: "mp3", // 输出格式
sampleRate: 16000, // 采样率
bitRate: 128, // 比特率
});
1.2.2 录音流程控制
录音功能需要严格遵循 open → start → stop 的调用顺序:
// 打开录音设备(必须在用户交互中调用)
this.recorder.open(
() => {
// 打开成功
this.recorder.start();
},
(msg, isUserNotAllow) => {
// 打开失败(权限问题或设备异常)
if (isUserNotAllow) {
this.$message.error("请在浏览器设置中允许麦克风权限");
}
}
);
// 停止录音并获取数据
this.recorder.stop((blob, duration) => {
// blob 为 MP3 格式的二进制数据
this.uploadRecording(blob);
});
关键注意事项:
open()方法是异步的,必须在回调中调用start()- 必须在用户交互事件(如点击)中触发,否则浏览器会阻止权限请求
1.2.3 文件上传与接口调用
async uploadRecording(mp3Blob) {
// 构建 FormData
const formData = new FormData();
formData.append("file", mp3Blob, "recording.mp3");
// 上传文件
const uploadResponse = await uploadFileApi(formData);
const audioUrl = uploadResponse.data[0].fullUrl;
// 调用语音转文字接口
const recognizeResponse = await flashRecognizer({
audioUrl: audioUrl,
chatId: Date.now().toString()
});
// 将结果显示在输入框
this.inputMessage = recognizeResponse.data.text;
}
1.3 常见问题与解决方案
| 问题 | 原因 | 解决方案 |
|---|---|---|
start失败:未open |
调用顺序错误 | 在 open() 回调中调用 start() |
未加载mp3编码器 |
缺少编码器文件 | 引入 mp3-engine 模块 |
| 录音无声音 | 权限未授予 | 添加权限请求提示 |
二、Markdown 渲染方案
2.1 方案对比与选择
在实现过程中,我们尝试了三种不同的方案:
方案一:自定义正则解析
formatContent(content) {
// 处理加粗
let html = content.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>");
// 处理换行
html = html.replace(/\n/g, "<br>");
// ... 更多规则
return html;
}
优点:零依赖,轻量
缺点:需要维护大量正则,不支持复杂格式(如表格)
方案二:使用 marked 库
npm install marked@4.3.0
import { marked } from "marked";
formatContent(content) {
return marked(content);
}
问题:Vue2 项目的 webpack 配置不支持 ES Module,导致编译错误
方案三:使用 vue-markdown 组件(最终选择)
npm install vue-markdown
<template>
<div class="ai-content">
<vue-markdown :source="content"></vue-markdown>
</div>
</template>
<script>
import VueMarkdown from "vue-markdown";
export default {
components: { VueMarkdown },
}
</script>
优点:专为 Vue 设计,开箱即用,支持完整 Markdown 语法
2.2 样式定制
为了适配项目的 UI 风格,需要对 vue-markdown 生成的标签进行样式覆盖:
.ai-content {
line-height: 1.8;
}
/* 标题样式 */
.ai-content h1,
.ai-content h2,
.ai-content h3,
.ai-content h4,
.ai-content h5,
.ai-content h6 {
margin: 2px 0;
font-weight: 600;
}
2.3 支持的 Markdown 格式
| 语法 | 效果 |
|---|---|
**加粗** |
加粗文本 |
*斜体* |
斜体文本 |
- 列表项 |
无序列表 |
1. 列表项 |
有序列表 |
--- |
分隔线 |
|表头||内容| |
表格 |
`代码` |
行内代码 |
三、功能整合与交互设计
3.1 界面布局

3.2 状态管理
data() {
return {
chatId: "", // 会话ID
messages: [], // 消息列表
inputMessage: "", // 输入内容
loading: false, // 发送loading
isRecording: false, // 录音状态
recordingLoading: false, // 录音处理loading
};
}
3.3 交互流程
用户点击录音 → 权限请求 → 开始录音(isRecording=true)
↓
用户点击停止 → 停止录音 → 上传文件 → 语音转文字
↓
结果显示在输入框 → 用户点击发送 → 调用AI接口
↓
AI回复 → Markdown渲染展示
四、技术总结与最佳实践
4.1 语音转文字要点
- 权限处理:必须在用户交互中请求麦克风权限
- 异步控制:严格遵循 open → start → stop 的调用顺序
- 错误处理:捕获权限拒绝、设备异常等情况
- 格式转换:使用 recorder-core 的 MP3 编码器确保兼容性
4.2 Markdown 渲染要点
- 方案选择:Vue 项目优先使用 vue-markdown 组件
- 样式隔离:使用 scoped CSS 避免全局样式污染
- 性能优化:避免在大型文档中频繁更新 Markdown 内容
- 安全性:对用户输入的 Markdown 进行 XSS 过滤
关键词:Vue2、语音转文字、Markdown、recorder-core、vue-markdown
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)