100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > node ref char*_「 volute 」树莓派+Node.js造一个有灵魂的语音助手

node ref char*_「 volute 」树莓派+Node.js造一个有灵魂的语音助手

时间:2021-04-04 13:11:34

相关推荐

node ref char*_「 volute 」树莓派+Node.js造一个有灵魂的语音助手

volute 是什么?

volute(蜗壳)是一个使用 Raspberry Pi+ 制作的语音助手.

什么是树莓派?

树莓派(英语:Raspberry Pi)是基于 Linux 的单片机电脑,由英国树莓派基金会开发,目的是以低价硬件及自由软件促进学校的基本计算机科学教育。

树莓派每一代均使用博通(Broadcom)出产的 ARM 架构处理器,如今生产的机型内存在 2GB 和 8GB 之间,主要使用 SD 卡或者 TF 卡作为存储媒体,配备 USB 接口、HDMI 的视频输出(支持声音输出)和 RCA 端子输出,内置 Ethernet/WLAN/Bluetooth 网络链接的方式(依据型号决定),并且可使用多种操作系统。产品线型号分为 A 型、B 型、Zero 型和 ComputeModule 计算卡。

简单的说,这是一台可以放到口袋里的电脑!!

什么是 ?

是一个能执行 Javascript 的环境,一个事件驱动 I/O 的 Javascript 环境,基于 Google 的 V8 引擎.

什么是人机对话系统 ?

人机对话(Human-Machine Conversation)是指让机器理解和运用自然语言实现人机通信的技术。

对话系统大致可分为 5 个基本模块:语音识别(ASR)、自然语音理解(NLU)、对话管理(DM)、自然语言生成(NLG)、语音合成(TTS)。

语音识别(ASR):完成语音到文本的转换,将用户说话的声音转化为语音。自然语言理解(NLU):完成对文本的语义解析,提取关键信息,进行意图识别与实体识别。对话管理(DM):负责对话状态维护、数据库查询、上下文管理等。自然语言生成(NLG):生成相应的自然语言文本。语音合成(TTS):将生成的文本转换为语音。

材料准备

树莓派 4B 主板树莓派 5V3A TYPE C 接口微型 USB 麦克风迷你音箱16G TF 卡川宇读卡器杜邦线,外壳,散热片...

树莓派系统安装及基础配置

新的树莓派不像你买的 Macbook Pro 一样开机就能用 ,想要顺利体验树莓派,还得一步一步来~

烧录操作系统

树莓派没有硬盘结构,仅有一个 micro SD 卡插槽用于存储,因此要把操作系统装到 micro SD 卡中。

树莓派支持许多操作系统,这里选择的是官方推荐的 Raspbian,这是一款基于 Debian Linux 的树莓派专用系统,适用于树莓派所有的型号。

安装系统我用的是 Raspberry Pi Imager 工具为树莓派烧录系统镜像。

基础配置

要对树莓派进行配置,首先要启动系统(我们安装的是系统镜像,可免安装直接进入),然后将树莓派连接显示器即可看到系统桌面,我这里使用的是另一种方法:

使用 IP Scanner 工具 扫描出 Raspberry Pi 的 IP扫描出 IP 后使用 VNC Viewer 工具 连接进系统也可以直接 ssh 连接,然后通过 raspi-config 命令进行配置

volute 实现思路

任务调度服务

const fs = require("fs");const path = require("path");const Speaker = require("speaker");const { record } = require("node-record-lpcm16");const XunFeiIAT = require("./services/");const XunFeiTTS = require("./services/");const initSnowboy = require("./services/");const TulingBotService = require("./services/");// 任务调度服务const taskScheduling = {// 麦克风mic: null,speaker: null,detector: null,// 音频输入流inputStream: null,// 音頻輸出流outputStream: null,init() {// 初始化snowboy= initSnowboy({record: (this),stopRecord: (this),});// 管道流,将麦克风接收到的流传递给snowboy();},start() {// 监听麦克风输入流this.mic = record({sampleRate: 16000, // 采样率threshold: ,verbose: true,recordProgram: "arecord",}).stream();();},// 记录音频输入recordSound() {// 每次记录前,先停止上次未播放完成的输出流();("start record");// 创建可写流= fs.createWriteStream((__dirname, "./assets/"),{encoding: "binary",});// 管道流,将麦克风接受到的输入流 传递给 创建的可写流();},// 停止音频输入stopRecord() {if () {("stop record");// 解绑绑定的管道流();();(() => {// 销毁输入流.destroy();= null;// 重新初始化();// 调用语音听写服务();});}},// speech to textspeech2Text() {// 实例化 语音听写服务const iatService = new XunFeiIAT({onReply: (msg) => {("msg", msg);// 回调,调用聊天功能(msg);},});();},// 聊天->图灵机器人onChat(text) {// 实例化聊天机器人(text).then((res) => {(res);// 接收到聊天消息,调用语音合成服务(res);});},// text to speechtext2Speech(text) {// 实例化 语音合成服务const ttsService = new XunFeiTTS({text,onDone: () => {("onDone");();},});();},// 播放,音频输出onSpeak() {// 实例化speaker,用于播放语音= new Speaker({channels: 1,bitDepth: 16,sampleRate: 16000,});// 创建可读流this.outputStream = fs.createReadStream((__dirname, "./assets/"));// this is just to activate the speaker, 2s delay.write((32000, 10));// 管道流,将输出流传递给speaker进行播放();("end", () => {this.outputStream = null;= null;});},// 停止播放stopSpeak() {this.outputStream && this.outputStream.unpipe();},};();

热词唤醒 Snowboy

语音助手需要像市面上的设备一样,需要唤醒。 如果没有唤醒步骤,一直做监听的话,对存储资源和网络连接的需求是非常大的。

Snowboy 是一款高度可定制的唤醒词检测引擎(Hotwords Detection Library),可以用于实时嵌入式系统,通过训练热词之后,可以离线运行,并且 功耗很低。当前,它可以运行在 Raspberry Pi、(Ubuntu)Linux 和 Mac OS X 系统上。

const path = require("path");const snowboy = require("snowboy");const models = new snowboy.Models();// 添加训练模型({file: (__dirname, "../configs/"),sensitivity: "",hotwords: "volute",});// 初始化 Detector 对象const detector = new snowboy.Detector({resource: (__dirname, "../configs/"),models: models,audioGain: 1.0,applyFrontend: false,});/*** 初始化 initSnowboy* 实现思路:* 1. 监听到热词,进行唤醒,开始录音* 2. 录音期间,有声音时,重置silenceCount参数* 3. 录音期间,未接受到声音时,对silenceCount进行累加,当累加值大于3时,停止录音*/function initSnowboy({ record, stopRecord }) {const MAX_SILENCE_COUNT = 3;let silenceCount = 0,speaking = false;/*** silence事件回调,没声音时触发*/const onSilence = () => {("silence");if (speaking && ++silenceCount > MAX_SILENCE_COUNT) {speaking = false;stopRecord && stopRecord();("silence", onSilence);("sound", onSound);("hotword", onHotword);}};/*** sound事件回调,有声音时触发*/const onSound = () => {("sound");if (speaking) {silenceCount = 0;}};/*** hotword事件回调,监听到热词时触发*/const onHotword = (index, hotword, buffer) => {if (!speaking) {silenceCount = 0;speaking = true;record && record();}};("silence", onSilence);("sound", onSound);("hotword", onHotword);return detector;}module.exports = initSnowboy;

语音听写 科大讯飞 API

语音转文字使用的是讯飞开放平台的语音听写服务.它可以将短音频(≤60 秒)精准识别成文字,除中文普通话和英文外,支持 25 种方言和 12 个语种,实时返回结果,达到边说边返回的效果。

require("dotenv").config();const fs = require("fs");const WebSocket = require("ws");const { resolve } = require("path");const { createAuthParams } = require("../utils/auth");class XunFeiIAT {constructor({ onReply }) {super();// websocket 连接this.ws = null;// 返回结果,解析后的消息文字= "";= onReply;// 需要进行转换的输入流 语音文件= resolve(__dirname, "../assets/");// 接口 入参= {host: "",path: "/v2/iat",apiKey: process.env.XUNFEI_API_KEY,secret: process.env.XUNFEI_SECRET,};}// 生成websocket连接generateWsUrl() {const { host, path } = ;// 接口鉴权,参数加密const params = createAuthParams();return `ws://${host}${path}?${params}`;}// 初始化init() {const reqUrl = ();this.ws = new WebSocket(reqUrl);WsEvent();}// 初始化websocket事件initWsEvent() {("open", (this));("error", );("close", );("message", (this));}/*** websocket open事件,触发表示已成功建立连接*/onOpen() {("open");();}onPush(file) {(file);}// websocket 消息接收 回调onMessage(data) {const payload = (data);if (payload.data && payload.data.result) {// 拼接消息结果+= payload.data.result.ws.reduce((acc, item) => acc + ((cw) => ),"");// status 2表示结束if (payload.data.status === 2) {();}}}// websocket 关闭事件onClose() {("close");}// websocket 错误事件onError(error) {(error);}/*** 解析语音文件,将语音以二进制流的形式传送给后端*/pushAudioFile(audioFile) {= "";// 发送需要的载体参数const audioPayload = (statusCode, audioBase64) => ({common:statusCode === 0? {app_id: "5f6cab72",}: undefined,business:statusCode === 0? {language: "zh_cn",domain: "iat",ptt: 0,}: undefined,data: {status: statusCode,format: "audio/L16;rate=16000",encoding: "raw",audio: audioBase64,},});const chunkSize = 9000;// 创建buffer,用于存储二进制数据const buffer = (chunkSize);// 打开语音文件(audioFile, "r", (err, fd) => {if (err) {throw err;}let i = 0;// 以二进制流的形式递归发送function readNextChunk() {(fd, buffer, 0, chunkSize, null, (errr, nread) => {if (errr) {throw errr;}// nread表示文件流已读完,发送传输结束标识(status=2)if (nread === 0) {(({data: { status: 2 },}));return fs.close(fd, (err) => {if (err) {throw err;}});}let data;if (nread < chunkSize) {data = (0, nread);} else {data = buffer;}const audioBase64 = ("base64");const payload = audioPayload(i >= 1 ? 1 : 0, audioBase64);((payload));i++;(this);});}(this);});}}module.exports = XunFeiIAT;

聊天机器人 图灵机器人 API

图灵机器人 API V2.0 是基于图灵机器人平台语义理解、深度学习等核心技术,为广大开发者和企业提供的在线服务和开发接口。

目前 API 接口可调用聊天对话、语料库、技能三大模块的语料:

聊天对话是指平台免费提供的近 10 亿条公有对话语料,满足用户对话娱乐需求;

语料库是指用户在平台上传的私有语料,仅供个人查看使用,帮助用户最便捷的搭建专业领域次的语料。

技能服务是指平台打包的 26 种实用服务技能。涵盖生活、出行、购物等多个领域,一站式满足用户需求。

require("dotenv").config();const axios = require("axios");// 太简单了..懒得解释 const TulingBotService = {requestUrl: "",start(text) {return new Promise((resolve) => {axios.post(, {reqType: 0,perception: {inputText: {text,},},userInfo: {apiKey: process.env.TULING_BOT_API_KEY,userId: process.env.TULING_BOT_USER_ID,},}).then((res) => {// ((res.data, null, 2));resolve([0].);});});},};module.exports = TulingBotService;

语音合成 科大讯飞 API

语音合成流式接口将文字信息转化为声音信息,同时提供了众多极具特色的发音人(音库)供您选择。

该语音能力是通过 Websocket API 的方式给开发者提供一个通用的接口。Websocket API 具备流式传输能力,适用于需要流式数据传输的 AI 服务场景。相较于 SDK,API 具有轻量、跨语言的特点;相较于 HTTP API,Websocket API 协议有原生支持跨域的优势。

require("dotenv").config();const fs = require("fs");const WebSocket = require("ws");const { resolve } = require("path");const { createAuthParams } = require("../utils/auth");class XunFeiTTS {constructor({ text, onDone }) {super();this.ws = null;// 要转换的文字= text;= onDone;// 转换后的语音文件= resolve(__dirname, "../assets/");// 接口入参= {host: "",path: "/v2/tts",appid: process.env.XUNFEI_APP_ID,apiKey: process.env.XUNFEI_API_KEY,secret: process.env.XUNFEI_SECRET,};}// 生成websocket连接generateWsUrl() {const { host, path } = ;const params = createAuthParams();return `ws://${host}${path}?${params}`;}// 初始化init() {const reqUrl = ();(reqUrl);this.ws = new WebSocket(reqUrl);WsEvent();}// 初始化websocket事件initWsEvent() {("open", (this));("error", );("close", );("message", (this));}/*** websocket open事件,触发表示已成功建立连接*/onOpen() {("open");();if (()) {();}}// 发送要转换的参数信息onSend() {const frame = {// 填充commoncommon: {app_id: .appid,},// 填充businessbusiness: {aue: "raw",auf: "audio/L16;rate=16000",vcn: "xiaoyan",tte: "UTF8",},// 填充datadata: {text: ().toString("base64"),status: 2,},};((frame));}// 保存转换后的语音结果onSave(data) {(, data, { flag: "a" });}// websocket 消息接收 回调onMessage(data, err) {if (err) return;const res = (data);if ( !== 0) {();return;}// 接收消息结果并进行保存const audio = res.data.audio;const audioBuf = (audio, "base64");(audioBuf);if ( == 0 && res.data.status == 2) {();();}}onClose() {("close");}onError(error) {(error);}}module.exports = XunFeiTTS;

效果演示

volute · 语雀​知乎视频​

源码地址

Github 源码地址 , 如果对你有帮助,请给个star~

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。