使用Recorder实现录音播放上传。亲测可用,兼容大部分浏览器。

html页面

<!DOCTYPE html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>火星黑洞</title></head><body><div><audio 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="提交" /><br /><div id="recordingslist"></div></div><script type="text/javascript" src="js/Recorder.js"></script><script>var recorder;var audio = document.querySelector('audio');function startRecording() {HZRecorder.get(function(rec) {recorder = rec;recorder.start();}, {sampleBits: 16,sampleRate: 16000});}function stopRecording() {recorder.stop();var blob = recorder.getBlob();var url = URL.createObjectURL(blob);var div = document.createElement('div');var au = document.createElement('audio');var hf = document.createElement('a');au.controls = true;au.src = url;hf.href = url;hf.download = new Date().toISOString() + '.wav';hf.innerHTML = hf.download;div.appendChild(au);div.appendChild(hf);recordingslist.appendChild(div);}function playRecording() {recorder.play(audio);}function uploadAudio() {recorder.upload("Handler1.ashx", 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>

Recorder.js

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

html 录音、播放、上传相关推荐

  1. 录音、上传、播放音频微信小程序实践

    文章目录 录音.上传.播放音频微信小程序实践 实践分析 依赖接口 录音 上传 播放 Page 事件 参考 录音.上传.播放音频微信小程序实践 最近上线了一款智能外呼机器人产品,需要开发一款录音.上传. ...

  2. H5使用企业微信jssdk录音、上传、下载、播放

    企业微信上使用js-sdk语音发布任务 企业微信官方API:音频接口地址 step1:登录企业微信新建应用程序并记录你的Secret step2:在我的企业最下面找出你的企业ID也就是你的appId ...

  3. html5拨打电话自动录音,html5实现手机触摸出现录音以及离开停止录音并上传的功能(代码)...

    本篇文章给大家带来的内容是关于html5实现手机触摸出现录音以及离开停止录音并上传的功能(代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 以下是实现功能实例: html var ...

  4. Vue使用微信录音并上传服务端

    在微信公众号或者微信h5的网页开发中,会用到录音等功能,在微信里面使用微信录音会比较好一点,不用去设置ios和android的h5录音兼容性,并且h5的其他录音js文件可能不兼容微信浏览器等,所以vu ...

  5. vue 调用pc端本地摄像头、麦克风实现拍照、录视频、录音 并上传到服务器指定树文件夹

    vue 调用pc端本地摄像头.麦克风实现拍照.录视频.录音 并上传 自己写blog只是为了下次方便使用 过程确实很烦 ,自己摸索加各大网站cv查看 可以直接使用 1.调用摄像头拍照 录屏 首先是npm ...

  6. java 网页 录音_Java+FlashWavRecorder实现网页录音并上传

    [注意] [前言] 肯定有需求要网页录音,并且要上传.这奇葩需求. 然后找到了FlashWavRecorder, [原始版本号] 1.下载 在上面的地址下载zip解压之后,目录里面有个index.ht ...

  7. 可通过蓝牙,WiFi,4G实现录音数据上传的WT2605新型音频芯片在录音笔等产品的应用解析

    概述:本文主要介绍一款新型的音频芯片WT2605在录音产品中的应用与实现,主要依靠音频芯片通过ADC采集数据,将数据编码为音频流数据存储在本地,也可通过外设将数据传给蓝牙/WiFi/4G模块,实现录音 ...

  8. uniApp录音后上传音频

    uniApp录音后上传音频 通过 uni.getRecorderManager() 里的onStop回调返回的tempFilePath是录音文件的临时地址.这个文件上传后不一定可以播放,上传后在服务器 ...

  9. 小程序上传音频失败_微信小程序实现录音后上传文件方法详细

    本篇文章讲述了微信小程序实现录音后上传文件方法,大家对微信小程序实现录音后上传文件方法不了解的话或者对微信小程序实现录音后上传文件方法感兴趣的话那么我们就一起来看看本篇文章吧, 好了废话少说进入正题吧 ...

  10. 前端调用麦克风获取实时音频流和录音并上传至后台

    前端调用麦克风获取实时音频流和录音并上传至后台 index.html <!DOCTYPE html> < a href=" ">Default.html&l ...

最新文章

  1. 第五届合肥工业大学宣城校区程序设计大赛题解
  2. CSS布局——横向两列布局
  3. Leetcode:Substring with Concatenation of All Words分析和实现
  4. 安装 Ruby 和 Rails 开发环境
  5. 设计模式-----单例模式
  6. 苹果开发着账号:个人、公司、企业账号的申请流程
  7. mysql分布式数据库中间件对比
  8. 2019ICPC(南京) - Greedy Sequence(线段树)
  9. 女朋友心血来潮帮我清洗电脑
  10. 动手动脑-Java重载
  11. 如何开发一个可运维系统的一点体会
  12. 报错The sandbox is not in sync with the Podfile.lock
  13. 二级菜单打开一个时其他关闭_blender2.8教程 顶部菜单栏
  14. Win10家庭版安装docker(WSL与WSL2两种安装方式)
  15. 应用phpexcel导出excel文件后打不开的问题解决方法
  16. 高中女销售学Linux云计算4个月搞定年薪12万
  17. mysql 基础教程 很全
  18. 改变世界面貌的十个数学公式
  19. 端口号和协议号的区别
  20. 安装企业微信和微信-ubuntu

热门文章

  1. 贴近摄影测量 | 中国最神秘的建筑!
  2. 天池龙珠计划机器学习训练营机器学习基础知识学习笔记--Task03
  3. Python Matplotlib绘制渐变色柱状图(bar)并加边框和配置渐变颜色条(colorbar)
  4. OpenCV-基于自定义色条实现灰度图上色
  5. 怎样鞋360度的Flash动画都比较有影响力的客户
  6. 第七节:类和对象【一】【java】
  7. 自动化测试练手项目推荐
  8. Linux:搭建深度学习环境配置教程
  9. Java日志记录函数调用栈方法
  10. js 字符串转数值 的常用方法和对比