html5使⽤websocket发送(PCM)⾳频数据到服务器,再转
在wav⽂件
PCM格式
通过websocket发送⾳频数据。
<html>
<head>
<meta charset="utf-8">
<title>test</title>
</head>
<body>
<div>
<button id="intercomBegin">开始对讲</button>
<button id="intercomEnd">关闭对讲</button>
</div>
</body>
<script>
var begin = ElementById('intercomBegin');
var end = ElementById('intercomEnd');
typeof array
var ws = null;//实现WebSocket
var record=null;//多媒体对象,⽤来处理⾳频
var timeInte = null;//定义⼀个定时器
console.log('开始对讲')
}
console.log('关闭对讲')
if(ws) {
ws.close();
record.stop();
clearInterval(timeInte);
}
}
function init(rec){
record = rec;
}
if (!UserMedia) {
alert('浏览器不⽀持⾳频输⼊');
}else{
{ audio: true },
function (mediaStream) {
init(new Recorder(mediaStream));
init(new Recorder(mediaStream));
},function(error){
console.log(error)
}
)
}
//录⾳对象
var Recorder = function(stream) {
var sampleBits = 16;//输出采样数位 8, 16
var sampleRate = 8000;//输出采样率
var context = new AudioContext();
var audioInput = ateMediaStreamSource(stream);
var recorder = ateScriptProcessor(4096, 1, 1);
var audioData = {
size: 0 //录⾳⽂件长度
, buffer: [] //录⾳缓存
, inputSampleRate: sampleRate //输⼊采样率
, 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 = thispress();
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]);
}
};
this.start = function () {
}
}
this.stop = function () {
recorder.disconnect();
}
dePCM();
}
this.clear = function() {
audioData.clear();
}
audioData.input(ChannelData(0));
}
};
function receive(data) {
if( typeof e == 'string' && JSON.parse(e).message=='OK'){
console.log('OK');
}else{
var buffer = (new Response(data)).arrayBuffer();
buffer.then(function(buf){
console.log(">>>#recv start >>>>>>>#"); var audioContext = new ( window.AudioContext || window.webkitAudioContext )();
var fileResult =addWavHeader(buf, '8000', '16', '1');//解析数据转码wav
audioContext.decodeAudioData(fileResult, function(buffer) {
_visualize(audioContext,buffer);//播放
});
console.log(">>>#recv end >>>>>>>#"); });
}
}
//处理⾳频流,转码wav
var addWavHeader = function(samples,sampleRateTmp,sampleBits,channelCount){
var dataLength = samples.byteLength;
var buffer = new ArrayBuffer(44 + dataLength);
var view = new DataView(buffer);
function writeString(view, offset, string){
for (var i = 0; i < string.length; i++){
view.setUint8(offset + i, string.charCodeAt(i));
}
}
var offset = 0;
/* 资源交换⽂件标识符 */
writeString(view, offset, 'RIFF'); offset += 4;
/* 下个地址开始到⽂件尾总字节数,即⽂件⼤⼩-8 */
view.setUint32(offset, /*32*/ 36 + dataLength, true); offset += 4;
/* WAV⽂件标志 */
writeString(view, offset, 'WAVE'); offset += 4;
/* 波形格式标志 */
writeString(view, offset, 'fmt '); offset += 4;
/* 过滤字节,⼀般为 0x10 = 16 */
view.setUint32(offset, 16, true); offset += 4;
/* 格式类别 (PCM形式采样数据) */
view.setUint16(offset, 1, true); offset += 2;
/* 通道数 */
view.setUint16(offset, channelCount, true); offset += 2;
/
* 采样率,每秒样本数,表⽰每个通道的播放速度 */
view.setUint32(offset, sampleRateTmp, true); offset += 4;
/* 波形数据传输率 (每秒平均字节数) 通道数×每秒数据位数×每样本数据位/8 */
/* 波形数据传输率 (每秒平均字节数) 通道数×每秒数据位数×每样本数据位/8 */
view.setUint32(offset, sampleRateTmp * channelCount * (sampleBits / 8), true); offset +=4;
/* 快数据调整数采样⼀次占⽤字节数通道数×每样本的数据位数/8 */
view.setUint16(offset, channelCount * (sampleBits / 8), true); offset += 2;
/* 每样本数据位数 */
view.setUint16(offset, sampleBits, true); offset += 2;
/* 数据标识符 */
writeString(view, offset, 'data'); offset += 4;
/
* 采样数据总数,即数据总⼤⼩-44 */
view.setUint32(offset, dataLength, true); offset += 4;
function floatTo32BitPCM(output, offset, input){
input = new Int32Array(input);
for (var i = 0; i < input.length; i++, offset+=4){
output.setInt32(offset,input[i],true);
}
}
function floatTo16BitPCM(output, offset, input){
input = new Int16Array(input);
for (var i = 0; i < input.length; i++, offset+=2){
output.setInt16(offset,input[i],true);
}
}
function floatTo8BitPCM(output, offset, input){
input = new Int8Array(input);
for (var i = 0; i < input.length; i++, offset++){
output.setInt8(offset,input[i],true);
}
}
if(sampleBits == 16){
floatTo16BitPCM(view, 44, samples);
}else if(sampleBits == 8){
floatTo8BitPCM(view, 44, samples);
}else{
floatTo32BitPCM(view, 44, samples);
}
return view.buffer;
}
//播放⾳频
var _visualize = function(audioContext, buffer) {
var audioBufferSouceNode = ateBufferSource(),
analyser = ateAnalyser(),
that = this;
//将信号源连接到分析仪
//将分析仪连接到⽬的地(扬声器),否则我们将听不到声⾳
//然后将缓冲区分配给缓冲区源节点
audioBufferSouceNode.buffer = buffer;
//发挥作⽤
if (!audioBufferSouceNode.start) {
audioBufferSouceNode.start = On //在旧浏览器中使⽤noteOn⽅法 audioBufferSouceNode.stop = Off //在旧浏览器中使⽤noteOff⽅法 };
//如果有的话,停⽌前⼀个声⾳
if (this.animationId !== null) {
cancelAnimationFrame(this.animationId);
}
audioBufferSouceNode.start(0);
audo.source = audioBufferSouceNode;
audo.audioContext = audioContext;
}
var ws = new WebSocket("ws://127.0.0.1:6200");
var ws = new WebSocket("ws://127.0.0.1:6200");
ws.binaryType = 'arraybuffer'; //传输的是 ArrayBuffer 类型的数据
console.log('握⼿成功');
//业务命令构建
var data = {
"cmd": "jtv",//发送命令
"id": "018665897939",//发送设备id
"type": 1,//对讲类型
"channel": 0//语⾳通道
}
//ws.send(JSON.stringify(data)); //这⾥是发送消息。不包括⾳频数据,先注掉
};
timeInte=setInterval(function(){
adyState==1){//ws进⼊连接状态,则每隔500毫秒发送⼀包数据
record.start();
console.log(">>>>###send Blob start >>>>>>");
console.Blob());
ws.Blob()); //发送⾳频数据
console.log(">>>>###send Blob end >>>>>>");
record.clear(); //每次发送完成则清理掉旧数据
}
},500); //每隔500ms发送⼀次,定时器
/
//
console.log( "Received Message: " + evt.data);
receive(evt.data);
}
///
}
</script>
</html>
通过服务器来接收⾳频数据。这个时间可以以⽂件形式保存下来为.pcm就可以了。这⾥就使⽤⼯具来接收
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
推荐文章
热门文章
-
随机森林算法的改进方法
2024-10-02 -
基于随机森林算法的风险预警模型研究
2024-10-02 -
Python中的随机森林算法详解
2024-10-02 -
随机森林发展历史
2024-10-02 -
如何使用随机森林进行时间序列数据模式识别(八)
2024-10-02 -
随机森林回归模型原理
2024-10-02 -
如何使用随机森林进行时间序列数据模式识别(六)
2024-10-02 -
如何使用随机森林进行时间序列数据预测(四)
2024-10-02 -
如何使用随机森林进行异常检测(六)
2024-10-02 -
随机森林算法和grandientboosting算法 -回复
2024-10-02 -
随机森林方法总结全面
2024-10-02 -
随机森林算法原理和步骤
2024-10-02 -
随机森林的原理
2024-10-02 -
随机森林 重要性
2024-10-02 -
随机森林算法
2024-10-02 -
机器学习中随机森林的原理
2024-10-02 -
随机森林算法原理
2024-10-02 -
使用计算机视觉技术进行动物识别的技巧
2024-10-02 -
基于crf命名实体识别实验总结
2024-10-02 -
transformer预测模型训练方法
2024-10-02
最新文章
-
随机森林算法介绍及R语言实现
2024-10-02 -
基于随机森林优化的神经网络算法在冬小麦产量预测中的应用研究_百度文 ...
2024-10-02 -
基于正则化贪心森林算法的情感分析方法研究
2024-10-02 -
随机森林算法和grandientboosting算法
2024-10-02 -
基于随机森林的图像分类算法研究
2024-10-02 -
随机森林结合直接正交信号校正的模型传递方法
2024-10-02
发表评论