资讯专栏INFORMATION COLUMN

web音频流转发之音频源

FingerLiu / 3128人阅读

摘要:前言音频流转发之音视频直播音频流转发之能直播为什么不可以看完本系列文章,你就能做一个直播,真正的直播,包括音频流的转发,这也是我最近查看发现有相关能实现音频流的转发,所有打算分享系列文章供大家交流,如有不对之处请指正。

前言

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.在音频上下文里创建源 — 例如

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。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/88692.html

相关文章

  • web音频转发AudioNode

    摘要:概述是一个处理音频的通用模块比如一个音频源一个元素一个音频地址或者一个中间处理模块一个过滤器如或一个音量控制器如一个既有输入也有输出。下面一章就开始介绍音频流的转发了。 前言 上一章地址: web音频流转发之音频源下一张地址:web音频流转发之音视频直播在这一章我说几个我们需要用到的音频处理模块也就3个吧,包括我们转发流是需要用到的核心模块。更多模块请看MDN,或者看HTML5音频AP...

    twohappy 评论0 收藏0
  • web音频转发音视频直播

    摘要:前言经过前面两篇文章的讲解,大家已经了解了的基本使用方法,下面我们就根据我们了解的做一个直播。因为没有做回音消除,和破音处理,这样听上去会很爽。 前言 经过前面两篇文章的讲解,大家已经了解了audio的基本使用方法,下面我们就根据我们了解的api做一个直播。web音频流转发之AudioNode web音频流转发之音频源 原理 视频直播:采集一帧一帧的视频,转换为base64转发,接收...

    邹强 评论0 收藏0

发表评论

0条评论

FingerLiu

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<