前言
web音频流转发之音视频直播
web音频流转发之AudioNode
app能直播,web为什么不可以?看完本系列文章,你就能做一个直播,真正的直播,包括音频流的转发,这也是我最近查看web audio api发现有相关api能实现音频流的转发,所有打算分享系列文章供大家交流,如有不对之处请指正。看完本系列文章能完成一个web直播,当然包括视频流。当然webrtc也能实现web直播,但是实现原理有所差别。文章也很简单就是对web audio api的灵活使用。
兼容性
兼容性是有必要看下,顺便看一下ie,和安卓Android Browse的兼容性,然而我想说我的荣耀8 安卓6.0 还是嵌套的chrome 37你们信吗?到底是作为一个渐渐增强的功能,还是作为一个装逼技能就看大家的使用啦!
概述
一个简单而典型的web audio流程如下:
1.创建音频上下文
2.在音频上下文里创建源 — 例如 <audio>, 振荡器, 流
3.创建效果节点,例如混响、双二阶滤波器、平移、压缩
4.为音频选择一个目地,例如你的系统扬声器
5.连接源到效果器,对目的地进行效果输出
这段话引用自MDN,这一章我主要讲解inputs中的3个api。
createMediaElementSource
下面是一个简单到极点的例子,完成了从audio获取音频源,然后输出到你的扬声器设备。
这个方法我们在直播中做用不到。
//创建音频上下文
let audioCtx = new (window.AudioContext || window.webkitAudioContext)(),
//获取audio节点
myAudio = document.querySelector('audio'),
//创建音频源
source = audioCtx.createMediaElementSource(myAudio),
//将音频源直接连接到输出设备
source.connect(audioCtx.destination);
createMediaStreamSource
这个方法介绍的是用navigator.mediaDevices.getUserMedia(navigator.getUserMedia已经废弃)获取到的音频流作为音频流。在直播时我们会采用此方法作为,音频流的采集方法;当然在这里我们也会获取到我们需要的视频流数据
//简单兼容
let getUserMedia = navigator.mediaDevices.getUserMedia || navigator.getUserMedia;
//获取麦克风,摄像头权限
getUserMedia({audio: true, video: true}).then(stream => {
let audioCtx = new AudioContext(),
//以流媒体作为音频源
source = audioCtx.createMediaStreamSource(stream);
//将音频源直接连接到输出设备
source.connect(audioCtx.destination);
});
createBufferSource
这个方法相对前面两个稍微复杂一点点。createBufferSource是由存储器中的音频数据组成的音频源,它通过AudioBuffer来进行存储,解释一下:它是通过一个固定的音频数据的二进制作为音频源,比如一首歌的二进制数据。
let audioCtx = new (window.AudioContext || window.webkitAudioContext)(),
source = audioCtx.createBufferSource();
//myArrayBuffer是一个AudioBuffer
source.buffer = myArrayBuffer;
source.loop = true; //循环播放
source.connect(audioCtx.destination);
source.start(); //开始播放音频源
下面讲讲myArrayBuffer的几种来源方式
//1.通过input=file 获取的音频文件
let fileInput = document.querySelector('input'),
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
fileInput.onchange = function(ev){
let file = ev.target.files[0],
fr = new FileReader();
fr.readAsArrayBuffer(file);
fr.onload = function(data){
//result是一个arraybuffer类型二进制数据
let result = data.target.result;
//解析数据
analyticBuffer(result);
};
};
//2.通过XHR获取音频数据(注意需要返回arraybuffer类型)
let request = new XMLHttpRequest();
request.open('GET', 'xxx.mp3', true);
//指定文件返回数据类型
request.responseType = 'arraybuffer';
//请求成功时执行
request.onload = function() {
//这是一个arraybuffer
var buffer = request.response;
//解析数据
analyticBuffer(buffer )
}
request.send();
//解析二进制数据
function analyticBuffer(buffer){
//将ArrayBuffer异步转换为一个AudioBuffer类型
audioCtx.decodeAudioData(buffer, (myArrayBuffer) => {
let source = audioCtx.createBufferSource();
source.buffer = myArrayBuffer;
source.connect(audioCtx.destination);
source.start();
});
}
//3.自己创造一个AudioBuffer
//采样率sample/s
let sampleRate = audioCtx.sampleRate,
//帧数,音频时间 = frameCount / sampleRate
frameCount = audioCtx.sampleRate * 2.0,
//创建一个两通道的音频数据,这是一个没有声音的音频数据
myArrayBuffer = audioCtx.createBuffer(2, frameCount , sampleRate);
//随机填充白噪音
//两个通道循环2次
for (var channel = 0; channel < 2; channel++) {
//获取每个通道的array数据
var nowBuffering = myArrayBuffer.getChannelData(channel);
for (let i = 0; i < frameCount; i++) {
//对每一帧填充数据
nowBuffering[i] = Math.random() * 2 - 1;
}
}
AudioBuffer的属性和方法
AudioBuffer的方法在我们直播的时候需要用到,在后面的AudioNode(音频处理模块)中也会出现AudioBuffer数据,我们需要它是获取和传输数据
let myArrayBuffer = audioCtx.createBuffer(2, 4096, sampleRate);
myArrayBuffer.sampleRate //采样数
myArrayBuffer.length //采样帧率 也就是4096
myArrayBuffer.duration //时长
myArrayBuffer.numberOfChannels //通道数
//返回x通道的Float32Array类型的数据,x表示是哪个通道0或1
myArrayBuffer.getChannelData(x)
//将myArrayBuffer第x通道的数据复制到anotherArray中,y表示数据复制开始的偏移量
let anotherArray = new Float32Array;
myArrayBuffer.copyFromChannel(anotherArray,x,y);
//将anotherArray数据复制到myArrayBuffer的X通道中,y偏移量
let anotherArray = new Float32Array;
myArrayBuffer.copyToChannel(anotherArray,x,y);
//关于copyToChannel,copyFromChannel,getChannelData在下一章看见例子就明白了
结束语
这一章大概就说到这么多吧,都是一些简单的api使用,下一章结合以后例子讲解部分AudioNode。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。