定时音频数据采集并发送websocket实时播放

一 定时音频数据采集并发送websocket实时播放

<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>定时音频数据采集</title></head><body><div><audio autoplay></audio><input onclick="startRecording()" type="button" value="录音" /><input onclick="stopRecording()" type="button" value="停止" /><input onclick="playRecording()" type="button" value="播放" /><input onclick="uploadAudio()" type="button" value="提交" /><br /><div id="recordingslist"></div></div><script type="text/javascript" src="Recorder.js"></script><script>var recorder;var audio = document.querySelector('audio');setInterval(function(){startRecording();setTimeout(function() { stopRecording(); },1200);},1200);var socket = new WebSocket('ws://172.16.39.203:8899/websocket/79'); // 替换为您的WebSocket服务器地址socket.onopen = function(event) { };      // 打开WebSocket连接时的回调函数socket.onmessage = function(event) { };   // 接收到WebSocket消息时的回调函数socket.onclose = function(event) { };     // WebSocket连接关闭时的回调函数function startRecording() {HZRecorder.get(function(rec) {  recorder = rec;recorder.start();}, {sampleBits: 16,sampleRate: 16000,bufferLength: 4096});}function stopRecording() {recorder.stop();var blob = recorder.getBlob();zh(blob);}function  zh(blob) {var reader = new FileReader();reader.onload = function(event) {var arrayBuffer = event.target.result;socket.send(arrayBuffer);};reader.readAsArrayBuffer(blob);}</script></body>
</html>

Recorder.js

(function (window) {//兼容window.URL = window.URL || window.webkitURL;navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;var HZRecorder = function (stream, config) {config = config || {};config.sampleBits = config.sampleBits || 8      //采样数位 8, 16config.sampleRate = config.sampleRate || (44100 / 6);   //采样率(1/6 44100)var context = new (window.webkitAudioContext || window.AudioContext)();var audioInput = context.createMediaStreamSource(stream);var createScript = context.createScriptProcessor || context.createJavaScriptNode;var recorder = createScript.apply(context, [4096, 1, 1]);var mp3ReceiveSuccess, currentErrorCallback;var audioData = {size: 0          //录音文件长度, buffer: []     //录音缓存, inputSampleRate: context.sampleRate    //输入采样率, inputSampleBits: 16       //输入采样数位 8, 16, outputSampleRate: config.sampleRate    //输出采样率, oututSampleBits: config.sampleBits       //输出采样数位 8, 16, 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;}, encodeWAV: 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(44 + dataLength);var data = new DataView(buffer);var channelCount = 1;//单声道var offset = 0;var writeString = function (str) {for (var i = 0; i < str.length; i++) {data.setUint8(offset + i, str.charCodeAt(i));}}// 资源交换文件标识符 writeString('RIFF'); offset += 4;// 下个地址开始到文件尾总字节数,即文件大小-8 data.setUint32(offset, 36 + dataLength, true); offset += 4;// WAV文件标志writeString('WAVE'); offset += 4;// 波形格式标志 writeString('fmt '); offset += 4;// 过滤字节,一般为 0x10 = 16 data.setUint32(offset, 16, true); offset += 4;// 格式类别 (PCM形式采样数据) data.setUint16(offset, 1, true); offset += 2;// 通道数 data.setUint16(offset, channelCount, true); offset += 2;// 采样率,每秒样本数,表示每个通道的播放速度 data.setUint32(offset, sampleRate, true); offset += 4;// 波形数据传输率 (每秒平均字节数) 单声道×每秒数据位数×每样本数据位/8 data.setUint32(offset, channelCount * sampleRate * (sampleBits / 8), true); offset += 4;// 快数据调整数 采样一次占用字节数 单声道×每样本的数据位数/8 data.setUint16(offset, channelCount * (sampleBits / 8), true); offset += 2;// 每样本数据位数 data.setUint16(offset, sampleBits, true); offset += 2;// 数据标识符 writeString('data'); offset += 4;// 采样数据总数,即数据总大小-44 data.setUint32(offset, dataLength, true); offset += 4;// 写入采样数据 if (sampleBits === 8) {for (var i = 0; i < bytes.length; i++, offset++) {var s = Math.max(-1, Math.min(1, bytes[i]));var val = s < 0 ? s * 0x8000 : s * 0x7FFF;val = parseInt(255 / (65535 / (val + 32768)));data.setInt8(offset, val, true);}} else {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], { type: 'audio/wav' });}};//开始录音this.start = function () {audioInput.connect(recorder);recorder.connect(context.destination);}//停止this.stop = function () {recorder.disconnect();}//获取音频文件this.getBlob = function () {this.stop();return audioData.encodeWAV();}//回放this.play = function (audio) {audio.src = window.URL.createObjectURL(this.getBlob());}//上传this.upload = function (url, callback) {var fd = new FormData();fd.append("audioData", this.getBlob());var xhr = new XMLHttpRequest();if (callback) {xhr.upload.addEventListener("progress", function (e) {callback('uploading', e);}, false);xhr.addEventListener("load", function (e) {callback('ok', e);}, false);xhr.addEventListener("error", function (e) {callback('error', e);}, false);xhr.addEventListener("abort", function (e) {callback('cancel', e);}, false);}xhr.open("POST", url);xhr.send(fd);}//音频采集recorder.onaudioprocess = function (e) {audioData.input(e.inputBuffer.getChannelData(0));//record(e.inputBuffer.getChannelData(0));}};//抛出异常HZRecorder.throwError = function (message) {alert(message);throw new function () { this.toString = function () { return message; } }}//是否支持录音HZRecorder.canRecording = (navigator.getUserMedia != null);//获取录音机HZRecorder.get = function (callback, config) {if (callback) {if (navigator.getUserMedia) {navigator.getUserMedia({ audio: true } //只启用音频, function (stream) {var rec = new HZRecorder(stream, config);callback(rec);}, function (error) {switch (error.code || error.name) {case 'PERMISSION_DENIED':case 'PermissionDeniedError':HZRecorder.throwError('用户拒绝提供信息。');break;case 'NOT_SUPPORTED_ERROR':case 'NotSupportedError':HZRecorder.throwError('浏览器不支持硬件设备。');break;case 'MANDATORY_UNSATISFIED_ERROR':case 'MandatoryUnsatisfiedError':HZRecorder.throwError('无法发现指定的硬件设备。');break;default:HZRecorder.throwError('无法打开麦克风。异常信息:' + (error.code || error.name));break;}});} else {HZRecorder.throwErr('当前浏览器不支持录音功能。'); return;}}}window.HZRecorder = HZRecorder;
})(window);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/621894.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【python】进阶--->MySQL数据库(三)

一、修改列的类型长度及约束 alter table 表名 modify 列名 类型(长度) [约束];修改列名 : alter table 表名 change 旧列名 新列名 类型(长度) [约束];二、数据查询语言 查询表中所有的数据 : select * from 表名; 查询表中部分列数据 : select 列名1, 列名2 from 表名;1. …

进程等待-wait和waitpid

目录 1.为什么要进程等待 2.如何进程等待&#xff1f; 1.wait函数 2.waitpid 1.pid 2.status 3.options/非堵塞轮询 1.为什么要进程等待 1.子进程退出&#xff0c;如果父进程没有退出&#xff0c;那么子进程就会变成僵尸状态。僵尸状态会变得刀枪不入&#xff0c;kiil -…

如何使用vite框架封装一个js库,并发布npm包

目录 前言介绍 一、创建一个vite项目 1、使用创建命令&#xff1a; 2、选择others 3、 模板选择library 4、选择开发语言 ​编辑 二、安装依赖 三、目录介绍 1、vite.config.ts打包文件 2、package.json命令配置文件 三、发布npm 1、注册npm账号 2、设置npm源 3、登…

Echarts 折线图圆点属性【圆点大小】【鼠标悬停时放大圆点】

调整 ECharts 折线图上的圆点大小 可以通过设置相应的系列属性实现。具体来说&#xff0c;可以通过设置 symbolSize 属性来控制圆点的大小option {xAxis: {type: category,data: [Mon, Tue, Wed, Thu, Fri, Sat, Sun]},yAxis: {type: value},series: [{data: [820, 932, 901, …

让代码比你来时更干净

** 代码设计原则 ** 一、 函数设计 每个函数和每个模块都全神贯注于一件事明确的定义API尽量少的方法和函数减少依赖关系&#xff0c;便于维护 二、 逻辑原则 代码的逻辑直截了当&#xff0c;让缺陷难以隐藏构建简单的抽象没有重复的代码 三、 增益设计 性能调到最优&a…

【模型评估 05】Holdout、交叉检验、自助法

机器学习中&#xff0c;我们通常把样本分为训练集和测试集&#xff0c;训练集用于训练模型&#xff0c;测试集用于评估模型。在样本划分和模型验证的过程中&#xff0c;存在着不同的抽样方法和验证方法。 1. 在模型评估过程中&#xff0c;有哪些主要的验证方法&#xff0c;它们…

Debian(Linux)局域网共享文件-NFS

NFS (Network File system) 是一种客户端-服务器文件系统协议&#xff0c;允许多个系统或用户访问相同的共享文件夹或文件。最新版本是 NFS-V4&#xff0c;共享文件就像存储在本地一样。它提供了中央管理&#xff0c;可以使用防火墙和 Kerberos 身份验证进行保护。 本文将指导…

经典蓝牙连接过程

目录 1. Inquiry过程 2. 连接过程 2.1 create connection(必选) 2.

系列四、Spring Security中的认证 授权(前后端不分离)

一、Spring Security中的认证 & 授权&#xff08;前后端不分离&#xff09; 1.1、MyWebSecurityConfigurerAdapter /*** Author : 一叶浮萍归大海* Date: 2024/1/11 21:50* Description:*/ Configuration public class MyWebSecurityConfigurerAdapter extends WebSecuri…

安卓应用无法拉起部分机型微信支付

错误提示&#xff1a; 2024-01-11 09:01:01.878 11754-11754 MicroMsg.S...ApiImplV10 com.bm.read E register app failed for wechat app signature check failed 2024-01-11 09:01:01.879 11754-11754 MicroMsg.S...ApiImplV10 com.bm.read E s…

建站为什么需要服务器?(Web服务器与计算机对比)

​  在部署网站时&#xff0c;底层基础设施在确保最佳性能、可靠性和可扩展性方面发挥着至关重要的作用。虽然大多数人都熟悉个人计算机 (PC) 作为日常工作和个人任务的设备&#xff0c;但 PC 和 Web 服务器之间存在显著差异。在这篇文章中&#xff0c;我们将讨论这些差异是什…

CentOS:docker容器日志清理

1.先查看磁盘空间 df -h 2.找到容器的containerId-json.log文件,并清理 find /var/lib/docker/containers/ -name *-json.log |xargs du -sh 3、可以根据需求清理对应日志也可以清理数据大的日志 $ cat /dev/null > /var/lib/docker/containers/dbaee0746cc6adad3768b4ef…

java基础知识点系列——数据输入(五)

java基础知识点系列——数据输入&#xff08;五&#xff09; 数据输入概述 Scanner使用步骤 &#xff08;1&#xff09;导包 import java.util.Scanner&#xff08;2&#xff09;创建对象 Scanner sc new Scanner(System.in)&#xff08;3&#xff09;接收数据 int i sc…

【数据库集群】之一主一从

目录 一、mysql集群概念二、mysql集群环境配置实验1、全新的服务器安装全新的数据库&#xff08;可以在vm中克隆比较快&#xff0c;克隆的服务器要没有安装好数据库&#xff0c;实验环境&#xff1a;mysql80&#xff09;2、配置域名解析3、一主一从服务器的配置&#xff1a;一、…

算法训练营Day39

#Java #动态规划 Feeling and experiences&#xff1a; 爬楼梯&#xff08;进阶版&#xff09;&#xff1a;卡码网题目链接 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬至多m (1 < m < n)个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; …

Innosetup 读写注册表,读写INI文件

一.innosetup读写注册表 1.注册表读写字符串 (RegQueryStringValue&#xff0c;RegWriteStringValue) RegQueryStringValue(HKEY_CURRENT_USER, SOFTWARE\SODA, appversion, appversion) RegWriteStringValue(HKEY_CURRENT_USER, SOFTWARE\SODA, appversion, s…

MySQL之多表连接查询、AS别名、扩展内容(information_schema的基本应用)

文章目录 前言一、引入多表连接查询二、多表连接查询案例1.准备对应的库表2.案例 三、AS别名用法示例 四、扩展内容1、information_schema的基本应用2、创建视图示例3、information_schema.tables视图的应用3.1、示例 五、show命令总结总结 前言 第三章内容主要描述了mysql使用…

InternLM第4次课笔记

XTuner 大模型单卡低成本微调实战 1 Finetune介绍 2 XTuner介绍 XTuner中微调的技术&#xff1a; 3 8GB显卡玩转LLM 4 动手实战环节 https://github.com/InternLM/tutorial/tree/main/xtuner

@RequestBody 注解内置的 HttpMessageConverter 实现类来解析请求体

在 Spring MVC 中&#xff0c;RequestBody 注解默认使用内置的 HttpMessageConverter 实现类来解析请求体&#xff0c;并尝试将其转换为方法参数所需的对象类型。如果需要指定解析的数据类型&#xff0c;可以通过在方法参数上添加更具体的注解来实现。 以下是一些常见的用于指…