'use strict'; const moment = require('moment') const WebSocket = require('ws'); const { TextDecoder } = require('util'); const decoder = new TextDecoder('utf-8'); module.exports = async function factory (app, conf) { app.fs.socket.on('connection', async (clientWs, req) => { const addtime = moment() const ip = req?.headers['x-forwarded-for']?.split(',')[0]?.trim() ?? req?.socket?.remoteAddress; app.fs.logger.info(`来自 ${ip} 的 WS 客户端已连接`); clientWs.on('close', async (reason) => { app.fs.logger.info(`来自 ${ip} 的 WS 客户端已断开连接 连接时长:${moment.duration(moment().diff(addtime)).humanize()}`); }) /** * ali语音识别 基于ws转发ws的方案 90% * 用 voiceWsProxy 代替了 */ // // 从环境变量读取 DashScope API Key:contentReference[oaicite:8]{index=8} // const DASH_SCOPE_API_KEY = 'sk-52bd872b19f1465c90f73cf6be090856' || process.env.DASHSCOPE_API_KEY; // if (!DASH_SCOPE_API_KEY) { // console.error('请配置环境变量 DASHSCOPE_API_KEY'); // process.exit(1); // } // // DashScope WebSocket 服务器地址:contentReference[oaicite:9]{index=9} // const DASH_SCOPE_URL = 'wss://dashscope.aliyuncs.com/api-ws/v1/inference/'; // console.log('客户端已连接'); // // 为此连接创建对应的 DashScope WebSocket 客户端 // const dashWs = new WebSocket(DASH_SCOPE_URL, { // headers: { // Authorization: `bearer ${DASH_SCOPE_API_KEY}`, // 'X-DashScope-DataInspection': 'enable' // } // }); // let taskId = null; // // DashScope 连接建立后,等待 run-task 指令 // dashWs.on('open', () => { // console.log('已连接到 DashScope 服务端'); // clientWs.send(JSON.stringify({ type: 'DashScopeOpen', message: '已连接到 DashScope 服务端' })); // }); // // 接收 DashScope 返回的消息并转发给前端 // dashWs.on('message', (data) => { // // DashScope 返回的是文本帧(JSON) // let msg = JSON.parse(data); // const event = msg.header && msg.header.event; // switch (event) { // case 'task-started': // console.log('DashScope 任务启动'); // break; // case 'result-generated': // // 转发识别结果给前端:contentReference[oaicite:10]{index=10} // const text = msg.payload.output.sentence.text; // const isFinal = (msg.payload.output.sentence.end_time !== null); // clientWs.send(JSON.stringify({ // type: 'result', // text: text, // final: isFinal // })); // break; // case 'task-finished': // console.log('DashScope 任务结束'); // clientWs.send(JSON.stringify({ type: 'finished' })); // break; // case 'task-failed': // console.error('DashScope 任务失败:', msg.header.error_message); // clientWs.send(JSON.stringify({ // type: 'error', // message: msg.header.error_message || '识别失败' // })); // // 失败后可关闭连接 // dashWs.close(); // break; // default: // console.log('未知事件:', event); // } // }); // // DashScope 连接错误或关闭时通知前端并清理 // dashWs.on('error', (err) => { // console.error('DashScope 连接错误:', err); // clientWs.send(JSON.stringify({ type: 'error', message: 'DashScope 连接出错' })); // clientWs.close(); // }); // dashWs.on('close', () => { // console.log('DashScope 连接已关闭'); // clientWs.close(); // }); // // 处理来自前端客户端的消息 // clientWs.on('message', (data, isBinary) => { // console.log('收到前端消息二进制:', isBinary); // // 区分文本/二进制消息 // if (isBinary) { // // 二进制音频数据直接转发给 DashScope // dashWs.send(data); // } else { // const data_ = decoder.decode(data); // console.log('收到前端 string 消息:', data_); // const msg = JSON.parse(data_); // if (msg.type === 'start') { // console.log('命令启动'); // // 生成唯一任务ID,并发送 run-task 指令:contentReference[oaicite:11]{index=11}:contentReference[oaicite:12]{index=12} // taskId = uuidv4().replace(/-/g, '').slice(0, 32); // const runTaskMsg = { // header: { // action: 'run-task', // task_id: taskId, // streaming: 'duplex' // }, // payload: { // task_group: 'audio', // task: 'asr', // function: 'recognition', // model: 'paraformer-realtime-v2', // parameters: { // format: 'wav', // sample_rate: 16000 // } // // 可按需添加热词等其他参数 // } // }; // dashWs.send(JSON.stringify(runTaskMsg)); // } else if (msg.type === 'end') { // // 发送 finish-task 指令:contentReference[oaicite:13]{index=13} // const finishMsg = { // header: { // action: 'finish-task', // task_id: taskId, // streaming: 'duplex' // }, // payload: { // input: {} // } // }; // dashWs.send(JSON.stringify(finishMsg)); // } // } // }); // // 处理前端断开/错误:关闭 DashScope 连接 // clientWs.on('close', () => { // console.log('客户端已断开'); // dashWs.close(); // }); // clientWs.on('error', (err) => { // console.error('客户端 WebSocket 错误:', err); // dashWs.close(); // }); }) }