HTML5录音控件
最近的项目又需要用到录音,年前有过调研,再次翻出来使用,这里做一个记录。
HTML5提供了录音支持,因此可以方便使用HTML5来录音,来实现录音、语音识别等功能,语音开发必备。但是ES标准提供的API并不人性化,不方便使用,并且不提供保存为wav的功能,开发起来费劲啊!!
github寻找轮子,发现Recorder.js,基本上可以满足需求了,良好的封装,支持导出wav,但是存在:
- wav采样率不可调整
- recorder创建麻烦,需要自己初始化getUserMedia
- 无实时数据回调,不方便绘制波形
- 。。。
改造轮子
创建recorder工具方法
提供创建recorder工具函数,封装audio接口:
static createRecorder(callback,config){
window.AudioContext = window.AudioContext || window.webkitAudioContext;
window.URL = window.URL || window.webkitURL;
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
if (navigator.getUserMedia) {
navigator.getUserMedia(
{ audio: true } //只启用音频
, function (stream) {
var audio_context = new AudioContext;
var input = audio_context.createMediaStreamSource(stream);
var rec = new Recorder(input, config);
callback(rec);
}
, function (error) {
switch (error.code || error.name) {
case 'PERMISSION_DENIED':
case 'PermissionDeniedError':
throwError('用户拒绝提供信息。');
break;
case 'NOT_SUPPORTED_ERROR':
case 'NotSupportedError':
throwError('浏览器不支持硬件设备。');
break;
case 'MANDATORY_UNSATISFIED_ERROR':
case 'MandatoryUnsatisfiedError':
throwError('无法发现指定的硬件设备。');
break;
default:
throwError('无法打开麦克风。异常信息:' + (error.code || error.name));
break;
}
});
} else {
throwError('当前浏览器不支持录音功能。'); return;
}
}
采样率
H5录制的默认是44k的,文件大,不方便传输,因此需要进行重新采样,一般采用插值取点方法:
以下代码主要来自stackoverflow:
/**
* 转换采样率
* @param data
* @param newSampleRate 目标采样率
* @param oldSampleRate 原始数据采样率
* @returns {any[]|Array}
*/
function interpolateArray(data, newSampleRate, oldSampleRate) {
var fitCount = Math.round(data.length * (newSampleRate / oldSampleRate));
var newData = new Array();
var springFactor = new Number((data.length - 1) / (fitCount - 1));
newData[0] = data[0]; // for new allocation
for (var i = 1; i < fitCount - 1; i++) {
var tmp = i * springFactor;
var before = new Number(Math.floor(tmp)).toFixed();
var after = new Number(Math.ceil(tmp)).toFixed();
var atPoint = tmp - before;
newData[i] = this.linearInterpolate(data[before], data[after], atPoint);
}
newData[fitCount - 1] = data[data.length - 1]; // for new allocation
return newData;
}
function linearInterpolate(before, after, atPoint) {
return before + (after - before) * atPoint;
}
修改导出wav函数exportWAV,增加采样率选项:
/**
* 导出wav
* @param type
* @param desiredSamplingRate 期望的采样率
*/
function exportWAV(type,desiredSamplingRate) {
// 默认为16k
desiredSamplingRate = desiredSamplingRate || 16000;
var buffers = [];
for (var channel = 0; channel < numChannels; channel++) {
var buffer = mergeBuffers(recBuffers[channel], recLength);
// 需要转换采样率
if (desiredSamplingRate!=sampleRate) {
// 插值去点
buffer = interpolateArray(buffer, desiredSamplingRate, sampleRate);
}
buffers.push(buffer);
}
var interleaved = numChannels === 2 ? interleave(buffers[0], buffers[1]) : buffers[0];
var dataview = encodeWAV(interleaved,desiredSamplingRate);
var audioBlob = new Blob([dataview], { type: type });
self.postMessage({ command: 'exportWAV', data: audioBlob });
}
实时录音数据回调
为了方便绘制音量、波形图,需要获取到实时数据:
config新增一个回调函数onaudioprocess:
config = {
bufferLen: 4096,
numChannels: 1, // 默认单声道
mimeType: 'audio/wav',
onaudioprocess:null
};
修改录音数据处理函数:
this.node.onaudioprocess = (e) => {
if (!this.recording) return;
var buffer = [];
for (var channel = 0; channel < this.config.numChannels; channel++) {
buffer.push(e.inputBuffer.getChannelData(channel));
}
// 发送给worker
this.worker.postMessage({
command: 'record',
buffer: buffer
});
// 数据回调
if(this.config.onaudioprocess){
this.config.onaudioprocess(buffer[0]);
}
};
这样,在创建recorder时,配置onaudioprocess就可以获取到实时数据了
实时数据编码
编码计算耗时,需要放到worker执行:
接口函数新增encode,发送消息给worker,让worker执行:
encode(cb,buffer,sampleRate) {
cb = cb || this.config.callback;
if (!cb) throw new Error('Callback not set');
this.callbacks.encode.push(cb);
this.worker.postMessage({ command: 'encode',buffer:buffer,sampleRate:sampleRate});
}
worker里新增encode函数,处理encode请求,完成后执行回调
self.onmessage = function (e) {
switch (e.data.command) {
case 'encode':
encode(e.data.buffer,e.data.sampleRate);
break;
}
};
encode(cb,buffer,sampleRate) {
cb = cb || this.config.callback;
if (!cb) throw new Error('Callback not set');
this.callbacks.encode.push(cb);
this.worker.postMessage({ command: 'encode',buffer:buffer,sampleRate:sampleRate});
}
wav上传
增加一个上传函数:
exportWAVAndUpload(url, callback) {
var _url = url;
exportWAV(function(blob){
var fd = new FormData();
fd.append("audioData", blob);
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);
})
}
完整代码
=点击下载
发现新轮子
今天再次看这个项目,发现这个项目已经不维护了,
Note: This repository is not being actively maintained due to lack of time and interest. If you maintain or know of a good fork, please let me know so I can direct future visitors to it. In the meantime, if this library isn't working, you can find a list of popular forks here: http://forked.yannick.io/mattdiamond/recorderjs.
作者推荐https://github.com/chris-rudmin/Recorderjs,提供更多的功能:
- bitRate (optional) Specifies the target bitrate in bits/sec. The encoder selects an application-specific default when this is not specified.
- bufferLength - (optional) The length of the buffer that the internal JavaScriptNode uses to capture the audio. Can be tweaked if experiencing performance issues. Defaults to
4096
. - encoderApplication - (optional) Specifies the encoder application. Supported values are
2048
- Voice,2049
- Full Band Audio,2051
- Restricted Low Delay. Defaults to2049
. - encoderComplexity - (optional) Value between 0 and 10 which determines latency and processing for resampling.
0
is fastest with lowest complexity.10
is slowest with highest complexity. The encoder selects a default when this is not specified. - encoderFrameSize (optional) Specifies the frame size in ms used for encoding. Defaults to
20
. - encoderPath - (optional) Path to encoderWorker.min.js worker script. Defaults to
encoderWorker.min.js
- encoderSampleRate - (optional) Specifies the sample rate to encode at. Defaults to
48000
. Supported values are8000
,12000
,16000
,24000
or48000
. - leaveStreamOpen - (optional) Keep the stream around when trying to
stop
recording, so you can re-start
without re-initStream
. Defaults tofalse
. - maxBuffersPerPage - (optional) Specifies the maximum number of buffers to use before generating an Ogg page. This can be used to lower the streaming latency. The lower the value the more overhead the ogg stream will incur. Defaults to
40
. - monitorGain - (optional) Sets the gain of the monitoring output. Gain is an a-weighted value between
0
and1
. Defaults to0
- numberOfChannels - (optional) The number of channels to record.
1
= mono,2
= stereo. Defaults to1
. Maximum2
channels are supported. - originalSampleRateOverride - (optional) Override the ogg opus 'input sample rate' field. Google Speech API requires this field to be
16000
. - resampleQuality - (optional) Value between 0 and 10 which determines latency and processing for resampling.
0
is fastest with lowest quality.10
is slowest with highest quality. Defaults to3
. - streamPages - (optional)
dataAvailable
event will fire after each encoded page. Defaults tofalse
.
推荐使用
作者:Jadepeng
出处:jqpeng的技术记事本--http://www.cnblogs.com/xiaoqi
您的支持是对博主最大的鼓励,感谢您的认真阅读。
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
HTML5录音控件的更多相关文章
- 使用jQuery和CSS自定义HTML5 Video 控件 简单适用
Html5 Video是现在html5最流行的功能之一,得到了大多数最新版本的浏览器支持.包括IE9,也是如此.不同的浏览器提供了不同的原生态浏览器视频空间.我们制作自定义视频控件为了在所有的浏览器中 ...
- 一个不错的Html5 DatePicker控件,主要支持手机端。
原地址不知道在哪了,下载地址 QQ群:616945527 Html5控件wen文件夹中DatePicker.rar
- C# winform 支持html5的 控件
OpenWebKitSharp WebKit.net c#winform中使用WebKit传递js对象实现与网页交互 分类: .NET开发2013-08-18 23:55 2496人阅读 评论(1) ...
- HTML5 UI 控件Mobiscroll的使用(年月日三级联动)
概述: 遇到制作一个html5界面,需要选择年月日,其实这个功能很常用.一般我们都是网上找,之前也没有收藏一个自己常用的,今天发现一个不错的库.特此记录一下使用过程,以便以后遇到了方面查阅. 1.官方 ...
- HTML5:控件自动获得焦点
在HTML5中,页面打开后,需要指定的控件自动获得焦点很简单,只需要一个属性就可以实现 - autofocus. 示例如下: <input type="text" auto ...
- HTML5 input控件 placeholder属性
placeholder 属性提供可描述输入字段预期值的提示信息(hint),该提示会在输入字段为空时显示,并会在字段获得焦点时消失. <input placeholder="请输入姓名 ...
- 画板社交工具开发分享——HTML5 canvas控件、PHP、社交分享学习(一)
不谈国内社交网站(人人.微博等)目前的盈利状况如何,facebook.twitter都已经取得了很大的成功.这一定程度上都得益于人们对社交的喜爱和投入. 目前的情况来看,也有很多人已经对直接的文字分享 ...
- 【WEB自动化测试之控件定位】基于HTML5控件的唯一控件属性定位
一.WEB控件定位是什么 要想弄懂这个问题,我们还是基于实践来学习.我们先来看一条入门级别自动化测试用例的构成. DemoCase:正确用户名和密码登录博客园,登录成功 URL: https:// ...
- jquery和css自定义video播放控件
下面介绍一下通过jquery和css自定义video播放控件. Html5 Video是现在html5最流行的功能之一,得到了大多数最新版本的浏览器支持.包括IE9,也是如此.不同的浏览器提供了不同的 ...
随机推荐
- html基础认识,高手别看
HTML5是一种用于在万维网上构建和呈现内容的符号言语.它是HTML规范的第五和当时版别.它是由万维网联盟(W3C)在十月发布的2014 [ 2 ] [ 4 ]和最新的多媒体支持进步言语,一起坚持它简 ...
- MySQL之使用DDL语句创建表
一.使用DDL语句创建表 DDL语言全面数据定义语言(Data Define Language) 主要的DDL动词: CREATE(创建).DROP(删除).ALTER(修改) TRUNCATE(截断 ...
- IO流程中IO向量iovec
作者:Younger Liu,本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 未本地化版本许可协议进行许可. 为了提高从磁盘读取数据到内存的效率,引入了IO向量机制,IO向量即struct ...
- Github--账号重新申请与配置
2017-04-24 最近洗心革面痛下决心要好好再深入学习一番前端,正好加入了一个外包团队接了份单子,外包项目正在如火如荼地进行着,自己也打算趁这个机会来好好学习总结一番. 但是俗话说得好," ...
- poj3159最短路spfa+邻接表
https://vjudge.net/contest/66569#problem/K 相当于模板吧,第一次写spfa的 #include<iostream> #include<cst ...
- ST-1之乱码bug
我印象最深刻的一个错误就是乱码.上学期末做web期末作业时候,我就遇到了好多乱码问题.乱码问题并不是程序本身的逻辑错误,但是却让程序的可用性非常的差.只有输入英文时才能判断结果的正确与否.而且编译器又 ...
- (转)详解JS位置、宽高属性之一:offset系列
很多初学者对于JavaScript中的offset.scroll.client一直弄不明白,虽然网上到处都可以看一张图(图1),但这张图太多太杂,并且由于浏览器差异性,图示也不完全正确. 图一 不知道 ...
- MFC基础程序设计VS2015 最新02
视频教程地址观看:http://pan.baidu.com/s/1mhKQ6kK 对于每个函数的帮助资料都应该详细阅读:a)简要说明:能够快速了解函数的功能:b)参数:每一个参数的功能都应该了解它的含 ...
- MVC两种获取上传的文件数据变量的方式
第一种方式,在控制器中利用HttpPostedFileBase参数对象获取. [HttpPost] public ActionResult SaveFile(HttpPostedFileBase up ...
- FutureTask——另一种闭锁的实现
关于多线程,我们接触对多的,最基础,入门的可能就是实现Runnable接口继承Thead类,因为Java单继承的原因,通常建议是实现Runnable接口.但这种"简单"的线程会带来 ...