摘要:前言音頻流轉(zhuǎn)發(fā)之音視頻直播音頻流轉(zhuǎn)發(fā)之能直播為什么不可以看完本系列文章,你就能做一個直播,真正的直播,包括音頻流的轉(zhuǎn)發(fā),這也是我最近查看發(fā)現(xiàn)有相關(guān)能實現(xiàn)音頻流的轉(zhuǎn)發(fā),所有打算分享系列文章供大家交流,如有不對之處請指正。
前言
web音頻流轉(zhuǎn)發(fā)之音視頻直播
web音頻流轉(zhuǎn)發(fā)之AudioNode
app能直播,web為什么不可以?看完本系列文章,你就能做一個直播,真正的直播,包括音頻流的轉(zhuǎn)發(fā),這也是我最近查看web audio api發(fā)現(xiàn)有相關(guān)api能實現(xiàn)音頻流的轉(zhuǎn)發(fā),所有打算分享系列文章供大家交流,如有不對之處請指正??赐瓯鞠盗形恼履芡瓿梢粋€web直播,當(dāng)然包括視頻流。當(dāng)然webrtc也能實現(xiàn)web直播,但是實現(xiàn)原理有所差別。文章也很簡單就是對web audio api的靈活使用。
兼容性是有必要看下,順便看一下ie,和安卓Android Browse的兼容性,然而我想說我的榮耀8 安卓6.0 還是嵌套的chrome 37你們信嗎?到底是作為一個漸漸增強的功能,還是作為一個裝逼技能就看大家的使用啦!
一個簡單而典型的web audio流程如下:
1.創(chuàng)建音頻上下文
2.在音頻上下文里創(chuàng)建源 — 例如
下面是一個簡單到極點的例子,完成了從audio獲取音頻源,然后輸出到你的揚聲器設(shè)備。
這個方法我們在直播中做用不到。
//創(chuàng)建音頻上下文 let audioCtx = new (window.AudioContext || window.webkitAudioContext)(), //獲取audio節(jié)點 myAudio = document.querySelector("audio"), //創(chuàng)建音頻源 source = audioCtx.createMediaElementSource(myAudio), //將音頻源直接連接到輸出設(shè)備 source.connect(audioCtx.destination);createMediaStreamSource
這個方法介紹的是用navigator.mediaDevices.getUserMedia(navigator.getUserMedia已經(jīng)廢棄)獲取到的音頻流作為音頻流。在直播時我們會采用此方法作為,音頻流的采集方法;當(dāng)然在這里我們也會獲取到我們需要的視頻流數(shù)據(jù)
//簡單兼容 let getUserMedia = navigator.mediaDevices.getUserMedia || navigator.getUserMedia; //獲取麥克風(fēng),攝像頭權(quán)限 getUserMedia({audio: true, video: true}).then(stream => { let audioCtx = new AudioContext(), //以流媒體作為音頻源 source = audioCtx.createMediaStreamSource(stream); //將音頻源直接連接到輸出設(shè)備 source.connect(audioCtx.destination); });createBufferSource
這個方法相對前面兩個稍微復(fù)雜一點點。createBufferSource是由存儲器中的音頻數(shù)據(jù)組成的音頻源,它通過AudioBuffer來進(jìn)行存儲,解釋一下:它是通過一個固定的音頻數(shù)據(jù)的二進(jìn)制作為音頻源,比如一首歌的二進(jìn)制數(shù)據(jù)。
let audioCtx = new (window.AudioContext || window.webkitAudioContext)(), source = audioCtx.createBufferSource(); //myArrayBuffer是一個AudioBuffer source.buffer = myArrayBuffer; source.loop = true; //循環(huán)播放 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類型二進(jìn)制數(shù)據(jù) let result = data.target.result; //解析數(shù)據(jù) analyticBuffer(result); }; }; //2.通過XHR獲取音頻數(shù)據(jù)(注意需要返回arraybuffer類型) let request = new XMLHttpRequest(); request.open("GET", "xxx.mp3", true); //指定文件返回數(shù)據(jù)類型 request.responseType = "arraybuffer"; //請求成功時執(zhí)行 request.onload = function() { //這是一個arraybuffer var buffer = request.response; //解析數(shù)據(jù) analyticBuffer(buffer ) } request.send(); //解析二進(jìn)制數(shù)據(jù) function analyticBuffer(buffer){ //將ArrayBuffer異步轉(zhuǎn)換為一個AudioBuffer類型 audioCtx.decodeAudioData(buffer, (myArrayBuffer) => { let source = audioCtx.createBufferSource(); source.buffer = myArrayBuffer; source.connect(audioCtx.destination); source.start(); }); } //3.自己創(chuàng)造一個AudioBuffer //采樣率sample/s let sampleRate = audioCtx.sampleRate, //幀數(shù),音頻時間 = frameCount / sampleRate frameCount = audioCtx.sampleRate * 2.0, //創(chuàng)建一個兩通道的音頻數(shù)據(jù),這是一個沒有聲音的音頻數(shù)據(jù) myArrayBuffer = audioCtx.createBuffer(2, frameCount , sampleRate); //隨機填充白噪音 //兩個通道循環(huán)2次 for (var channel = 0; channel < 2; channel++) { //獲取每個通道的array數(shù)據(jù) var nowBuffering = myArrayBuffer.getChannelData(channel); for (let i = 0; i < frameCount; i++) { //對每一幀填充數(shù)據(jù) nowBuffering[i] = Math.random() * 2 - 1; } }AudioBuffer的屬性和方法
AudioBuffer的方法在我們直播的時候需要用到,在后面的AudioNode(音頻處理模塊)中也會出現(xiàn)AudioBuffer數(shù)據(jù),我們需要它是獲取和傳輸數(shù)據(jù)
let myArrayBuffer = audioCtx.createBuffer(2, 4096, sampleRate); myArrayBuffer.sampleRate //采樣數(shù) myArrayBuffer.length //采樣幀率 也就是4096 myArrayBuffer.duration //時長 myArrayBuffer.numberOfChannels //通道數(shù) //返回x通道的Float32Array類型的數(shù)據(jù),x表示是哪個通道0或1 myArrayBuffer.getChannelData(x) //將myArrayBuffer第x通道的數(shù)據(jù)復(fù)制到anotherArray中,y表示數(shù)據(jù)復(fù)制開始的偏移量 let anotherArray = new Float32Array; myArrayBuffer.copyFromChannel(anotherArray,x,y); //將anotherArray數(shù)據(jù)復(fù)制到myArrayBuffer的X通道中,y偏移量 let anotherArray = new Float32Array; myArrayBuffer.copyToChannel(anotherArray,x,y); //關(guān)于copyToChannel,copyFromChannel,getChannelData在下一章看見例子就明白了結(jié)束語
這一章大概就說到這么多吧,都是一些簡單的api使用,下一章結(jié)合以后例子講解部分AudioNode。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/88692.html
摘要:概述是一個處理音頻的通用模塊比如一個音頻源一個元素一個音頻地址或者一個中間處理模塊一個過濾器如或一個音量控制器如一個既有輸入也有輸出。下面一章就開始介紹音頻流的轉(zhuǎn)發(fā)了。 前言 上一章地址: web音頻流轉(zhuǎn)發(fā)之音頻源下一張地址:web音頻流轉(zhuǎn)發(fā)之音視頻直播在這一章我說幾個我們需要用到的音頻處理模塊也就3個吧,包括我們轉(zhuǎn)發(fā)流是需要用到的核心模塊。更多模塊請看MDN,或者看HTML5音頻AP...
摘要:前言經(jīng)過前面兩篇文章的講解,大家已經(jīng)了解了的基本使用方法,下面我們就根據(jù)我們了解的做一個直播。因為沒有做回音消除,和破音處理,這樣聽上去會很爽。 前言 經(jīng)過前面兩篇文章的講解,大家已經(jīng)了解了audio的基本使用方法,下面我們就根據(jù)我們了解的api做一個直播。web音頻流轉(zhuǎn)發(fā)之AudioNode web音頻流轉(zhuǎn)發(fā)之音頻源 原理 視頻直播:采集一幀一幀的視頻,轉(zhuǎn)換為base64轉(zhuǎn)發(fā),接收...
閱讀 2120·2023-04-26 00:50
閱讀 2490·2021-10-13 09:39
閱讀 2225·2021-09-22 15:34
閱讀 1619·2021-09-04 16:41
閱讀 1348·2019-08-30 15:55
閱讀 2441·2019-08-30 15:53
閱讀 1714·2019-08-30 15:52
閱讀 754·2019-08-29 16:19