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,也是如此.不同的浏览器提供了不同的 ...
随机推荐
- 是什么让spring 5放弃了使用Guava Cache?
一路走来,Spring社区从刚开始的核心模块一直发展到现在,最近Sping5也完成了M5的发布, 相信不久之后第一个RELEASE版本也会发布.里面有很多特性是和即将要发布的JAVA 9息息相关的.今 ...
- single number i && ii && iii
Problem statement Elementary knowledge: There is a popular question when I seeked my job at Beijing: ...
- 关于WordPress搬家方法步骤的整理
最近准备更换自己的博客服务器,所以需要将原来服务器上的所有东西都搬到新的服务器.为了数据的安全,在网上找了很多的资料.现在整理一下整个搬家过程的操作步骤.下面进入正题: 1.测试环境这次我使用的示例服 ...
- javascript函数作用域及this指向详解
一.先说一个简单的概念--变量提升: 通过function+函数名的方式,声明的函数,可以在代码中的任何位置调用: 通过var定义变量的方式,声明的函数,则必须在声明之后进行调用,原因就是在变量定义之 ...
- JDK的下载与配置
一.下载JDK 1.进入oracle官网 下载完成后直接运行就能生成jdk文件. 二.配置环境 1.打开环境配置 右击计算机选择属性 选择高级系统数据 点击环境变量 2.配置JAVA_HOME 新建一 ...
- ios模拟器bug
Error: xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Libra ...
- Java线程安全 关于原子性与volatile的试验
1. 变量递增试验 static /*volatile*/ int shared=0;//volatile也无法保证++操作的原子性 static synchronized int incrShare ...
- CountDownLatch——闭锁的实现之一
CountDownLatch实际上是一种闭锁实现.闭锁:是一种同步工具类,可以延迟线程的进度知道其到达终止状态--<Java并发编程实战>.这个怎么解释呢?简单来说,就是有1个线程需要等待 ...
- ArrayList源码解析(一)
源码解析系列主要对Java的源码进行详细的说明,由于水平有限,难免出现错误或描述不准确的地方,还请大家指出. 1.位置 ArrayList位于java.util包中. package java.uti ...
- (高级篇 Netty多协议开发和应用)第十章-Http协议开发应用(基于Netty的HttpServer和HttpClient的简单实现)
1.HttpServer package nettyHttpTest; import io.netty.bootstrap.ServerBootstrap; import io.netty.chann ...