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