背景
為Mac上的播放器添加一個彈幕層,這樣就可以看到直播的視頻和彈幕了,這樣就徹底的告別了flash。有以下幾個問題需要處理
- 獲取彈幕數據,以及處理彈幕數據
- 將處理后的彈幕數據,展示在播放器的上一層并且使其滾動起來
AsyncSocket & GCDAsyncSocket
項目中的socket通訊使用到了CocoaAsyncSocket。
由于之前在iOS上也實現了彈幕的獲取,那時候并沒有涉及到同時有播放器的播放,所以當時使用的AsyncSocket也并沒有出現任何問題。這次不同的是,需要在播放的同時獲取彈幕并顯示,依然使用AsyncSocket則導致線程阻塞無法異步執行播放任務和彈幕,在各種Google后想到了去查詢AsyncSocket和GCDAsyncSocket的區別,于是將其進行了切換,好在只需要修改相應的代理方法即可,方法內的發送數據、接收數據實現是一致的,可以無痛切換。
關于它們的詳細區別Reference_GCDAsyncSocket,About AsyncSocket
斗魚彈幕的獲取機制,細節部分可以在github上搜索,已經有很多現成的實現方法了,主要流程就是一次身份驗證,然后才是彈幕數據的獲取(ps:數據經過序列化的數據),還有注意的就是為了驗證在線的心跳包機制。官方文檔
NSView 中的 NSTextField 背景透明
彈幕的展示原理
在一個彈幕容器View上分成多個彈道,然后將數據放入彈道中,彈幕有3種狀態(準備進入,進入中和飛出屏幕),基于CAAnimationDelegate通過***計算彈幕進入和飛出的時間***反復繪制單個彈幕的View來達到彈幕移動的目的
這里一個比較坑的問題就是設置了半天就是無法將NSTextField中的背景顏色設置成透明的,這里折騰了我幾個小時。
最后通過一個NSTextField的擴展方法創建實例解決了這個問題
extension NSTextField {
/// Return an `NSTextField` configured exactly like one created by dragging a “Label” into a storyboard.
class func newLabel() -> NSTextField {
let label = NSTextField()
label.isEditable = false
label.isSelectable = false
label.textColor = .labelColor
label.backgroundColor = .controlColor
label.drawsBackground = false
label.isBezeled = false
label.alignment = .natural
label.font = NSFont.systemFont(ofSize: NSFont.systemFontSize(for: label.controlSize))
label.lineBreakMode = .byClipping
label.cell?.isScrollable = true
label.cell?.wraps = false
return label
}
}
最終效果
zhiboOnMac 下載地址
一款在Mac上無需flash觀看直播的播放器(支持斗魚和熊貓)
zhiboOnMac歷史版本