視頻網站的彈幕是如何保存的?


給說存xml里的人點了個反對。

怎麼可能存xml里嘛,一個彈幕網站,時時刻刻都有人發彈幕,但是寫xml是要鎖的啊。一群人同時發彈幕怎麼來的及寫到xml里嘛。

xml只是後端讀取資料庫生成的,用來給前端播放器解析的格式而已。

自己曾經嘗試著寫過彈幕網站,性能可能不是非常好,但至少不會用xml存彈幕。

彈幕是一個很典型的結構化數據,欄位不少。以B站彈幕為例,必須的欄位有cid(視頻id),發布時間,彈幕回放時間(就是在視頻的第幾秒出現這條彈幕),彈幕類型,字體大小,彈幕顏色,彈幕池,發送者和彈幕內容。

其中有索引需求的是cid和彈幕池。播放器請求彈幕時會發送自己的視頻id,這時候你需要返回這個視頻id對應的彈幕。每時每刻都有人發彈幕,為了讓顯示的彈幕有一個合理的觀看感受,所以我們一般會設置一個彈幕上限。又拿B站舉例,一般30分鐘的視頻彈幕上限是3000。

但是有一些彈幕比較特殊,它們可能是這個視頻的字幕,或者是被up主主動保護起來的彈幕,這些彈幕要求任何時候都要顯示。

於是伺服器提取彈幕的過程是:找出該視頻特殊彈幕池中的彈幕,然後找出普通彈幕池中該視頻彈幕的前3000條,兩者取並集,拿給後端生成xml,返回給前端播放器。

具體存儲上,我還是用了mysql作為存儲彈幕的資料庫,為了增強寫性能,用了讀寫分開。

同時,發彈幕這個行為對實時性要求比較低。畢竟發送彈幕以後馬上就可以在播放器里看到的那一條,是播放器自己的畫上去的,而不是從資料庫里取出來的。(B站的播放器在外面畫了一個藍框來表示)對於這種應用,非常適合採用消息隊列來應對大量的寫入。

我的實現裡面採用的rabbitmq,所有發送到伺服器的彈幕先拿去喂兔子。然後用一個daemon程序不斷從隊列里讀取彈幕並寫入資料庫。


保存到高速緩存中。自己寫不了的話用Redis也不錯。


應該是多級存儲的,最終持久化可能是資料庫,可能是分散式文件系統,都可以。然後,必然的會有一層以上的緩存伺服器,牽涉到較為複雜的數據同步。

基本上應該就是這個樣子,具體會有各種變化。


只是一個xml文件而已


身份是web開發者,卻沒有過接觸視頻的活。但大致能想到實現方式,這些想法今晚也用A站隨手做了測試,看看他們的實現方式。

彈幕持久化是前提條件,記錄跟隨視頻以及出現時間、位置、字體、顏色等等參數。

網站第一次Get請求肯定會把彈幕從資料庫中獲取返回給終端,緩存也好,Xml文件也好,視頻播放的過程中的彈幕必然是早早的已放在客戶端瀏覽器中,到位即顯。

而非直播視頻對彈幕的實時顯示在各個客戶端的要求並不高,非要有一定實時性,也可以利用非同步獲取並且插入緩存,在視頻播放的過程中定時獲取當前最新的彈幕信息。鑒於這點,在A站同個視頻開過2個瀏覽器,其中待輸入彈幕的視頻提前2分鐘播放,在某一時間點輸入彈幕並在當前瀏覽器成功顯示,而另外一個瀏覽器2分鐘後並未出現那條該出現的彈幕。可見A站應該僅是第一次請求時載入彈幕數據,之後定時獲取的機制沒實現。

關於彈幕的持久化保存,相信是有一定延遲性,在A站輸入某彈幕後,在幾秒後(可能是5)刷新瀏覽器,再次播放在那個位置,也存在未出現的情況。所以應該也是在幾秒後非同步寫入後台資料庫。

但想到是直播視頻的彈幕,實時性要求就特別高了,會利用大量websocket來構建,幾萬人同時在一個視頻在線的情況必然讓伺服器和分散式系統的要求特別高。有時間再研究更新更新。

關於A站的一些實現方式,僅憑隨手測試推測,並未深入研究,如有誤,請A站大神不要追究。


個人意見:

彈幕應該是即時的,後台不緩存的。

你看到的就是和你同時在線看視頻的人剛剛發的。造成大家一起看視頻聊天的效果。

而不是幾天甚至幾個月前發過的彈幕還會出現,那樣的話,彈幕就成留言板了,做成評論好了。

要不然,一個視頻稍微火熱一些就會有數不清的彈幕。但是有時候看一些播放量幾千萬的也很少出現彈幕,應該是火熱過去了,和你同時看的人少了,發彈幕的也少了,所以你看到的的就少了。

--------

非相關人員,僅為猜測。歡迎專業人士指正。


親自實驗了不是xml 把離線下載的視頻里的xml刪了 彈幕還是一樣的……

隨手截了兩張圖


你用客戶端下載個視頻 下載的目錄里有數據結構


推薦閱讀:

象棋和國際象棋的電腦程序是如何設計的?
為什麼在目前開發工資這麼高的情況下還是在知乎上看到很多程序員想轉行?
單片機編程最早是彙編,然後從彙編轉為c語言,那麼,c++會不會替代c語言來進行單片機編程 ?
計算器為什麼能實現保留根式、分數或含π的結果的功能?
程序員得痔瘡算工傷嗎?

TAG:互聯網 | 資料庫 | 軟體開發 | 程序 | 彈幕視頻網站 |