2011-04-16 45 views
20

我想實現一個Python中的服務器,通過HTTP流式傳輸MP3格式的音樂。我希望它播放音樂,以便客戶端可以連接到流,並開始聽任何正在播放的內容,就像電臺一樣。編寫一個Python音樂流光

以前,我使用SocketServer.TCPServer在Python中實現了自己的HTTP服務器(是的,我知道BaseHTTPServer存在,只是想自己編寫一個迷你HTTP協議棧),所以音樂流媒體如何在架構上有所不同?我需要在網絡端和MP3端查看哪些庫?

+0

你想讓VLC這樣的東西能夠鏈接到流中,還是隻編寫自己的客戶端? – thenoviceoof 2011-04-17 06:24:50

+0

@thenoviceoof - 很好的問題,是的,我想要「主流」的客戶端能夠連接。 iTunes,Winamp,VLC等 – 2011-04-17 09:15:56

+0

您是在實時壓縮音頻還是在流式傳輸預先創建的MP3文件? – rakslice 2011-04-24 01:41:48

回答

26

mp3格式是專爲流式傳輸而設計的,它使得一些事情比您預想的要簡單。數據本質上是一個audio frames的流,帶有內置的邊界標記,而不是文件頭,然後是原始數據。這意味着,一旦客戶希望接收音頻數據,您就可以從現有mp3源中的任意點開始發送字節,無論是實時還是文件,並且客戶端將同步到它找到的下一幀,開始播放音頻。好極了!

當然,您必須爲客戶提供設置連接的方法。事實上的標準是SHOUTcast(ICY)協議。這非常類似於HTTP,但是狀態和頭部字段的差異足以與Python內置的http服務器庫不直接兼容。您可能可以讓這些庫爲您完成一些工作,但他們記錄的接口不足以完成它;你必須閱讀他們的代碼才能理解如何讓他們說出SHOUTcast。

這裏有一些鏈接,讓你開始:

http://forums.winamp.com/showthread.php?threadid=70403

http://forums.radiotoolbox.com/viewtopic.php?t=74

http://www.smackfu.com/stuff/programming/shoutcast.html

http://en.wikipedia.org/wiki/Shoutcast

我建議從一個單一的MP3文件作爲數據源,獲取客戶端 - 服務器連接設置和p後期工作,然後繼續討論諸如實時數據源,多種編碼比特率,帶內元數據和播放列表等問題。

播放列表通常是.pls或.m3u文件,基本上只是指向您的直播流的URL的靜態文本文件。它們並不困難,甚至不是絕對必要的,因爲許多(大多數?)mp3流媒體客戶端將接受沒有播放列表的實時流URL。

至於建築,這個領域是非常開放的。您擁有與HTTP服務器相同的選項。螺紋?工作進程?事件驅動?隨你便。對我而言,更有趣的問題是如何將來自單個輸入流(廣播公司)的數據與服務於多個輸出流(播放器)的網絡處理器共享。爲了避免IPC和同步問題,我可能會從單線程事件驅動設計開始。在Python 2中,像gevent這樣的庫會給你very good I/O performance,同時允許你以一種非常容易理解的方式構建代碼。在python 3中,我更喜歡asyncio協程。

+0

會動態生成.mp3數據需要高級的python編程嗎? – MikeiLL 2014-09-09 23:42:29

0

你會想看看服務m3upls文件。這應該給你一個文件格式,讓玩家理解得足以擊中你的http服務器尋找mp3文件。

一個最小的m3u文件只是一個簡單的文本文件,每行一首歌曲url。假設你有以下網址提供的服務器上:

/playlists/<playlist_name/playlist_id> 
/songs/<song_name/song_id> 

你會成爲從URL播放列表:

/playlists/myfirstplaylist 

和資源的內容將只是:

/songs/1 
/songs/mysong.mp3 

一位玩家(如Winamp)將能夠打開您的HTTP服務器上的m3u文件的URL,然後開始播放播放列表中的第一首歌曲。您需要做的所有事情都是爲了支持這一點,就像服務於任何其他靜態內容一樣。

取決於您希望支持多少客戶端,您可能希望使用像Twisted這樣的庫來查看異步IO以支持大量同步流。越來越走得太遠

+4

這聽起來很像我喜歡的SHOUTcast(http://en.wikipedia.org/wiki/SHOUTcast)。我的問題是:如何使其工作,使「播放列表」文件只是一個通用的URL,指向「流」,而不是一個特定的MP3文件?即使URL是「/somefile.mp3」,我也不希望爲每首歌曲**生成一個播放列表。相反,我希望它是一個連續不斷的歌曲/廣告等,就像電臺一樣。事實上,這是一個很好的例子。廣播電臺如何從他們的網站上做到這一點,你可以在那裏收聽他們的現場直播? – 2011-04-22 12:41:15

+0

我假設他們只是繼續將音頻內容寫入客戶端http連接。沒有理由你給定的URL不能代表無限的數據流。如果你沒有關閉連接,客戶端將繼續收聽,因此當你完成流式傳輸歌曲文件時,只需開始將商業廣告寫入套接字,然後再播放另一首歌曲。你能分享一些代碼,以便我們看看你的簡單HTTP服務器,也許更具體地談論你需要做什麼? – stderr 2011-04-26 02:48:52

+1

這個答案沒有解決「開始聽任何正在播放的東西,就像一個廣播電臺」。 – 2013-01-16 21:56:18

0

你會希望有一個指向一個靜態的URI m3u格式或.PLS文件(例如http://example.com/now_playing.mp3),然後在他們要求該文件時,向他們發送mp3數據,無論你在歌曲中的哪個位置。可能有一些小問題我在這裏琢磨......但是,至少在森林指出,你可以開始從任何字節流式傳輸mp3數據。

+0

實際上,只要客戶要求,你幾乎可以**在客戶端開始播放mp3數據。 MP3編碼不使用文件標題。 – 2013-01-18 19:05:10

+0

嗯,有趣。你是對的,它是整個文件中的交錯標題/數據。但是,這樣做會錯過任何ID3標籤,而且我的主要觀點是,您可能不應該從任何字節位置開始,而必須從其中一個標頭開始。 – mike 2013-01-20 09:50:49

+0

你絕對應該從任何字節位置開始。格式就是爲此而設計的。同步比特出現在每個幀中專門用於該目的。 – 2013-01-20 20:35:16

1

既然你已經有很好的經驗蟒(給你已經寫了一個HTTP服務器),我只能提供關於如何擴展您已經完成了地面工作幾個要點:

  • 準備你的服務器處理請求頭請求處理器如:Accept-Encoding,Range,TE (Transfer Encoding)等。一個MP3-over-HTTP播放器(即VLC)不過是一個MP3播放器,知道如何「說」HTTP和「尋找」文件中的不同位置。

  • 使用wireshark或tcpdump到當通過HTTP播放mp3時,通過VLC嗅探實際的HTTP請求,所以您知道您將如何接收並實施它們。

祝您的項目順利!