前面幾篇咱們已經學習了聲音與影像的採集相關知識,那接下咱們來學習一下如何在 Web 上進行聲音與影像的採集。
如何在 Web 上進行聲音與影像的採集 ? ( 其它平台的別問我 )
這篇文章中,咱們將會用到一個東東叫做WebRTC
,接下來會以它為主,將之分成以下三個章節:
讓瀏覽器不需加裝任何套件就可以進行即時文字、語音與影像對話的 API 。
WebRTC 全名為 Web Real-Time Communication,中文為網頁即時通訊,這東東用途就是讓咱們的瀏覽器不用裝認何啥套件就可以進行和其它瀏覽器進行即時文字、語音與影像對話。
它在 2011 年時進入了 W3C 的推薦表準,並且到了現在(2018),大部份的瀏覽器都有支援 (IE 例外)。
它主要有三種類型的 API:
基本上在這篇文章中只會用到第一個 getUserMedia 其它的 API 在後面文章會詳細的進行說明。
當前(2018)支援各平台的狀態請參考以下連結:
事實上就是如此的簡單,下面程式碼中,我們使用 getUserMedia 來採集聲音與影像,而 stream 就是咱們所採集到的聲音與影像,它們都是 raw data,也就是說聲音是 PCM 編碼,而影像就是單純的一堆連續的圖片編碼。
const constraints = { audio: true, video: true }
navigator.mediaDevices.getUserMedia(constraints)
.then((stream) => {
// stream 就是咱們的聲音與影像
})
.catch((err) => {
// 錯誤處理
})
上面的程式碼中有幾個重點要注意一下:
這也代表你可以將程式碼改成如下,記得要 try catch 不然錯誤會無法捕捉到的。
const constraints = { audio: true, video: true }
try {
const stream = await navigator.mediaDevices.getUserMedia(constraints)
} catch (error) {
// 錯誤處理
}
MediaStream 之後會詳細說明。
詳細的參數請參考此篇文章這裡只簡單的說明有那些用法。
例如你可限制只使用 audio:
{ audio: true }
例如你可以限制 video 的長與寬:
{ video: { width: 1280, height: 720 } }
例如你可以限制影像的幀率(FPS):
之前的文章有提到幀率這東西,它就是一秒鐘的影像有幾個圖片,如果現在是屬於低頻寬的網路環境,咱們可以將他調低,如下面所示,它就變成一秒鐘的影像只有 10 張圖片(正常應該是 20 ~ 30)。
{ video: { frameRate: 10 }
例如你可以調整聲音的採樣率與採樣大小:
{ audio: true, sampleSize: 8 (bit), sampleRate: 40000 (40kHz) }
不過 stack overflow 這裡看到好像有說就算調整了也沒啥用,不過這裡我只是要讓你知道,是有這兩種屬性的。
下面的範例中,我們有用到 getUserMedia 來進行聲音的採集,同時我們有用到 recorderjs 這個套件來將採集來的聲音記錄下來,最後結束時,會將聲音輸出成 wav。最下面附件有全部程式碼,可以直接的複製到 html 檔案後,然後再用瀏覽器開啟,最後等個 10 秒鐘,你就會看到多了聲音控制畫面與下載的連結了。
在這段程式碼中有一個東西叫AudioContext
,它也是原生的 API,你可以想成它是一個聲音的容器,然後我們將聲音串流丟到它的裡面,接下來咱們就可以針對這個容器內的聲音做些事情,像記錄或加工都可以。
navigator.mediaDevices.getUserMedia({ audio: true })
.then((stream) => {
const audioContext = new AudioContext;
const audioInput = audioContext.createMediaStreamSource(stream);
const rec = new Recorder(audioInput);
// 這個聲音串流一開時,就開始進行錄製。
rec.record()
setTimeout(function () {
// 然後在 10 秒後結束錄製,並產生個語音控制項與下載連結。
rec.stop();
createAudioController(rec);
createDownloadLink(rec);
}, 10000);
})
.catch((err) => {
console.log('nonono ~~~ !!');
})
接下來 10 秒過後,我們會停止錄製,並且會產生兩個東西,如下圖,有點醜我知道,因為我懶改。
首先第一個是畫面上會有個 audio 的控制項,讓你可以直接聽你剛剛錄的歌,下面為這段程式碼。
function createAudioController(rec) {
rec && rec.exportWAV((blob) => {
const url = URL.createObjectURL(blob);
const audio = document.createElement('audio');
audio.controls = true;
audio.src = url;
main.appendChild(audio);
});
}
第二個是畫面上會有個 link 連結,點下去就可以下載你剛剛錄的聲音 wav 檔,這個檔案前一篇中文章30-06之聲音與影像的封裝有提到,它是儲放聲音的一種容器,通常他就是用來專門儲放 raw data (PCM) 的格式(容器)。
function createAudioController(rec) {
rec && rec.exportWAV((blob) => {
const url = URL.createObjectURL(blob);
const audio = document.createElement('audio');
audio.controls = true;
audio.src = url;
main.appendChild(audio);
});
}
這篇文章中我們簡單的學習到以下幾個重點:
這篇文章中我們說明了如何在 Web 上進行聲音的採集,但這只是直播開發用戶端的其中一部份,其它的 Android、ios、mac、windows 平台如何的去進行採集,那就要請各位自已去探討囉,這裡就只針對我熟悉的 Web 部份來研究。
<html>
<div id="main"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/recorderjs/0.1.0/recorder.js"></script>
<script>
navigator.mediaDevices.getUserMedia({ audio: true })
.then((stream) => {
const audioContext = new AudioContext;
const audioInput = audioContext.createMediaStreamSource(stream);
const rec = new Recorder(audioInput);
// 這個聲音串流一開時,就開始進行錄製。
rec.record()
setTimeout(function () {
// 然後在 10 秒後結束錄製,並產生個下載連結。
rec.stop();
createAudioController(rec);
createDownloadLink(rec);
}, 10000);
})
.catch((err) => {
console.log('nonono ~~~ !!');
})
function createDownloadLink(rec) {
rec && rec.exportWAV((blob) => {
const url = URL.createObjectURL(blob);
const hf = document.createElement('a');
hf.href = url;
hf.download = 'test.wav';
hf.innerHTML = hf.download;
main.appendChild(hf);
});
}
function createAudioController(rec) {
rec && rec.exportWAV((blob) => {
const url = URL.createObjectURL(blob);
const audio = document.createElement('audio');
audio.controls = true;
audio.src = url;
main.appendChild(audio);
});
}
</script>
</html>