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.
0is fastest with lowest complexity.10is 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,24000or48000. - leaveStreamOpen - (optional) Keep the stream around when trying to
stoprecording, so you can re-startwithout 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
0and1. Defaults to0 - numberOfChannels - (optional) The number of channels to record.
1= mono,2= stereo. Defaults to1. Maximum2channels 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.
0is fastest with lowest quality.10is slowest with highest quality. Defaults to3. - streamPages - (optional)
dataAvailableevent 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,也是如此.不同的浏览器提供了不同的 ...
随机推荐
- C语言学习第四章
今天学习C语言循环结构,为什么要用循环呢?因为有时候我们对一堆的数字进行重复的处理的时候要重复的编写一些相同或者差不多的代码,让程序显得很臃肿,而且写着也麻烦,如果用循环来写的话能简化很多,出错的话也 ...
- [ext4]04 磁盘布局 - Meta Block Groups
Meta Block Groups,可以翻译为元块组集. 如果不采用Meta Block Groups特性,在每个冗余备份的超级块的后面是一个完整的(包含所有块组描述符的)块组描述符表的备份.如前所述 ...
- SpringMVC中的session用法及细节记录
前言 初学SpringMVC,最近在给公司做的系统做登录方面,需要用到session. 在网上找了不少资料,大致提了2点session保存方式: 1.javaWeb工程通用的HttpSession 2 ...
- oracle高效分页查询总结
本文参考链接:http://blog.sina.com.cn/s/blog_8604ca230100vro9.html 探索查询语句: --分页参数:size = 20 page = 2 --没有or ...
- 通过Servlet实现汉字验证码
package com; import java.awt.Color;import java.awt.Font;import java.awt.Graphics;import java.awt.Gra ...
- Struts2之Action接收请求参数和拦截器
技术分析之在Struts2框架中使用Servlet的API 1. 在Action类中也可以获取到Servlet一些常用的API * 需求:提供JSP的表单页面的数据,在Ac ...
- java之反射
初学反射,也是第二次写博客了把,就简单记录一下. Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对 ...
- 又是一个MVP+RxJava+Retrofit的干货集中营
欢迎访问我的个人博客 ,未经允许不得转发 前言 今天想要与大家一起分享的是近一个星期内开发的一个新app--干货集中营客户端,其实网上已经有许多类似的项目,代码家也在他的干货集中营中推荐了几款优秀的作 ...
- OpenCV探索之路(六):边缘检测(canny、sobel、laplacian)
边缘检测的一般步骤: 滤波--消除噪声 增强--使边界轮廓更加明显 检测--选出边缘点 Canny算法 Canny边缘检测算法被很多人推崇为当今最优秀的边缘检测算法,所以我们第一个就介绍他. open ...
- java关键字transient与volatile小结
本文转自:http://heaven-arch.iteye.com/blog/1160693 transient和volatile两个关键字一个用于对象序列化,一个用于线程同步,都是Java中比较高阶 ...