js实现mp3录⾳通过websocket实时传送+简易波形图效果
废话:想不到我的第⼀篇博客是关于前端,作为⼀名后端的⼩菜,前端⽅⾯肯定还有很多不⾜之处,如果⽂章有任何问题欢迎指正。感谢⼤家。好了!废话不多说下⾯讲⼀下需求。
需求:公司要求实现web端的录⾳并通过websocket实时上传⾄java后台,⽽且能通过vlc实时播放,简单⼀点讲就是我⽤⽹页在那⼀边讲话,⼀个⼤喇叭就能实时把我的话播出去,这样是不是通俗易懂呀,⽽且呢公司要求⽤mp3格式。当然啦!为了知道⾃⼰在讲话需要⼀个波形图,这⾥主要实现前半部分功能,后半部分⾂妾也做不到呀!后半部分的vlc播放呢如果⼤家想知道,可以留⾔,届时可以给⼤家指条明路
前端实现:
引⼊:
<script type="text/javascript" src="/js/recorder/recordmp3.js"></script>
这个跟⼤佬的js有点不⼀样,我在⾥⾯加了⼀点东西,⽽且在这个js⾥⾯引⼊了两个另外的js,lame.min.js和worker-realtime.js,这俩在⼤佬的代码⾥有
页⾯:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312"/>
<title>测试</title>
</head>
<body>
<button id="intercomBegin">开始对讲</button>
<button id="intercomEnd">关闭对讲</button>
<canvas id="casvased" ></canvas>
</body>
<script type="text/javascript" src="/js/jquery-3.3.1.js"></script>
<script type="text/javascript" src="/js/recorder/recordmp3.js"></script>
<script type="text/javascript">
var begin = ElementById('intercomBegin');
var end = ElementById('intercomEnd');
var canvas = ElementById("casvased");
var canvasCtx = Context("2d");
var ws = null; //实现WebSocket
var recorder;
/*
* WebSocket
*/
function useWebSocket() {
ws = new WebSocket("ws://127.0.0.1:8089/send/voice");
ws.binaryType = 'arraybuffer'; //传输的是 ArrayBuffer 类型的数据
console.log('握⼿成功');
if (ws.readyState == 1) { //ws进⼊连接状态,则每隔500毫秒发送⼀包数据
recorder.start();
}
};
console.info(msg)
}
console.info(err)
}
}
/*
* 开始对讲
*/
recorder = new MP3Recorder({
debug: true,
funOk: function () {
console.log('点击录制,开始录⾳! ');
},
funCancel: function (msg) {
console.log(msg);
recorder = null;
}
});
}
/
*
* 关闭对讲
*/
if (ws) {
ws.close();
recorder.stop();
console.log('关闭对讲以及WebSocket');
}
}
var sendData = function() { //对以获取的数据进⾏处理(分包)
var reader = new FileReader();
var outbuffer = sult;
var arr = new Int8Array(outbuffer);
if (arr.length > 0) {
var tmparr = new Int8Array(1024);
var j = 0;
for (var i = 0; i < arr.byteLength; i++) {
tmparr[j++] = arr[i];
if (((i + 1) % 1024) == 0) {
ws.send(tmparr);
if (arr.byteLength - i - 1 >= 1024) {
tmparr = new Int8Array(1024);
} else {
tmparr = new Int8Array(arr.byteLength - i - 1);
}
j = 0;
}
if ((i + 1 == arr.byteLength) && ((i + 1) % 1024) != 0) {
ws.send(tmparr);
}
}
}
};
})
}; </script> </html>
recordmp3.js
(function (exports) {
var MP3Recorder = function (config) {
var recorder = this;
config = config || {};
config.sampleRate = config.sampleRate || 44100;
config.bitRate = config.bitRate || 128;
navigator.webkitGetUserMedia ||
navigator.msGetUserMedia;
if (UserMedia) {
audio: true
},
function (stream) {
var context = new AudioContext(),
microphone = ateMediaStreamSource(stream),
processor = ateScriptProcessor(16384, 1, 1),//bufferSize⼤⼩,输⼊channel数,输出channel数      mp3ReceiveSuccess, currentErrorCallback;
var height = 100;
var width = 400;
const analyser = ateAnalyser()
analyser.fftSize = 1024
//连接到⾳频源
const bufferLength = analyser.frequencyBinCount // 返回的是 analyser的fftsize的⼀半
const dataArray = new Uint8Array(bufferLength);
function draw() {
canvasCtx.clearRect(0, 0, width, height); //清除画布
const requestAnimFrame = questAnimationFrame(draw) || window.webkitRequestAnimationFrame(draw);      canvasCtx.fillStyle = '#000130';
canvasCtx.fillRect(0, 0, width, height);
let barWidth = (width / bufferLength) * 2;
let barHeight;
let x = 0;
let c = 2
for (let i = 0; i < bufferLength; i++) {
barHeight = c+(dataArray[i]/400)*height;
canvasCtx.fillStyle = 'rgb(0, 255, 30)';
canvasCtx.fillRect(x, height / 2 - barHeight / 2, barWidth, barHeight);
x += barWidth + 1;
}
}
draw();
useWebSocket();
config.sampleRate = context.sampleRate;
//边录⾳边转换
var array = ChannelData(0);
realTimeWorker.postMessage({cmd: 'encode', buf: array});
sendData();
};
var realTimeWorker = new Worker('/js/recorder/worker-realtime.js');
switch (d) {
case 'init':
log('初始化成功');
if (config.funOk) {
config.funOk();
}
break;
case 'end':
log('MP3⼤⼩:', e.data.buf.length);
if (mp3ReceiveSuccess) {
mp3ReceiveSuccess(new Blob(e.data.buf, {type: 'audio/mp3'}));
}
break;
case 'error':
log('错误信息:' + );
if (currentErrorCallback) {
currentErrorCallback();
}
break;
default:
log('未知信息:', e.data);
}
};
currentErrorCallback = onError;
mp3ReceiveSuccess = onSuccess;
realTimeWorker.postMessage({cmd: 'finish'});
};
recorder.start = function () {
if (processor && microphone) {
js制作简单的焦点图效果
log('开始录⾳');
}
}
recorder.stop = function () {
if (processor && microphone) {
microphone.disconnect();
processor.disconnect();
log('录⾳结束');
}
}
realTimeWorker.postMessage({
cmd: 'init',
config: {
sampleRate: config.sampleRate,
bitRate: config.bitRate
}
});
},
function (error) {
var msg;
switch (de || error.name) {
case 'PERMISSION_DENIED':
case 'PermissionDeniedError':
msg = '⽤户拒绝访问麦客风';
break;
case 'NOT_SUPPORTED_ERROR':
case 'NotSupportedError':
msg = '浏览器不⽀持麦客风';
break;
case 'MANDATORY_UNSATISFIED_ERROR':
case 'MandatoryUnsatisfiedError':
msg = '不到麦客风设备';
break;
default:
msg = '⽆法打开麦克风,异常信息:' + (de || error.name);      break;
}
if (config.funCancel) {
config.funCancel(msg);
}
});
} else {
if (config.funCancel) {
config.funCancel('当前浏览器不⽀持录⾳功能');
}
}
function log(str) {
if (config.debug) {
console.log(str);
}
}
}
exports.MP3Recorder = MP3Recorder;
})(window);
后端websocket:
这⾥实现的是保存为mp3⽂件
package com.jetosendmon.socket;
import com.jetosendmon.utils.Utils;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.*;
import java.nio.ByteBuffer;
import java.util.Hashtable;
import java.util.Map;
@ServerEndpoint("/send/{key}")
@Component
public class ServerSocket {
private static final Map<String, Session> connections = new Hashtable<>();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); /***
* @Description:打开连接
* @Param: [id, 保存对⽅平台的资源编码
* session]
* @Return: void
* @Author: Liting
* @Date: 2019-10-10 09:22
*/
@OnOpen
public void onOpen(@PathParam("key") String id, Session session) {
System.out.println(id + "连上了");
connections.put(id, session);
}
/**
* 接收消息
*/
@OnMessage
public void onMessage(@PathParam("key") String id, InputStream inputStream) {  System.out.println("来⾃" + id);
try {
int rc = 0;
byte[] buff = new byte[100];
while ((rc = ad(buff, 0, 100)) > 0) {
byteArrayOutputStream.write(buff, 0, rc);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 异常处理
*
* @param throwable
*/
@OnError
public void onError(Throwable throwable) {
throwable.printStackTrace();
/
/TODO ⽇志打印异常
}
/**
* 关闭连接
*/
@OnClose
public void onClose(@PathParam("key") String id) {
System.out.println(id + "断开");
BufferedOutputStream bos = null;
FileOutputStream fos = null;
File file = null;
try {
file = new File("D:\\testtest.mp3");
//输出流
fos = new FileOutputStream(file);
//缓冲流
bos = new BufferedOutputStream(fos);
//将字节数组写出
bos.ByteArray());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bos != null) {
try {

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。