一、浏览器实现html5录音

二、业务代码

<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title></title>
</head>
<body><div><audio controls 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="提交" /><input onclick="cancelAudio()" type="button" value="取消" /></div><script type="text/javascript" src="record.js"></script><script>var recorder;var audio = document.querySelector('audio');function startRecording() {HZRecorder.get(function (rec) {recorder = rec;recorder.start();});}function stopRecording() {recorder.stop();}function playRecording() {recorder.play(audio);}function cancelAudio(){recorder.stop();recorder.clear();}function uploadAudio() {recorder.upload("/upload", function (state, e) {switch (state) {case 'uploading'://var percentComplete = Math.round(e.loaded * 100 / e.total) + '%';break;case 'ok'://alert(e.target.responseText);alert("上传成功");break;case 'error':alert("上传失败");break;case 'cancel':alert("上传被取消");break;}});}</script></body>
</html>

三、record.js


//兼容
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 audioContext = window.AudioContext || window.webkitAudioContext;var context = new audioContext();var audioInput = context.createMediaStreamSource(stream);// 第二个和第三个参数指的是输入和输出都是单声道,2是双声道。var recorder = context.createScriptProcessor(4096, 1, 1);var audioData = {size: 0          //录音文件长度, buffer: []     //录音缓存, inputSampleRate: context.sampleRate    //输入采样率, inputSampleBits: 16       //输入采样数位 8, 16, outputSampleRate: config.sampleRate    //输出采样率, outputSampleBits: 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.outputSampleBits);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;// 下个地址开始到文件尾总字节数,即文件大小-8data.setUint32(offset, 36 + dataLength, true); offset += 4;// WAV文件标志writeString('WAVE'); offset += 4;// 波形格式标志writeString('fmt '); offset += 4;// 过滤字节,一般为 0x10 = 16data.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;// 波形数据传输率 (每秒平均字节数) 单声道×每秒数据位数×每样本数据位/8data.setUint32(offset, channelCount * sampleRate * (sampleBits / 8), true); offset += 4;// 快数据调整数 采样一次占用字节数 单声道×每样本的数据位数/8data.setUint16(offset, channelCount * (sampleBits / 8), true); offset += 2;// 每样本数据位数data.setUint16(offset, sampleBits, true); offset += 2;// 数据标识符writeString('data'); offset += 4;// 采样数据总数,即数据总大小-44data.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/mp3' });}};//开始录音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.clear = function(){audioData.buffer=[];audioData.size=0;}//上传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;}}
};

三、欢迎交流指正,关注我,一起学习。

参考链接:

javascript - 浏览器HTML5录音功能_个人文章 - SegmentFault 思否(本文为本人18年3月4日原创)

功能:html5录音相关推荐

  1. android h5语音,html5录音支持pc和Android、ios部分浏览器,微信也是支持的,JavaScript getUserMedia...

    花了两天时间在前人基础上重复造了一个网页录音的轮子,顺带把github仓库使用研究了一下,扔到了github上,地址:https://github.com/xiangyuecn/Recorder co ...

  2. html5录音支持pc和Android、ios部分浏览器,微信也是支持的,JavaScript getUserMedia

    以前在前人基础上重复造了一个网页录音的轮子,顺带把github仓库使用研究了一下,扔到了github上. 优势在于结构简单,可插拔式的录音格式支持,几乎可以支持任意格式(前提有相应的编码器):默认提供 ...

  3. html5录音+百度语音实现语音识别

    首先,语音识别技术已经不是什么新鲜的词汇了,各大公司也提供了自己的语音识别API,据说百度.讯飞等公司的识别率已经达到99%. 最近我也想给网站加上一个语音识别功能,用于搜索词汇.我首选的是讯飞,毕竟 ...

  4. 微信浏览器 html5 语音,html5录音支持pc和Android、ios部分浏览器,微信也是支持的,JavaScript getUserMedia...

    花了两天时间在前人基础上重复造了一个网页录音的轮子,顺带把github仓库使用研究了一下,扔到了github上,地址:https://github.com/xiangyuecn/Recorder 演示 ...

  5. h5调用android录音,html5录音支持pc和Android、ios部分浏览器,微信也是支持的,JavaScript getUserMedia...

    花了两天时间在前人基础上重复造了一个网页录音的轮子,顺带把github仓库使用研究了一下,扔到了github上,地址:https://github.com/xiangyuecn/Recorder 演示 ...

  6. Safari支不支持HTML5录音? 现在浏览器中最好的解决方案是WebRTC下的 navigator.getUserMedia API。...

    先放结论:Safari支不支持HTML5录音? --据我调查,不支持. 现在浏览器中最好的解决方案是WebRTC下的 navigator.getUserMedia API. 可是当使用Can I us ...

  7. html5录音怎么保存到本地,详解HTML5 录音遇到的坑

    本文恩主要介绍了详解HTML5 录音的踩坑之旅,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧,希望能帮助到大家. 说实话,一开始都没接触过 HTML5 的 Audio A ...

  8. html5 矩阵转换,功能HTML5矩阵变换

    我正在试图让如何绘制在HTML5对象时,但在信息的多个不同来源找到了不同的解释已经引起了一些混乱做矩阵变换的理解.我发现信息说,为了在html5中创建绘制对象的动画,如here所示,同时我也看到可以通 ...

  9. vue 微信录音倒计时_vue的微信语音功能,录音+对接口返回amr音频播放-Go语言中文社区...

    vue的微信语音功能,录音+对接口返回amr音频播放 最近的新项目需要调用微信的录音功能,但是后台又不给音频转码,无奈之下就踏上了研究前端音频编码器这东西. 参考的GitHub仓库--Recorder ...

最新文章

  1. 在html文档中应如何书写注释文字,html 注释_HTML基础笔记
  2. 2018-11-25
  3. java菜单栏的功能怎么被关闭_【求助帖】 菜单栏的监听问题
  4. modelandview为null的原因_如何在Java代码中去掉烦人的“!=null”
  5. python123第五周作业答案_马哥2016全新Linux+Python高端运维班第五周作业
  6. java 常量 内存分配_Java内存分配之堆、栈和常量池
  7. 网络——提交表单数据(post方式)
  8. [html] 说说你对影子(Shadow)DOM的了解
  9. 学习EXT.JS5时的重点载图
  10. 【mindspore】数据加载报错,提示The pointer[cnode] is null.
  11. breakall lisp文件_CAD图导入SU中一次成面的方法
  12. Dorado7使用常见问题,不定时持续更新。
  13. fedora 11 配置 thinkpad trackpoint 中键
  14. 笔记本如何解除锁定计算机,笔记本键盘锁住了怎么解锁 有三种方法可以解决...
  15. 基于VHDL的毛刺信号消除
  16. mma8653驱动编程
  17. 机器学习期末简答总结
  18. IT审计?CISA?
  19. 安卓用户初次体验微信公众号信息流改版
  20. jre_linux_64,jre linux 64下载_jdk7u79_linux_x64 免费版 1.0_零度软件园

热门文章

  1. 五种在家观看3D电影的解决方案
  2. 一条线直销,一条线循环简析
  3. Untitled-1
  4. 债务人确无还款能力,可依法申请退出失信黑名单
  5. 用动态属性和DataView实现DataGrid的双向排序
  6. get_user_pages和get_user_pages_fast的区别
  7. (22)LED灯(外部)
  8. 2022运动耳机排行榜、其中最优秀的五款运动耳机
  9. linux x11vnc,X11vnc (简体中文)
  10. 罗忠生炮轰全面屏 只因入职夏普手机底气足?