簡體   English   中英

如何在 NodeJs、ExpressJS 中制作音頻直播 API?

[英]How to make Live audio broadcasting API in NodeJs, ExpressJS?

讓我解釋

  1. 我在服務器上有一些 mp3 音頻文件
  2. 現在,我想借助 express 或 nodejs api 從服務器廣播這些音頻文件
  3. 當客戶端點擊此 API 時,音頻將在客戶端播放……而不是從頭開始……它應該是現場播放的,目前它在任何地方都在播放。

我使用 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM