- 原始每包数据过于大,后台不能接收,需要分包处理,每包最大1024
- 原始采样率为48000;通过合并压缩为自己所需采样率,本例中最终采样率为8000
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset=“UTF-8”>
- <meta name=“viewport” content=“width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0”>
- <meta name=“apple-mobile-web-capable” content=“yes”>
- <title>WebSocket发送音频流</title>
- </head>
- <body>
- <button id=“intercomBegin”>开始对讲</button>
- <button id=“intercomEnd”>关闭对讲</button>
- </body>
- <script type=“text/javascript”>
- var begin = document.getElementById(‘intercomBegin’);
- var end = document.getElementById(‘intercomEnd’);
- var ws = null; //实现WebSocket
- var record = null; //多媒体对象,用来处理音频
- function init(rec) {
- recrecord = rec;
- }
- //录音对象
- var Recorder = function(stream) {
- var sampleBits = 16; //输出采样数位 8, 16
- var sampleRate = 8000; //输出采样率
- var context = new AudioContext();
- var audioInput = context.createMediaStreamSource(stream);
- var recorder = context.createScriptProcessor(4096, 1, 1);
- var audioData = {
- size: 0, //录音文件长度
- buffer: [], //录音缓存
- inputSampleRate: 48000, //输入采样率
- inputSampleBits: 16, //输入采样数位 8, 16
- outputSampleRate: sampleRate, //输出采样数位
- oututSampleBits: sampleBits, //输出采样率
- clear: function() {
- this.buffer = [];
- this.size = 0;
- },
- input: function(data) {
- this.buffer.push(new Float32Array(data));
- this.size += data.length;
- },
- compress: function() { //合并压缩
- //合并
- var data = new Float32Array(this.size);
- var offset = 0;
- for (var i = 0; i < this.buffer.length; i++) {
- data.set(this.buffer[i], offset);
- offset += this.buffer[i].length;
- }
- //压缩
- var compression = parseInt(this.inputSampleRate / this.outputSampleRate);
- var length = data.length / compression;
- var result = new Float32Array(length);
- var index = 0,
- j = 0;
- while (index < length) {
- result[index] = data[j];
- j += compression;
- index++;
- }
- return result;
- },
- encodePCM: function() { //这里不对采集到的数据进行其他格式处理,如有需要均交给服务器端处理。
- var sampleRate = Math.min(this.inputSampleRate, this.outputSampleRate);
- var sampleBits = Math.min(this.inputSampleBits, this.oututSampleBits);
- var bytes = this.compress();
- var dataLength = bytes.length * (sampleBits / 8);
- var buffer = new ArrayBuffer(dataLength);
- var data = new DataView(buffer);
- var offset = 0;
- for (var i = 0; i < bytes.length; i++, offset += 2) {
- var s = Math.max(-1, Math.min(1, bytes[i]));
- data.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
- }
- return new Blob([data]);
- }
- };
- var sendData = function() { //对以获取的数据进行处理(分包)
- var reader = new FileReader();
- reader.onload = e => {
- var outbuffer = e.target.result;
- 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);
- }
- }
- }
- };
- reader.readAsArrayBuffer(audioData.encodePCM());
- audioData.clear();//每次发送完成则清理掉旧数据
- };
- this.start = function() {
- audioInput.connect(recorder);
- recorder.connect(context.destination);
- }
- this.stop = function() {
- recorder.disconnect();
- }
- this.getBlob = function() {
- return audioData.encodePCM();
- }
- this.clear = function() {
- audioData.clear();
- }
- recorder.onaudioprocess = function(e) {
- var inputBuffer = e.inputBuffer.getChannelData(0);
- audioData.input(inputBuffer);
- sendData();
- }
- }
- /*
- * WebSocket
- */
- function useWebSocket() {
- ws = new WebSocket(“ws://172.18.5.61/ws”);
- ws.binaryType = ‘arraybuffer’; //传输的是 ArrayBuffer 类型的数据
- ws.onopen = function() {
- console.log(‘握手成功’);
- if (ws.readyState == 1) { //ws进入连接状态,则每隔500毫秒发送一包数据
- record.start();
- }
- };
- ws.onmessage = function(msg) {
- console.info(msg)
- }
- ws.onerror = function(err) {
- console.info(err)
- }
- }
- /*
- * 开始对讲
- */
- begin.onclick = function() {
- navigatornavigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;
- if (!navigator.getUserMedia) {
- alert(‘浏览器不支持音频输入’);
- } else {
- navigator.getUserMedia({
- audio: true
- },
- function(mediaStream) {
- init(new Recorder(mediaStream));
- console.log(‘开始对讲’);
- useWebSocket();
- },
- function(error) {
- console.log(error);
- switch (error.message || error.name) {
- case ‘PERMISSION_DENIED’:
- case ‘PermissionDeniedError’:
- console.info(‘用户拒绝提供信息。’);
- break;
- case ‘NOT_SUPPORTED_ERROR’:
- case ‘NotSupportedError’:
- console.info(‘浏览器不支持硬件设备。’);
- break;
- case ‘MANDATORY_UNSATISFIED_ERROR’:
- case ‘MandatoryUnsatisfiedError’:
- console.info(‘无法发现指定的硬件设备。’);
- break;
- default:
- console.info(‘无法打开麦克风。异常信息:’ + (error.code || error.name));
- break;
- }
- }
- )
- }
- }
- /*
- * 关闭对讲
- */
- end.onclick = function() {
- if (ws) {
- ws.close();
- record.stop();
- console.log(‘关闭对讲以及WebSocket’);
- }
- }
- </script>
- </html>
本文链接地址: WebSocket发送音频流