政府单位系统 需要这个语音播报的功能,为什么一直弹出请求授权,
点了开启播报 下次语音消息来了 又弹窗,不能一次性全部允许吗有没有和谷歌浏览器这样chrome://settings/content/sound 一下设置所有的免授权的网址 那个网址这边能打开不,这边看下 # 语音播报功能文档
## 功能概述
语音播报功能用于实时播报系统告警消息和催报通知,通过 WebSocket 接收后端推送的消息,并使用浏览器原生语音合成 API 进行播报。
---
## 技术实现
### 1. 语音合成 API
项目使用浏览器原生的 `Web Speech API` 进行语音播报:
```javascript
const synth = window.speechSynthesis
```
#### 核心播报方法
```javascript
voiceBroadcast(text) {
const msg = new SpeechSynthesisUtterance(text)
msg.lang = 'zh-CN' // 中文语音
msg.volume = 1 // 音量 (0-1)
msg.rate = 1 // 语速
msg.pitch = 1 // 音调
synth.speak(msg)
}
```
### 2. 授权机制
由于浏览器安全策略,首次使用语音播报需要用户手动授权。
#### 授权流程
1. 收到消息时检测是否已授权 (`voiceAuthorized`)
2. 未授权则将消息加入待播报队列 (`pendingVoiceTexts`)
3. 弹出确认框请求用户授权
4. 用户点击"开启播报"后:
- 标记已授权
- 调用 `unlockVoiceBroadcast()` 解锁语音引擎
- 调用 `flushPendingVoiceBroadcasts()` 播报队列中的消息
#### 关键代码
```javascript
// 解锁语音播报(静音播报空字符串激活引擎)
unlockVoiceBroadcast() {
const unlockMsg = new SpeechSynthesisUtterance(' ')
unlockMsg.lang = 'zh-CN'
unlockMsg.volume = 0// 静音
synth.cancel()
synth.speak(unlockMsg)
}
// 刷新页面后需重新授权
// 用户拒绝授权后,后续消息继续存入队列(最多20条)
```
### 3. 消息队列机制
```javascript
queueVoiceBroadcast(text) {
if (!text) return
if (this.voiceAuthorized) {
this.voiceBroadcast(text)// 已授权直接播报
return
}
// 未授权时存入队列,最多保留20条
if (this.pendingVoiceTexts.length >= 20) {
this.pendingVoiceTexts.shift()
}
this.pendingVoiceTexts.push(text)
this.promptVoiceAuthorization()// 弹出授权确认框
}
```
---
## WebSocket 消息接收
### 一期 WebSocket
**连接地址**: `window._CONFIG['websocket1']`
**消息格式**:
```javascript
{
message: {
sendManageName: '发送方名称',
secondTypeName: '消息类型',
content: '消息内容',
sendTime: '发送时间'
}
}
```
**播报内容生成**:
```javascript
let speakStr = `${data.message.sendManageName}的${data.message.secondTypeName}${content}`
```
### 二期 WebSocket
**连接地址**: `window._CONFIG['websocket2']`
**消息格式** (催报消息):
```javascript
{
cmd: 'DDFA_MSG',
sendManageName: '发送方名称',
bussName: '业务名称',
content: '消息内容'
}
```
**播报内容生成**:
```javascript
this.queueVoiceBroadcast(
`来自${data.sendManageName + '的' + data.bussName + '消息,' + content}`
)
```
---
## 文本预处理
播报前会对文本进行字符替换,确保语音正确朗读:
```javascript
content = content.replace(/m³/g, '立方米')
content = content.replace(/\/s/g, '每秒')
```
---
## 消息存储
播报内容会同步存储到 `sessionStorage`,用于历史记录查看:
```javascript
const time = moment().format('YYYY/MM/DD HH:mm')
const newMsgStr = time + speakStr + '\n'
sessionStorage.setItem('一期speakStr语音', voiceStr)
```
---
## 心跳机制
WebSocket 通过心跳保持连接:
```javascript
// 每5秒发送心跳
heartCheckFun() {
this.heartCheck = {
timeout: 5000,
start: function() {
this.timeoutObj = setTimeout(() => {
that.websocketSend('HeartBeat')
}, this.timeout)
}
}
}
```
---
## 错误重连
连接错误时自动重连,最多尝试5次:
```javascript
websocketOnerror() {
this.wsConnectErrorTime += 1
if (this.wsConnectErrorTime > 5) {
this.lockReconnect = true// 锁定不再重连
return
}
this.reconnect()// 5秒后重连
}
```
---
## 相关文件
| 文件路径 | 功能描述 |
|---------|---------|
| `src/components/page/GlobalHeader.vue` | 主要语音播报实现(Web Speech API) |
| `src/components/tools/HeaderNotice.vue` | 旧版通知组件(百度 TTS,已弃用) |
---
## 注意事项
1. **浏览器兼容性**: Web Speech API 支持现代浏览器(Chrome、Edge、Firefox、Safari)
2. **授权状态**: 刷新页面后需要重新授权
3. **队列上限**: 未授权时最多缓存20条消息
4. **连接管理**: 页面离开时自动关闭 WebSocket 连接 (`beforeDestroy`)
5. **门户用户**: `manageId === '10001'` 的用户有特殊的 WebSocket 初始化逻辑
页:
[1]