项目背景

在医疗信息系统的前端项目中,我们需要为 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 语音转文字要点

  1. 权限处理:必须在用户交互中请求麦克风权限
  2. 异步控制:严格遵循 open → start → stop 的调用顺序
  3. 错误处理:捕获权限拒绝、设备异常等情况
  4. 格式转换:使用 recorder-core 的 MP3 编码器确保兼容性

4.2 Markdown 渲染要点

  1. 方案选择:Vue 项目优先使用 vue-markdown 组件
  2. 样式隔离:使用 scoped CSS 避免全局样式污染
  3. 性能优化:避免在大型文档中频繁更新 Markdown 内容
  4. 安全性:对用户输入的 Markdown 进行 XSS 过滤

关键词:Vue2、语音转文字、Markdown、recorder-core、vue-markdown

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐