因公司业务须要在网页录音功能,由于h5的api兼容限制不得想出一些解决方案,如下是总结。
https://shudong.wang/10585.htmljavascript
https://wsdo.github.io/recording/html
https://github.com/wsdo/recordingjava
后续继续完善,有这个需求的朋友能够继续讨论
百度语音识别ios
感受百度够强大,确定有完美的解决方案,最终发如今移动端网页打开百度语音直接跳转让下载app(说明不支持)
谷歌语音识别git
在不支持的机型上面不显示语音识别按钮
h5录音主要使用AudioContext 和 getUserMedia 兼容性仍是不好的,尤为是在移动端。AudioContextgithub
getUserMedia
可使用的:(最新版本,经常使用)web
pc safari 支持 ios Safari 支持 安卓 小米5 微信里面可使用 小米5 Chrome 最新版可使用 小米5 uc可使用
不可使用的
ios Chrome 到这出了问题 webkitAudioContext.createScriptProcessor
ios 微信里面不支持
小米5 自带浏览器不能够
华为自带浏览器不能够api
考虑到手机端微信里面使用场景比较多
先了解一下简介和历史吧
长久以来,音频/视频捕获都是网络开发中的“圣杯”。
多年来,咱们老是依赖于浏览器插件(Flash 或 Silverlight)实现这一点。快来看看吧!promise
如今轮到 HTML5 大显身手了。也许看起来不是很显眼,可是 HTML5 的崛起引起了对设备硬件访问的激增。
地理位置 (GPS)、Orientation API(加速计)、WebGL (GPU) 和 Web Audio API(视频硬件)都是很好的例子。
这些功能很是强大,展现了基于系统底层硬件功能之上的高级 JavaScript API。浏览器
本教程介绍了一种新 API:navigator.getUserMedia(),可以让网络应用访问用户的相机和麦克风。
若是您还不知道,getUserMedia() 的历史可谓一段有趣的故事。
过去几年中出现过好几种“Media Capture API”的变体。不少人意识到,须要可以在网络上访问本地设备,但这要全部人协力开发出一种新的规范。局面一片混乱,以致于 W3C 最终决定成立一个工做组。他们只有一个目的:理清混乱的局面!设备 API 政策 (DAP) 工做组负责对过剩的提议进行统一和标准化。
我会试着总结一下 2011 所发生的事情...
HTML 媒体捕获是 DAP 在网络媒体捕获标准化上迈出的第一步。具体方法是超载 <input type="file"> 并为 accept 参数添加新值。
若是您要让用户经过网络摄像头拍摄本身的快照,就可使用 capture=camera:
<input type="file" accept="image/*;capture=camera">
录制视频或音频也是相似的:
<input type="file" accept="video/*;capture=camcorder"> <input type="file" accept="audio/*;capture=microphone">
不少人认为 HTML 媒体捕获的局限性太大,所以一种新的规范应运而生,能够支持任何类型的(将来)设备。不出意料地,该设计须要新的 <device> 元素,也就是 getUserMedia() 的前身。
Opera 是第一批根据 <device> 元素建立视频捕获的初始实施的浏览器之一。不久以后(准确地说是同一天),WhatWG 决定废止 <device> 标记,以支持称为 navigator.getUserMedia() 的新兴 JavaScript API。一周后,Opera 推出的新版本中加入了对更新的 getUserMedia() 规范的支持。当年年末,Microsoft 也加入这一行列,发布了 IE9 实验室以支持新规范。
<device type="media" onchange="update(this.data)"></device> <video autoplay></video> <script> function update(stream) { document.querySelector('video').src = stream.url; } </script>
很遗憾,已发布的浏览器中没有任何一款曾经包含 <device>。我猜这是一个不太须要担忧的 API。可是 <device> 确实有两大优势:一是语义方面,二是能够轻松进行扩展,而不只仅是支持音频/视频设备。
如今深吸一口气。这玩意儿速度飞快!
<device> 元素最终仍是像渡渡鸟同样销声匿迹了。
依靠 WebRTC(网络即时通讯)的大力协助,最近几个月寻找合适捕获 API 的步伐加快了不少。该规范由 W3C WebRTC 工做组负责监管。Google、Opera、Mozilla 和其余一些公司目前正致力于在本身的浏览器中实施该 API。
getUserMedia() 与 WebRTC 相关,由于它是通向这组 API 的门户。它提供了访问用户本地相机/麦克风媒体流的手段。
支持:
在 Chrome 浏览器 18.0.1008 和更高版本中,可在 about:flags 下启用 WebRTC。
主要使用 AudioContext 和 getUserMedia 这个api 来操做
AudioContext接口表示由音频模块链接而成的音频处理图,每一个模块对应一个AudioNode。AudioContext能够控制它所包含的节点的建立,以及音频处理、解码操做的执行。作任何事情以前都要先建立AudioContext对象,由于一切都发生在这个环境之中。
能够来这里了解
https://developer.mozilla.org...
MediaDevices.getUserMedia() 会提示用户给予使用媒体输入的许可,媒体输入会产生一个MediaStream,里面包含了请求的媒体类型的轨道。此流能够包含一个视频轨道(来自硬件或者虚拟视频源,好比相机、视频采集设备和屏幕共享服务等等)、一个音频轨道(一样来自硬件或虚拟音频源,好比麦克风、A/D转换器等等),也多是其它轨道类型。它返回一个 Promise 对象,成功后会resolve回调一个 MediaStream 对象。若用户拒绝了使用权限,或者须要的媒体源不可用,promise会reject回调一个 PermissionDeniedError 或者 NotFoundError 。
能够来这里了解
https://developer.mozilla.org...
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
这是一个使用 navigator.mediaDevices.getUserMedia()的例子,带一个polyfill以适应旧的浏览器。 要注意的是这个polyfill并不能修正一些约束语法上的遗留差别,这表示约束在某些浏览器上可能不会很好地运行。推荐使用处理了约束的 adapter.js polyfill 来替代。
https://github.com/webrtc/ada...
/ 老的浏览器可能根本没有实现 mediaDevices,因此咱们能够先设置一个空的对象 if (navigator.mediaDevices === undefined) { navigator.mediaDevices = {}; } // 一些浏览器部分支持 mediaDevices。咱们不能直接给对象设置 getUserMedia // 由于这样可能会覆盖已有的属性。这里咱们只会在没有getUserMedia属性的时候添加它。 if (navigator.mediaDevices.getUserMedia === undefined) { navigator.mediaDevices.getUserMedia = function(constraints) { // 首先,若是有getUserMedia的话,就得到它 var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia; // 一些浏览器根本没实现它 - 那么就返回一个error到promise的reject来保持一个统一的接口 if (!getUserMedia) { return Promise.reject(new Error('getUserMedia is not implemented in this browser')); } // 不然,为老的navigator.getUserMedia方法包裹一个Promise return new Promise(function(resolve, reject) { getUserMedia.call(navigator, constraints, resolve, reject); }); } } navigator.mediaDevices.getUserMedia({ audio: true, video: true }) .then(function(stream) { var video = document.querySelector('video'); // 旧的浏览器可能没有srcObject if ("srcObject" in video) { video.srcObject = stream; } else { // 防止再新的浏览器里使用它,应为它已经再也不支持了 video.src = window.URL.createObjectURL(stream); } video.onloadedmetadata = function(e) { video.play(); }; }) .catch(function(err) { console.log(err.name + ": " + err.message); });
function audioContextCheck() { if (typeof window.AudioContext !== "undefined") { console.log('AudioContext'); return new window.AudioContext(); } else if (typeof webkitAudioContext !== "undefined") { console.log('webkitAudioContext'); return new window.webkitAudioContext(); } else if (typeof window.mozAudioContext !== "undefined") { console.log('mozAudioContext'); return new window.mozAudioContext(); } else { console.log('NONE OF THEM!'); } }
or
var context; window.addEventListener('load', init, false); function init() { try { // Fix up for prefixing window.AudioContext = window.AudioContext || window.webkitAudioContext; context = new AudioContext(); } catch (e) { alert('Web Audio API is not supported in this browser'); } }
function hasGetUserMedia() { // Note: Opera builds are unprefixed. return !!(navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia); } if (hasGetUserMedia()) { // Good to go! } else { alert('getUserMedia() is not supported in your browser'); }
var AudioContext = window.AudioContext || window.webkitAudioContext;
Storage.ctx = new AudioContext(); if (Storage.ctx.createJavaScriptNode) { jsAudioNode = Storage.ctx.createJavaScriptNode(bufferSize, numberOfAudioChannels, numberOfAudioChannels); } else if (Storage.ctx.createScriptProcessor) { jsAudioNode = Storage.ctx.createScriptProcessor(bufferSize, numberOfAudioChannels, numberOfAudioChannels); } else { alert('WebAudio API has no support on this browser.') throw 'WebAudio API has no support on this browser.'; } jsAudioNode.connect(Storage.ctx.destination);
navigator.mediaDevices.getUserMedia({ audio: true }) // 只处理音频 .then(onMicrophoneCaptured) .catch(onMicrophoneCaptureError);
safari 不支持Buffer 的方式 改成下面这种
URL.createObjectURL(new Blob([_function.toString(), ';this.onmessage = function (e) {' + _function.name + '(e.data);}' ], { type: 'application/javascript' }));
function processInWebWorker(_function) { var workerURL = URL.createObjectURL(new Blob([_function.toString(), ';this.onmessage = function (e) {' + _function.name + '(e.data);}' ], { type: 'application/javascript' })); var worker = new Worker(workerURL); worker.workerURL = workerURL; return worker; }