[英]How to make Live audio broadcasting API in NodeJs, ExpressJS?
讓我解釋
我使用 fs.createReadStream 等……方法……但沒有一個能正常工作……它們都從起點開始播放音頻……
簡而言之,我想制作一個廣播平台,該平台已經將 mp3 文件存儲為 Radio。
示例:- https://live.sgpc.net:8443/;nocache=889869
打開此鏈接.. 將播放現場音頻。
我找到了一篇log rocket發的帖子,指向正確的方向,文章鏈接。
主要思想是通過 Fs.createReadStream 開始讀取音頻文件,它會給你一個你可以操作的可讀流。 您獨立於連接到您的應用程序的用戶讀取音頻文件,在任何情況下都必須向前移動音頻。
您不想讀得太快,最好是按照歌曲的比特率,這樣您就可以“模仿”實時播放。 有多個 npm 包可以讀取音頻文件的比特率。 使用此信息,您可以將音頻流通過管道傳輸到轉換流(雙工流)中,以限制音頻流的播放速率。
const songReadable = Fs.createReadStream(audioFilePath); // readable stream to manipulate
const throttleTransformable = new Throttle(bitRate); // Transform stream to rate limit the reading of file
songReadable.pipe(throttleTransformable); // passing the readable stream to the transform
之后,您需要將 throttleTransformable 流傳遞給客戶端。 為了更輕松地處理背壓並將音頻流傳遞給多個客戶端,您可以為每個新客戶端創建一個新的 Stream,我們稱之為 clientStream。 當數據在 throttleTransformable 流上可用時,您可以將數據寫入每個 clientStream
throttleTransformable.on('data', (chunk) => {broadcastToEveryStreams(chunk)});
然后您只需將客戶端流通過管道傳輸到響應流,瀏覽器將接收音頻數據,但正如您打算使用實時數據一樣,而不是從一開始就接收。
這是帶有快速框架的 nodejs 中的完整示例。 它只是一個玩具,但我希望它能為您指明正確的方向
import { parseFile } from 'music-metadata';
import express from "express"
import Throttle from 'throttle';
import Fs from 'fs'
import { PassThrough } from 'stream'
const app = express();
let filePath = "./yourMP3AudioFile.mp3"; // put your favorite audio file
let bitRate = 0;
const streams = new Map()
app.use(express.static('public'));
app.get("/stream", (req, res) => {
const { id, stream } = generateStream() // We create a new stream for each new client
res.setHeader("Content-Type", "audio/mpeg")
stream.pipe(res) // the client stream is pipe to the response
res.on('close', () => { streams.delete(id) })
})
const init = async () => {
const fileInfo = await parseFile(filePath)
bitRate = fileInfo.format.bitrate / 8
}
const playFile = (filePath) => {
const songReadable = Fs.createReadStream(filePath);
const throttleTransformable = new Throttle(bitRate);
songReadable.pipe(throttleTransformable);
throttleTransformable.on('data', (chunk) => { broadcastToEveryStreams(chunk) });
throttleTransformable.on('error', (e) => console.log(e))
}
const broadcastToEveryStreams = (chunk) => {
for (let [id, stream] of streams) {
stream.write(chunk) // We write to the client stream the new chunck of data
}
}
const generateStream = () => {
const id = Math.random().toString(36).slice(2);
const stream = new PassThrough()
streams.set(id, stream)
return { id, stream }
}
init()
.then(() => app.listen(8080))
.then(() => playFile(filePath))
對於前端部分,公用文件夾中有一個簡單的 HTML 文件
<,DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width. initial-scale=1.0"> <title>NodeJS web radio</title> </head> <body> <audio id="audio" src="/stream" type="audio/mpeg" preload="none" controls autoplay></audio> </body> </html>
以及我使用的 npm 包
{
"express": "^4.18.2",
"music-metadata": "^8.1.0",
"throttle": "^1.0.3"
}
代碼主要是從 log rocket post repo中得到啟發。 我只是將它改編為 express 框架,並保留了必要的代碼以了解他們使用的方法。 它不處理音頻文件轉換或與客戶端的正確終止。 我使用了 ES6 模塊包,你必須在你的 package.json 文件中指定“type”:“module”才能工作
我不知道為什么,但自動播放似乎對我不起作用,我必須手動單擊開始箭頭。 當我在啟動服務器后從多個設備連接時,在不同的時間,我可以聽到實時音頻,盡管它在每個客戶端/設備之間並不完全同步。
小心,對客戶端流沒有任何控制,如果緩沖區已滿,因為客戶端連接太慢,它可能會變得丑陋,您可以檢查客戶端/響應流的高水位標記以獲得更多控制。 我不確定它是否會為很多客戶很好地擴展。 在我們復制數據的地方創建一個新流似乎不太正確。
也許你可以直接將數據寫入 express 的響應流
res.write(chunckAudioFile)
或者使用 websocket 將您的用戶連接到服務器。 在所有情況下,您都必須了解客戶端連接狀態。
我沒有花時間在這上面,但也許你也可以在客戶端緩沖音頻數據,以獲得更流暢的控制和播放時間。 WebAudio API 似乎有一些功能可以流式傳輸到 webdev 帖子的鏈接
綜上所述,根據您的要求,在某些網絡廣播中播放音頻我建議您查看專業廣播服務器,如 Shoutcast 或 Icecast。 對於客戶端,也許看看似乎處理音頻的videoJs
我希望它能幫助你,並給你好的想法
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.