文档章节

学习HTML5音频录制

yushulx
 yushulx
发布于 2016/10/18 10:48
字数 851
阅读 220
收藏 3

之前玩过WebRTC,通过HTML5可以轻松实现语音视频聊天,网上的示例很多。最近想了解下HTML5能否录制音频,用什么接口可以做到。这里分享下学习资料。

浏览器

要获取音频和视频,需要用到getUserMedia。桌面平台支持的浏览器包括Chrome, Firefox, Opera和Edge。移动平台包括Chrome, Firefox和Opera,不过只是Android平台,iOS不行。微软似乎也放弃IE了,全力支持Edge。苹果对HTML5的支持始终不够。前段日子还有新闻报道说有开发者针对HTML5起诉苹果。

获取视频音频流

网上示例很多,从Mozilla的文档中找了一段最简单的代码:

var p = navigator.mediaDevices.getUserMedia({ audio: true, video: true });
 
p.then(function(mediaStream) {
  var video = document.querySelector('video');
  video.src = window.URL.createObjectURL(mediaStream);
  video.onloadedmetadata = function(e) {
// Do something with the video here.
    video.play();
 
  };
});
 
p.catch(function(err) { console.log(err.name); }); // always check for errors at the end.

录制Audio

在Mozilla的HTML5文档中看到了MediaRecorder。这个接口简单方便,但是比较新,浏览器的兼容性有限。

桌面

移动

不过也有替代方案,使用AudioNodes。基本步骤如下:

1. 通过getUserMedia获取视频音频流。

2. 通过createMediaStreamSource创建MediaStreamAudioSourceNode

if (navigator.getUserMedia) {
   console.log('getUserMedia supported.');
   navigator.getUserMedia (
      // constraints: audio and video for this app
      {
         audio: true,
         video: true
      },
 
      // Success callback
      function(stream) {
         video.src = (window.URL && window.URL.createObjectURL(stream)) || stream;
         video.onloadedmetadata = function(e) {
            video.play();
            video.muted = 'true';
         };
 
         // Create a MediaStreamAudioSourceNode
         // Feed the HTMLMediaElement into it
         var source = audioCtx.createMediaStreamSource(stream);
 
      },
 
      // Error callback
      function(err) {
         console.log('The following gUM error occured: ' + err);
      }
   );
} else {
   console.log('getUserMedia not supported on your browser!');
}

3. 链接AudioNodes。创建ScriptProcessorNode。通过onaudioprocess来获取音频数据。

var scriptNode = audioCtx.createScriptProcessor(4096, 1, 1);
 
scriptNode.onaudioprocess = function(audioProcessingEvent) {
  // The input buffer is the song we loaded earlier
  var inputBuffer = audioProcessingEvent.inputBuffer;
 
  // Loop through the output channels (in this case there is only one)
  for (var channel = 0; channel < outputBuffer.numberOfChannels; channel++) {
    var inputData = inputBuffer.getChannelData(channel);
  }
}
 
source.connect(scriptNode);
scriptNode.connect(audioCtx.destination);

4. 通过XHR或者WebSockets来发送blob数据。

JavaScript库

流程就这么简单,但是写起来还是比较复杂的。所以需要参考下别人写的代码。在GitHub上可以找到RecordRTCRecorderjs。前者可以录制视频和音频,如果只想录制音频,可以选择后面这个,比较简单。

关于RecordRTC,有一个站点可以体验视频音频录制:online demo

现在分析下Recorderjs的源码。

onaudioprocess中获取音频buffer:

this.context = source.context;
        this.node = (this.context.createScriptProcessor || this.context.createJavaScriptNode).call(this.context, this.config.bufferLen, this.config.numChannels, this.config.numChannels);
 
        this.node.onaudioprocess = function (e) {
            if (!_this.recording) return;
 
            var buffer = [];
            for (var channel = 0; channel < _this.config.numChannels; channel++) {
                buffer.push(e.inputBuffer.getChannelData(channel));
            }
            _this.worker.postMessage({
                command: 'record',
                buffer: buffer
            });
        };
 
        source.connect(this.node);
        this.node.connect(this.context.destination); //this should not be necessary

用数组存储音频buffer:

function record(inputBuffer) {
                for (var channel = 0; channel < numChannels; channel++) {
                    recBuffers[channel].push(inputBuffer[channel]);
                }
                recLength += inputBuffer[0].length;
            }

WAV格式编码:

function encodeWAV(samples) {
                var buffer = new ArrayBuffer(44 + samples.length * 2);
                var view = new DataView(buffer);
 
                /* RIFF identifier */
                writeString(view, 0, 'RIFF');
                /* RIFF chunk length */
                view.setUint32(4, 36 + samples.length * 2, true);
                /* RIFF type */
                writeString(view, 8, 'WAVE');
                /* format chunk identifier */
                writeString(view, 12, 'fmt ');
                /* format chunk length */
                view.setUint32(16, 16, true);
                /* sample format (raw) */
                view.setUint16(20, 1, true);
                /* channel count */
                view.setUint16(22, numChannels, true);
                /* sample rate */
                view.setUint32(24, sampleRate, true);
                /* byte rate (sample rate * block align) */
                view.setUint32(28, sampleRate * 4, true);
                /* block align (channel count * bytes per sample) */
                view.setUint16(32, numChannels * 2, true);
                /* bits per sample */
                view.setUint16(34, 16, true);
                /* data chunk identifier */
                writeString(view, 36, 'data');
                /* data chunk length */
                view.setUint32(40, samples.length * 2, true);
 
                floatTo16BitPCM(view, 44, samples);
 
                return view;
            }

合并所有的buffer,并用WAV格式导出,最后转换成blob:

function exportWAV(type) {
                var buffers = [];
                for (var channel = 0; channel < numChannels; channel++) {
                    buffers.push(mergeBuffers(recBuffers[channel], recLength));
                }
                var interleaved = undefined;
                if (numChannels === 2) {
                    interleaved = interleave(buffers[0], buffers[1]);
                } else {
                    interleaved = buffers[0];
                }
                var dataview = encodeWAV(interleaved);
                var audioBlob = new Blob([dataview], { type: type });
            }

这样就可以保存或者发送录制的音频文件了。

参考资料

© 著作权归作者所有

yushulx
粉丝 29
博文 107
码字总数 60955
作品 0
杭州
私信 提问
学习 HTML5 最好的几个网站

HTML5 现在很火热,下面是十来个学习HTML5最好的网站,可惜是英文的,红薯说看不懂的要硬着头皮看。 HTML5 Labs HTML5 – Wikipedia Apple – HTML5 Youtube HTML5 Beta Dive into HTML5 by ...

小编辑
2011/04/14
7.8K
13
分享7个漂亮的HTML5视频音频播放器及源码

网页视频音频播放器大家并不陌生,在IE中我们可以运行ActiveX来嵌入微软的Media Player或者其他的本地播放器,当然可能大部分我们都是使用Flash来制作播放器。在HTML5发展迅速的今天,让我们...

tp_wire
2012/07/11
34K
5
【原创】攻陷移动学习平台,HTML5,你赢了!

作为新一代的Web标准,HTML5自问世以来就受到方方面面的强烈关注,过去的2015年,HTML5的确得到蓬勃的发展,尤其在微信朋友圈的营销上,可以说微信通过公众号的形式,以游戏、营销唤醒了HTM...

移动学习前沿
2016/06/23
0
0
HTML5拍照、摄像机功能实战

苏格团队 作者:Tomey 开篇 最近在做一个chrome app的云相机应用,应用包括拍照、摄像、保存照片视频、上传文件等等核心功能,其中涉及到很多HTML5对媒体流相关的API。写这篇文章的目的,其一...

苏格团队
01/24
0
0
CreateJs系列教程-1-开始出发

介绍: CreateJS为CreateJS库,可以说是一款为HTML5游戏开发的引擎。打造 HTML5 游戏! CreateJS 是一套可以构建丰富交互体验的 HTML5 游戏的开源工具包,旨在降低 HTML5 项目的开发难度和成...

乐派电影
2015/11/11
2.5K
0

没有更多内容

加载失败,请刷新页面

加载更多

当餐饮遇上大数据,嗯真香!

之前去开了一场会,主题是「餐饮领袖新零售峰会」。认真听完了餐饮前辈和新秀们的分享,觉得获益匪浅,把脑子里的核心纪要整理了一下,今天和大家做一个简单的分享,欢迎感兴趣的小伙伴一起交...

数澜科技
32分钟前
1
0
DNS-over-HTTPS 的下一代是 DNS ON BLOCKCHAIN

本文作者:PETER LAI ,是 Diode 的区块链工程师。在进入软件开发领域之前,他主要是在做工商管理相关工作。Peter Lai 也是一位活跃的开源贡献者。目前,他正在与 Diode 团队一起开发基于区块...

红薯
39分钟前
3
0
CC攻击带来的危害我们该如何防御?

随着网络的发展带给我们很多的便利,但是同时也带给我们一些网站安全问题,网络攻击就是常见的网站安全问题。其中作为站长最常见的就是CC攻击,CC攻击是网络攻击方式的一种,是一种比较常见的...

云漫网络Ruan
今天
8
0
实验分析性专业硕士提纲撰写要点

为什么您需要研究论文的提纲? 首先当您进行研究时,您需要聚集许多信息和想法,研究论文提纲可以较好地组织你的想法, 了解您研究资料的流畅度和程度。确保你写作时不会错过任何重要资料以此...

论文辅导员
今天
7
0
作为一个(IT)程序员!聊天没有话题?试试这十二种技巧

首先呢?我是一名程序员,经常性和同事没话题。 因为每天都会有自己的任务要做,程序员对于其他行业来说;是相对来说比较忙的。你会经常看到程序员在发呆、调试密密麻麻代码、红色报错发呆;...

小英子wep
今天
33
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部