欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript+HTML?實現(xiàn)網(wǎng)頁錄制音頻與下載

 更新時間:2024年07月24日 10:24:31   作者:UestcXiye  
在這個數(shù)字化的時代,網(wǎng)頁端的音頻處理能力已經(jīng)成為一個非常熱門的需求,本文將詳細介紹如何利用 getUserMedia 和 MediaRecorder 這兩個強大的 API,實現(xiàn)網(wǎng)頁端音頻的錄制、處理和播放等功能,需要的朋友可以參考下

HTML + JavaScript 實現(xiàn)網(wǎng)頁錄制音頻與下載

簡介

在這個數(shù)字化的時代,網(wǎng)頁端的音頻處理能力已經(jīng)成為一個非常熱門的需求。本文將詳細介紹如何利用 getUserMedia 和 MediaRecorder 這兩個強大的 API,實現(xiàn)網(wǎng)頁端音頻的錄制、處理和播放等功能。

getUserMedia

getUserMedia 和 MediaRecorder 是 HTML5 中兩個非常重要的 API,用于訪問設(shè)備媒體輸入流并對其進行操作。

getUserMedia 允許網(wǎng)頁端訪問用戶設(shè)備的媒體輸入設(shè)備,比如攝像頭和麥克風。通過該 API,在獲得用戶授權(quán)后,我們可以獲取這些媒體流的數(shù)據(jù),并用于各種網(wǎng)頁應用場景中。

典型的使用方式如下:

// 請求獲取音頻流
navigator.mediaDevices.getUserMedia({
  audio: true
})
.then(stream => {
  // 在此處理音頻流
})

getUserMedia 接受一個 constraints 對象作為參數(shù),通過設(shè)置配置來請求獲取指定的媒體類型,常見的配置有:

  • audio:Boolean 值,是否獲取音頻輸入。
  • video:Boolean 值,是否獲取視頻輸入。
  • 以及更詳細的各種音視頻參數(shù)設(shè)置。

MediaRecorder

MediaRecorder API 可以獲取由 getUserMedia 生成的媒體流,并對其進行編碼和封裝,輸出可供播放和傳輸?shù)拿襟w文件。

典型的用法如下:

// 獲取媒體流
const stream = await navigator.mediaDevices.getUserMedia({ audio: true })
// 創(chuàng)建 MediaRecorder 實例 
const mediaRecorder = new MediaRecorder(stream);
// 注冊數(shù)據(jù)可用事件,以獲取編碼后的媒體數(shù)據(jù)塊
mediaRecorder.ondataavailable = event => {
  audioChunks.push(event.data);
}
// 開始錄制
mediaRecorder.start();
// 錄制完成后停止
mediaRecorder.stop(); 
// 將錄制的數(shù)據(jù)組裝成 Blob
const blob = new Blob(audioChunks, {
  type: 'audio/mp3' 
});

簡單來說,getUserMedia 獲取輸入流,MediaRecorder 對流進行編碼和處理,兩者結(jié)合就可以實現(xiàn)強大的音視頻處理能力。

獲取和處理音頻流

了解了基本 API 使用方法后,我們來看看如何獲取和處理音頻流。

首先需要調(diào)用 getUserMedia 來獲取音頻流,典型的配置是:

const stream = await navigator.mediaDevices.getUserMedia({
  audio: {
    channelCount: 2,  
    sampleRate: 44100,
    sampleSize: 16,
    echoCancellation: true 
  }
});

我們可以指定聲道數(shù)、采樣率、采樣大小等參數(shù)來獲取音頻流。

PS:這似乎不管用。

使用 navigator.mediaDevices.enumerateDevices() 可以獲得所有可用的媒體設(shè)備列表,這樣我們就可以提供設(shè)備選擇功能給用戶,而不僅僅是默認設(shè)備。

舉例來說,如果我們想要讓用戶選擇要使用的錄音設(shè)備:

// 1. 獲取錄音設(shè)備列表
const audioDevices = await navigator.mediaDevices.enumerateDevices();
const mics = audioDevices.filter(d => d.kind === 'audioinput');
// 2. 提供設(shè)備選擇 UI 供用戶選擇
const selectedMic = mics[0]; 
// 3. 根據(jù)選擇配置進行獲取流
const constraints = {
  audio: {
    deviceId: selectedMic.deviceId
  }  
};
const stream = await navigator.mediaDevices.getUserMedia(constraints);

這樣我們就可以獲得用戶選擇的設(shè)備錄音了。

獲得原始音頻流后,我們可以利用 Web Audio API 對其進行處理。

例如添加回聲效果:

// 創(chuàng)建音頻環(huán)境
const audioContext = new AudioContext();
// 創(chuàng)建流源節(jié)點
const source = audioContext.createMediaStreamSource(stream);
// 創(chuàng)建回聲效果節(jié)點
const echo = audioContext.createConvolver();
// 連接處理鏈
source.connect(echo);
echo.connect(audioContext.destination);
// 加載回聲沖擊響應并應用
const impulseResponse = await fetch('impulse.wav');
const buffer = await impulseResponse.arrayBuffer();
const audioBuffer = await audioContext.decodeAudioData(buffer);
echo.buffer = audioBuffer;

通過這樣的音頻處理鏈,我們就可以在錄音時添加回聲、混響等音效了。

實現(xiàn)音頻的錄制和播放

錄制音頻的步驟:

  • 調(diào)用 getUserMedia 獲取音頻流。
  • 創(chuàng)建 MediaRecorder 實例,傳入音頻流。
  • 注冊數(shù)據(jù)可用回調(diào),以獲取編碼后的音頻數(shù)據(jù)塊。
  • 調(diào)用 recorder.start() 開始錄制。
  • 錄制完成后調(diào)用 recorder.stop()。

代碼:

let recorder;
let audioChunks = [];
// 開始錄音 handler
const startRecording = async () => {
  const stream = await navigator.mediaDevices.getUserMedia({
    audio: true
  });
  recorder = new MediaRecorder(stream);
  recorder.ondataavailable = event => {
    audioChunks.push(event.data);
  };
  recorder.start();
} 
// 停止錄音 handler
const stopRecording = () => {
  if(recorder.state === "recording") {
    recorder.stop();
  }
}

錄音完成后,我們可以將音頻數(shù)據(jù)組裝成一個 Blob 對象,然后賦值給一個 <audio> 元素的 src 屬性進行播放。

代碼:

// 錄音停止后
const blob = new Blob(audioChunks, { type: 'audio/ogg' }); 
const audioURL = URL.createObjectURL(blob);
const player = document.querySelector('audio');
player.src = audioURL;
// 調(diào)用播放
player.play();

這樣就可以播放剛剛錄制的音頻了。

后續(xù)也可以添加下載功能等。

音頻效果的處理

利用 Web Audio API,我們可以添加各種音頻效果,進行音頻處理。

例如添加回聲效果:

const audioContext = new AudioContext();
// 原始音頻節(jié)點
const source = audioContext.createMediaStreamSource(stream);
// 回聲效果節(jié)點
const echo = audioContext.createConvolver();
// 連接處理鏈
source.connect(echo);
echo.connect(audioContext.destination);
// 加載沖擊響應作為回聲效果
const impulseResponse = await fetch('impulse.wav');
const arrayBuffer = await impulseResponse.arrayBuffer();
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
echo.buffer = audioBuffer;

這樣在錄制時音頻流就會經(jīng)過回聲效果處理了。

此外,我們還可以添加混響、濾波、均衡器、壓縮等多種音頻效果,使得網(wǎng)頁端也能處理出專業(yè)級的音頻作品。

實時語音通話的應用

利用 getUserMedia 和 WebRTC 技術(shù),我們還可以在網(wǎng)頁端實現(xiàn)實時的點對點語音通話。

簡述流程如下:

  • 通過 getUserMedia 獲取本地音視頻流。
  • 創(chuàng)建 RTCPeerConnection 實例。
  • 將本地流添加到連接上。
  • 交換 ICE 候選信息,建立連接。
  • 當檢測到連接后,渲染遠端用戶的音視頻流。

這樣就可以實現(xiàn)類似 Skype 的網(wǎng)頁端語音通話功能了。

代碼:

// 1. 獲取本地流
const localStream = await navigator.mediaDevices.getUserMedia({
  audio: true,
  video: true
});
// 2. 創(chuàng)建連接對象
const pc = new RTCPeerConnection();
// 3. 添加本地流
localStream.getTracks().forEach(track => pc.addTrack(track, localStream)); 
// 4. 交換 ICE 等信令,處理 ONADDSTREAM 等事件
// ...
// 5. 收到遠端流,渲染到頁面
pc.ontrack = event => {
  remoteVideo.srcObject = event.streams[0];
}

獲取本地輸入流后,經(jīng)過編碼和傳輸就可以實現(xiàn)語音聊天了。

兼容性和 Latency 問題

盡管 getUserMedia 和 MediaRecorder 在現(xiàn)代瀏覽器中已經(jīng)得到了較好的支持,但由于不同廠商和版本實現(xiàn)存在差異,在實際應用中還是需要注意一些兼容性問題:

  • 檢測 API 支持情況,提供降級方案。
  • 注意不同瀏覽器對 Codec、采樣率等參數(shù)支持的差異。
  • 封裝瀏覽器差異,提供統(tǒng)一的 API。

此外,錄音和播放也存在一定的延遲問題。我們需要針對 Latency 進行優(yōu)化,比如使用更小的 buffer 大小,壓縮數(shù)據(jù)包大小等方法。

項目代碼

record.html:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Record Page</title>
        <link rel="stylesheet" type="text/css" href="css/record.css" rel="external nofollow" >
    </head>
    <body>
        <div class="app">
            <audio controls class="audio-player"></audio>
            <button class="record-btn">錄音</button>
            <a id="download" download="record.aac"></a>
        </div>
    </body>
    <script src="js/record.js"></script>
</html>

record.css:

.app {
    display: flex;
    justify-content: center;
    align-items: center;
}
.record-btn {
    margin: 0 10px;
}

record.js:

const recordBtn = document.querySelector(".record-btn")
const player = document.querySelector(".audio-player")
const download = document.querySelector('#download')
if (navigator.mediaDevices.getUserMedia) {
    let audioChunks = []
    // 約束屬性
    const constraints = {
        // 音頻約束
        audio: {
            sampleRate: 16000, // 采樣率
            sampleSize: 16, // 每個采樣點大小的位數(shù)
            channelCount: 1, // 通道數(shù)
            volume: 1, // 從 0(靜音)到 1(最大音量)取值,被用作每個樣本值的乘數(shù)
            echoCancellation: true, // 開啟回音消除
            noiseSuppression: true, // 開啟降噪功能
        },
        // 視頻約束
        video: false
    }
    // 請求獲取音頻流
    navigator.mediaDevices.getUserMedia(constraints)
        .catch(err => serverLog("ERROR mediaDevices.getUserMedia: ${err}"))
        .then(stream => {// 在此處理音頻流
            // 創(chuàng)建 MediaRecorder 實例
            const mediaRecorder = new MediaRecorder(stream)
            // 點擊按鈕
            recordBtn.onclick = () => {
                if (mediaRecorder.state === "recording") {
                    // 錄制完成后停止
                    mediaRecorder.stop()
                    recordBtn.textContent = "錄音結(jié)束"
                }
                else {
                    // 開始錄制
                    mediaRecorder.start()
                    recordBtn.textContent = "錄音中..."
                }
            }
            mediaRecorder.ondataavailable = e => {
                audioChunks.push(e.data)
            }
            // 結(jié)束事件
            mediaRecorder.onstop = e => {
                // 將錄制的數(shù)據(jù)組裝成 Blob(binary large object) 對象(一個不可修改的存儲二進制數(shù)據(jù)的容器)
                const blob = new Blob(audioChunks, { type: "audio/aac" })
                audioChunks = []
                const audioURL = window.URL.createObjectURL(blob)
                // 賦值給一個 <audio> 元素的 src 屬性進行播放
                player.src = audioURL
                // 添加下載功能
                download.innerHTML = '下載'
                download.href = audioURL
            }
        },
            () => {
                console.error("授權(quán)失??!");
            }
        );
} else {
    console.error("該瀏覽器不支持 getUserMedia!");
}

運行實例

打開 record.html,首先獲取麥克風權(quán)限:

點擊“允許”。

頁面有一個 audio-player 和一個 buttom。

點擊“錄音”按鈕,就開始錄音了。

再點一次按鈕,停止錄音,數(shù)據(jù)傳回給 audio-player,可以在網(wǎng)頁上播放錄音。

點擊“下載”,可以下載錄制的音頻。

PS:音頻文件名稱設(shè)置為 record.aac,文件格式為 WebM,音頻格式為 opus,單聲道,采樣率 48kHz,位深 32bit。

參考資料

Blob 的所有 Type 類型

getUserMedia() 音頻約束

源碼下載

百度網(wǎng)盤下載地址

鏈接: https://pan.baidu.com/s/1VS--_5O7FlBUss0VAERn-Q?pwd=8s43

提取碼: 8s43

GitHub:Web-Record

到此這篇關(guān)于JavaScript+HTML 實現(xiàn)網(wǎng)頁錄制音頻與下載的文章就介紹到這了,更多相關(guān)js網(wǎng)頁錄制音頻內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論