iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 8
1
Software Development

30天之即時網路影音開發攻略(小白本)系列 第 8

30-08之 WebRTC 採集的詳細說明與聲音的加工

黑色好看版 - 傳送門


https://ithelp.ithome.com.tw/upload/images/20181023/20089358qhkO9UHBxW.png

正文開始

前一篇文章『30-07 Web 如何進行語音與影像採集 ?』咱們已經學習到如何使用 WebRTC 來進行聲音與影像的採集,並且將採集的結果儲放成一個 stream,最後在將儲放成檔案,接下來我們將研究一下 stream 裡面的東西,以及來簡單的將所採集到的聲音進行加工。

採集的詳細說明與聲音的加工。

本篇文章會將之分成以下幾個章節:

  • WebRTC 的 Stream (Media Stream) 組成。
  • 如何對 Media Stream 的聲音進行加工 ?

WebRTC 的 Stream ( Media Stream ) 組成


stream = track A + track B

前一篇文章中,咱們有提到可以用以下的程式碼,將聲音與影像給採集下來。

const constraints = { audio: true, video: true }
navigator.mediaDevices.getUserMedia(constraints)
.then((stream) => {
    // stream 就是咱們的聲音與影像
})
.catch((err) => {
    // 錯誤處理
})

然後咱們這裡來問個問題:

stream 是由什麼組合的 ?

大部份的人應該會說不就是聲音與影像嗎 ? 嗯某些方面的對,但這是抽象的說法,在研究程式碼時我覺得要儘可能的去討探它裡面實際的做法,這樣出現問題了咱們可以才可以理解為啥。

在 WebRTC 中,咱們使用 getUserMedia 來取得聲音與影像的 stream,它就是一個通道,會不斷的將聲音與影像編碼,然後 stream 裡面實際上是由 track 所組成,它就是每一個媒體來源,用下面的圖會更容易的理解。

https://ithelp.ithome.com.tw/upload/images/20181023/20089358IGYWCPXNbe.png

然後轉換成 WebRTC 的物件關係圖會如下:

https://ithelp.ithome.com.tw/upload/images/20181023/20089358LXXIFDIkg9.png

知道了它的組合以後,基本上我們就可以針對那個 Track 進行操作。假設我們想操作麥克風或攝影機,那我們可以使用以下的程式碼,那將該個 track 取出來。

MediaStream.getAudioTracks()

MediaStream.getVideoTracks()

然後咱們就可以針對 track 做些事情,例如在某段時間將聲音禁止然後影像繼續錄,又或是在某段時間將採集的影像變小,然後在某段時間回復過來,這些就都可以做到囉。這裡就不寫範例囉。

備註

MediaStream.getAudioTracks 這方法是會回傳多個 track 沒錯,因為不同的麥克風就會有不同的 track。

如何對 Media stream 的聲音進行加工 ?


使用 AudioContext 就可以對聲音做點喝喝喝的事情

在某些時後,咱們希望將採集到的聲音進行一些加工,例如讓別人聽不出來聲音是誰,又或是想讓原本採集的聲音大聲些,這時咱們就需要使用 Web Audio API 的 AudioContext。

Web Audio API 是一個用來專門在 Web 上進行音源處理的東東,它的基本核心如下圖,第一個是 AudioContext,這東東你可以想成它是一個聲音世界的神。然後第二個是 AudioNode 它就是每個處理聲音的實體,它裡面的聲音可以從外部檔案、麥克風採集或是用 AudioContext 裡面所提供的東西來產生聲音。相對的它也可以將他的聲音丟給其它 AudioNode 來進行加工。

https://ithelp.ithome.com.tw/upload/images/20181023/20089358IP2GPbHMNQ.png

上面這樣說或需還有點兒抽像,接下來咱們簡單的來實作一段程式碼。

將 WebRTC 所採集的聲音進行放大,然後在直接輸出給喇叭

首先這段程式碼首先會先創造 AudioContext,接下來透過 createMediaStreamSource 來將 WebRTC 所採集的聲音流,轉換成 AudioContext 世界的 AudioNode。

 navigator.mediaDevices.getUserMedia({ audio: true })
    .then((stream) => {
      const audioContext = new AudioContext;

      // 將 WebRTC 所採集的聲音轉換成 AudioNode。
      const sourceNode = audioContext.createMediaStreamSource(stream);
      ……
    })
    .catch((err) => {
      console.log('nonono ~~~ !!');
    })

接下來我們在產生另一個 AudioNode 它是用來將我們來源聲音,音量加大的加工師。

navigator.mediaDevices.getUserMedia({ audio: true })
    .then((stream) => {
      const audioContext = new AudioContext;

      // 將 WebRTC 所採集的聲音轉換成 AudioNode。
      const sourceNode = audioContext.createMediaStreamSource(stream);

      // 產生音量加工師,用來將來源聲音加大
      const processNode = audioContext.createGain();
      processNode.gain.value = 20;
      sourceNode.connect(processNode);
      ……
    })
    .catch((err) => {
      console.log('nonono ~~~ !!');
    })

最後在將加工完的聲音丟到終端麥克風。

  navigator.mediaDevices.getUserMedia({ audio: true })
    .then((stream) => {
      const audioContext = new AudioContext;
      
      // 將 WebRTC 所採集的聲音轉換成 AudioNode。
      const sourceNode = audioContext.createMediaStreamSource(stream);

      // 產生音量加工師,用來將來源聲音加大
      const processNode = audioContext.createGain();
      processNode.gain.value = 20;
      sourceNode.connect(processNode);

      // 將加工完的聲音丟給終端麥克風
      const destinationNode = audioContext.destination;
      processNode.connect(destinationNode);
    })
    .catch((err) => {
      console.log('nonono ~~~ !!');
    })

結論


本篇文章中咱們學習到了以下的重點:

  • WebRTC 的 Stream ( Media Stream )。每一條 stream 都是由多個 track 所組成,每一個 track 就是一個媒體源( ex. 麥克風 A 、麥克風 B 、攝影機 )
  • 如何對 Media Stream 的聲音進行加工? 使用 Web Audio API 就可以處理囉。

參考資料



上一篇
30-07之Web 如何進行語音與影像採集 ?
下一篇
30-09之別人要如何聽到我的聲音呢 ?
系列文
30天之即時網路影音開發攻略(小白本)30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言