UNPKG

node-red-node-rdk-tools

Version:

配合RDK硬件及TROS使用的Node-RED功能包(Node-RED nodes for using TROS on a RDK hardware and TROS)

115 lines (95 loc) 3.37 kB
const bodyParser = require('body-parser'); const fs = require('fs'); const path = require('path'); const vosk = require('vosk-koffi'); const libName = 'libvosk.so'; const libPath = path.join(path.dirname(require.resolve('vosk-koffi')), '../', 'bin-linux-arm64', libName); const backupPath = path.join(__dirname, 'bin-linux-arm64', libName); if(!fs.existsSync(libPath)){ fs.copyFileSync(backupPath, libPath); } else{ console.log('libvosk.so exists') } const modelPath = path.join(__dirname, "./models/vosk-model-small-cn-0.22"); if(!fs.existsSync(modelPath)){ const zipPath = path.join(__dirname, "./zips/vosk-model-small-cn-0.22.zip"); const modelDir = path.join(__dirname, "./models"); const AdmZip = require('adm-zip'); try { const zip = new AdmZip(zipPath); zip.extractAllTo(modelDir, true); } catch(e) { console.log('An error occurred while extracting zip file!') } } module.exports = function(RED) { var playaudionodeid; vosk.setLogLevel(0); // 可选,禁用日志 const MODEL_PATH = path.join(__dirname, "./models/vosk-model-small-cn-0.22"); const SAMPLE_RATE = 16000; const model = new vosk.Model(MODEL_PATH); const recognizer = new vosk.Recognizer({ model: model, sampleRate: SAMPLE_RATE }); function extractPCM(buffer) { // 简单处理:跳过 WAV 的前 44 字节(仅适用于 16bit PCM) return buffer.slice(44); // 返回 Buffer(Int16 PCM) } function convertSpeech(wavBuffer, node) { const pcmBuffer = extractPCM(wavBuffer); recognizer.acceptWaveform(pcmBuffer); const result = recognizer.finalResult(); const resultStr = result.text.split(' ').join(''); node.status({}) node.send({ payload: resultStr }) } function RDKPlayAudioNode(config) { RED.nodes.createNode(this,config); this.voice = 0; var node = this; playaudionodeid = this.id; if (!fs.existsSync(MODEL_PATH)) { node.status({ fill: "red", shape: "dot", text: "Model was not found!" }) } this.on('close', () => { node.status({}); }) this.on('input', function(msg) { if (typeof msg.payload === "string" && msg.payload.indexOf('blob') >= 0) { RED.comms.publish("speechtotext", msg.payload); node.status({fill:"blue",shape:"dot",text:"rdk-speechtotext.status.converting"}); } else{ node.status({ fill: "red", shape: "dot", text: "rdk-speechtotext.status.invalidInput" }) } }); RED.httpAdmin.post('/speechtotext/wav/upload', bodyParser.raw({ // type: '*/*' type: 'audio/wav' }), RED.auth.needsPermission('write'), function(req, res){ const wavBuffer = req.body; convertSpeech(wavBuffer, node); res.json({ status: 'ok', receviced: true }) }) } RED.nodes.registerType("rdk-tools speechtotext", RDKPlayAudioNode); }