Websocket接收且展示音频流的实践
日期:2023年03月27日     新闻分类: 技术中心      浏览:2345次
内容导读:Websocket接收且展示音频流的实践

1、背景

要求在机器人项目的页面中展示,实时由websocket发来的音频流(波形图)

2、技术调研

Express

Websocket

音频波形图(recorder-core、pcm-p)

解码(js-64、g7112pcm)

3、Express

使用express建立后端服务做demo

const express = require('express');

const io = require('nodejs-websocket');

const app = express();

app.get('/', function (req, res) {

  res.send('Hello World!');

});

const server = app.listen(3000, function () {

  let host = server.address().address;

  let port = server.address().port;

console.log('Example app listening at http://%s:%s', host, port);

});

4、Websocket

var url = "ws://127.0.0.7:3001";

      this.ws = new WebSocket(url);

      this.ws.binaryType = "arraybuffer";

      var that = this;

      this.ws.addEventListener("open", function() {

        let jsonData = { state: "start", channel: "1" };

        that.ws.send(JSON.stringify(jsonData));

      });


const fs = require("fs");

const source = "./audio.pcm"; // 读取目标

io.createServer(connection => {

  console.log('new connection...');

  connection.on("text", function(data) {

    console.log("接收到的客户端消息:"+data);

    let rs = fs.createReadStream(source);

    rs.on("data", data => {

      connection.sendBinary(data);

    });

  });  

  connection.on("close", function (code, reason) {

      console.log("Connection closed");

  });

  connection.on("error",() => {

    console.log('服务异常关闭...');

  });

}).listen(3001);

5、音频波形图(recorder-core、pcm-p)

import Recorder from "recorder-core";

import PCMP from "pcm-p"

//需要使用到的音频格式编码引擎的js文件统统加载进来

import "recorder-core/src/engine/mp3";

import "recorder-core/src/engine/mp3-engine";

//比如 import Recorder from 'recorder-core/recorder.mp3.min' //已包含recorder-core和mp3格式支持

//可选的扩展支持项

import "recorder-core/src/extensions/wavesurfer.view";

this.p = new PCMP({

        encoding: "16bitInt",

        channels: 1,

        sampleRate: 32000,

        flushTime: 2000

      })

      var wave;

      var set = {

        elem: ".recwave",

        scale: 2, //缩放系数,应为正整数,使用2(3? no!)倍宽高进行绘制,避免移动端绘制模糊

        fps: 50, //绘制帧率,不可过高,50-60fps运动性质动画明显会流畅舒适,实际显示帧率达不到这个值也并无太大影响

        duration: 2500, //当前视图窗口内最大绘制的波形的持续时间,此处决定了移动速率

        direction: -1, //波形前进方向,取值:1由左往右,-1由右往左

        position: 0, //绘制位置,取值-1到1,-1为最底下,0为中间,1为最顶上,小数为百分比

        centerHeight: 1, //中线基础粗细,如果为0不绘制中线,position=±1时应当设为0

        //波形颜色配置:[位置,css颜色,...] 位置: 取值0.0-1.0之间

        linear: [

          0,

          "rgba(0,187,17,1)",

          0.7,

          "rgba(255,215,0,1)",

          1,

          "rgba(255,102,0,1)"

        ],

        centerColor: "" //中线css颜色,留空取波形第一个渐变颜色

      };

      wave = Recorder.WaveSurferView(set);

6、解码(js-64、g7112pcm)

import { 64 } from 'js-64';

import { decodeUlaw } from 'g7112pcm';

this.ws.addEventListener("message", function(event) {

let dataAudio = decodeUlaw(64.toUint8Array(response.VoiceData)); // 后端为节约流量直接发送G711压缩μ-law算法形式的64

        this.pAudio.feed(dataAudio);

        this.pAudio.volume(this.volumeAudio);

        let buf = Buffer.from(dataAudio);

        let data = new Uint16Array(buf.buffer, buf.byteOffset, buf.byteLength / Uint16Array.BYTES_PER_ELEMENT);

        this.waverAudio.input(data, 70, this.Config.sampleRate);

      });

7、备注

Express是前端调研可行性时,临时后端服务的方案,正式的环境,使用后端同学的服务,音频流也是从硬件采集,实时经后端处理,传输到前端展示


Html

<div class="lb_audio_waver" v-if="Config.controlPanelHasAudio">

    <div class="pandect_cont_top">

        <div class="pandect_cont_top_left">

            <div class="_icon"></div>

            <div class="pandect_cont_">音频波形图</div>

        </div>

    </div>

    <div class="audio_recwave"></div>

    <div class="audio_btn" @click="volumePlay" v-show="audioIsQuiet">

        <i class="el-icon-phone-outline"></i> 播放

    </div>

    <div class="audio_btn" @click="volumeQuiet" v-show="!audioIsQuiet">

        <i class="el-icon-phone"></i> 静音

    </div>

</div>

版权所有: 山西科达自控股份有限公司 备案号:晋ICP备09004627号-2   

邮箱

keda@sxkeda.com

电话

400-0351-150

微信

专属
客服

留言

右侧导航