![](/img/trans.png)
[英]Possible to analyze streaming audio from Icecast using Web Audio API and createMediaElementSource?
[英]Streaming Icecast Audio & Metadata with Javascript and the Web Audio API
我一直在試圖找出實現我已經有一段時間的想法的 go 的最佳方法。
目前,我有一個無線電掃描儀的 icecast mp3 stream,其中“正在播放”的元數據會根據掃描儀登陸的頻道實時更新。 當使用 VLC 等專用媒體播放器時,元數據與接收到的音頻完美對齊,並且它的功能完全符合我的要求 - 本質上是一個遠程無線電掃描儀。 我想通過網頁實現類似的東西,表面上這似乎是一個簡單的任務。
如果我想做的只是 stream 音頻,那么使用簡單的<audio>
標簽就足夠了。 但是,HTML5 音頻播放器沒有嵌入流內元數據的概念,該元數據與 mp3 音頻數據一起進行了 icecast 編碼。 雖然我可以從 icecast 服務器狀態 json 查詢當前“正在播放”的元數據,但由於客戶端和服務器端緩沖,以這種方式完成時,音頻和元數據之間可能會有超過 20 秒的延遲。 在某些情況下,當掃描儀每秒更改其“正在播放”的元數據時,這完全不適合我的應用程序。
有一個非常有趣的 Node.JS 解決方案,它是在考慮到這個確切目標的情況下開發的——無線電掃描儀應用程序中的實時元數據: icecast-metadata-js 。 這表明確實可以處理來自單個 icecast stream 的音頻和元數據。 現場演示尤其令人印象深刻: https://eshaz.github.io/icecast-metadata-js/
但是,我正在尋找一種無需安裝 Node.JS 即可完全在客戶端運行的解決方案,而且這似乎應該是相對微不足道的。
今天搜索了一天的大部分時間后,似乎在本網站和其他地方提出了幾個類似的問題,但沒有任何連貫的、布局合理的答案或建議。 From what I've been able to gather so far, I believe my solution is to use a Javascript streaming function (such as fetch
) to pull the raw mp3 & metadata from the icecast server, playing the audio via Web Audio API and handling the元數據塊到達時。 如下圖所示:
我想知道是否有人通過 Web 音頻 API 播放 mp3 流有任何好的閱讀和/或示例。 在大多數 JS 方面,我仍然是一個相對新手,但我了解了 API 的基本概念以及它如何處理音頻數據。 我正在努力實現的正確方法是:a)實時處理來自 mp3 stream 的數據,以及 b)檢測嵌入在 stream 中的元數據塊並相應地處理這些塊。
如果這是一個冗長的問題,我深表歉意,但我想提供足夠的背景故事來解釋為什么我想以我的具體方式向 go 講述事情。
提前感謝您的建議和幫助!
很高興您找到了我的圖書館icecast-metadata-js 。 這個庫實際上可以在客戶端和 NodeJS 中使用,現場演示的所有源代碼,它完全在客戶端運行:在存儲庫中: https://github.com/eshaz/icecast-metadata- js/tree/master/src/demo . 演示中的流沒有改變,只是服務器端的普通 Icecast 流。
您在圖表中的內容基本上是正確的。 ICY 元數據交織在實際的 MP3“流”數據中。 ICY 元數據更新發生的元數據間隔或頻率可以在 Icecast 服務器配置 XML 中配置。 此外,這可能取決於您的來源向 Icecast 發送元數據更新的頻率/准確度。 在我的演示頁面上,警察掃描儀中使用的軟件幾乎與音頻同步更新。
通常,默認元數據間隔為 16,000 字節,這意味着每 16,000 個 stream (mp3) 字節,將從 Icecast 發送元數據更新。 元數據更新總是包含一個長度字節。 如果長度字節大於0,則元數據更新的長度為元數據長度字節*16。
ICY 元數據是一串由分號分隔的 key='value' 對。 元數據更新中任何未使用的長度都是 null 填充的。
即"StreamTitle='The Stream Title';StreamUrl='https://example.com';\0\0\0\0\0\0"
read [metadataInterval bytes] -> Stream data
read [1 byte] -> Metadata Length
if [Metadata Length > 0]
read [Metadata Length * 16 bytes] -> Metadata
字節長度 | 響應數據 | 行動 |
---|---|---|
ICY 元數據間隔 | stream數據 | 發送到您的音頻解碼器 |
1 | 元數據長度字節 | 用於確定元數據字符串的長度(不發送到音頻解碼器) |
元數據長度 * 16 | 元數據字符串 | 解碼並更新您的“正在播放”(不要發送到音頻解碼器) |
對 Icecast 服務器的初始GET
請求需要包含Icy-MetaInt: 1
header,它告訴 Icecast 提供交錯的元數據。 響應 header 將包含 ICY 元數據間隔Icy-MetaInt
,應捕獲(如果可能)並用於確定元數據間隔。
在演示中,我使用客戶端獲取 API 來發出 GET 請求,並將響應數據提供給IcecastReadableStream
的一個實例,該實例將 stream 和元數據分開,並通過回調使每個可用。 我正在使用媒體源 API 播放 stream 數據,並獲取時序數據以正確同步元數據更新。
這是讀取 ICY 元數據所需的最低 CORS 配置:
Access-Control-Allow-Origin: '*' // this can be scoped further down to your domain also
Access-Control-Allow-Methods: 'GET, OPTIONS'
Access-Control-Allow-Headers: 'Content-Type, Icy-Metadata'
如果需要, icecast-metadata-js可以檢測 ICY 元數據間隔,但最好允許客戶端使用此額外的 CORS 配置從 header 讀取它:
Access-Control-Expose-Headers: 'Icy-MetaInt'
此外,我計划發布一個新功能(在我完成 Ogg 元數據之后),它封裝了fetch
api 邏輯,這樣用戶所需要做的就是提供一個 Icecast 端點,並取回音頻/元數據。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.