以前咱們解析過不少社交直播App中不一樣場景的開發,好比在線K歌、小程序直播、多人視頻聊天、AR等。ios
咱們最近在知乎看到了一個問題「爲何k歌軟件始終沒有開發出實時合唱功能?」,咱們只在知乎作了簡要解讀。在這裏咱們詳細來解析其中難點,以及實現的方式。算法
如今大部分K歌應用中,都有「合唱」功能。用戶點歌,而後開啓合唱功能,本身一我的根據伴奏演唱,完成後點擊「上傳」,剛纔錄下的歌聲就變成了帶有一人歌聲的伴奏。其它用戶能夠選擇這個伴奏唱歌,錄製完成後,間接的完成了合唱。簡單來說,就是作了兩次「錄製-上傳」的操做。小程序
這種「錄製合唱」,並非咱們要作的「實時合唱」。服務器
固然不能否認,從技術角度講,錄製合唱有其優勢:網絡
錄製合唱的效果也徹底取決於用戶自身。其缺憾也顯而易見,就是用戶並無「合唱」的體驗,仍然是一我的在唱歌。併發
而咱們要作的「實時合唱」的體驗並不是如此。實時合唱的流程體驗以下:post
在實時合唱的場景下,用戶再也不是一我的唱,而是在本身演唱的同時,能夠聽到好友合唱的聲音。實時合唱能讓用戶像得到線下同樣的體驗,極大的提高沉浸感。性能
既然實時合唱更能給用戶帶來參與感,爲何卻不常見呢?與重複「錄製-上傳」的合唱不一樣,實時合唱的體驗給技術提出了更高的要求,主要包含兩方面。優化
這裏的同步指的是兩個歌手的歌聲與伴奏三者之間的同步。咱們先假設咱們的唱歌的兩位用戶都是專業級的,踩不許節奏的問題徹底不存在。如上述場景描述,因爲伴奏是同時發送給兩個用戶,那麼關鍵就在於二者的歌聲是否能同步。影響合唱同步的主要因素就是延時。編碼
那麼延時會帶來多大的影響呢?爲了方便你們理解,咱們能夠以一個非音樂科班生的角度簡單計算一下。以歌曲《稻香》爲例,它的鋼琴樂譜是4/4拍,標準樂曲速度爲80拍/分鐘。副歌部分大約每一個音樂小節唱8到12個字,且主要以八分音符和十六分音符組成,基本上每一個音符對應歌詞中的一個字。粗略計算的話,大約200 - 300ms左右唱出一個字。
不考慮伴奏的狀況下,假設上圖中的A和B之間的端到端延時爲100ms。從聲音傳輸流程上來講:
A先唱,B聽到A的歌聲。此時產生100ms延時;
B在聽到A的歌聲後開始加入合唱,歌聲傳到A端。此時又產生100ms延時;
那麼 A聽到B的歌聲永遠延時200ms。根據以前唱每一個字所用時間的計算,聽感上會至少慢半個字,是錯位的。
若是要考慮伴奏的傳輸,以及伴奏與歌聲的混音,狀況將更加複雜。因此,實時合唱場景下的延時越低越好。通常端到端延時只要低於150ms,聽者是感知不到的。因此唱《稻香》這種速度的歌,延時低於80ms能夠完美合唱,演唱者的體驗也是好的。若是唱更快速、歌詞更密集的歌,延時要求更低,不然合唱時兩人永遠也對不許拍子,演唱者的體驗也很是糟糕。
那麼,如何下降延時呢?這個場景下的延時包括兩部分:設備端的延時和端到端的延時,咱們須要針對不一樣階段的延時,來分析如何下降延時。
音頻在採集端、播放端的延時
這張圖咱們曾在《詳解音視頻直播中的低延時》中分享過。在這裏,音頻=歌聲,或音頻=歌聲+伴奏。這取決於你如何傳輸歌聲與伴奏,咱們在講解解決之道時會詳細說明。
設備端上的延時包括採集端的採集、前處理、編碼,播放端的接收、解碼、後處理過程產生的延時,以及兩端在編碼後和解碼前產生端網絡延時。
端上的延時主要與硬件性能、採用的編解碼算法、音視頻數據量相關,設備端上的延時可達到 30~200ms,甚至更高。
音頻在設備端上的延時還能夠細分爲如下幾點:
另外,合唱場景一般會爲用戶提供各類KTV音效,即人聲在編碼傳輸前會增長一步前處理,這還會加大音頻在端上的延時。
若想下降音頻在端上的延時,就須要針對不一樣機型進行編解碼算法的優化,以下降音頻採集、編解碼、音頻處理帶來的延時。端上延時還與設備性能、系統緊密相關,若是歌手中有一方的設備性能較差,也會影響合唱效果。
端到服務器之間的延時
除了端上的延時,音頻數據在端到服務器、服務器到服務器之間的傳輸過程也會產生較大延時,這也是阻礙「實時合唱」功能落地的重要因素。
影響採集端與服務器、服務器與播放端的延時的有如下主幾個因素:客戶端同服務間的物理距離、客戶端和服務器的網絡運營商、終端網絡的網速、負載和網絡類型等。若是服務器就近部署在服務區域、服務器與客戶端的網絡運營商一致時,影響上下行網絡延時的主要因素就是終端網絡的負載和網絡類型。通常來講,無線網絡環境下的傳輸延時波動較大,傳輸延時一般在 10~100ms不定。而有線寬帶網絡下,同城的傳輸延時能較穩定的低至 5ms~10ms。可是在國內有不少中小運營商,以及一些交叉的網絡環境、跨國傳輸,那麼延時會更高。
服務器間的延時
在此咱們要要考慮兩種狀況,第一種,兩端都鏈接着同一個邊緣節點,那麼做爲最優路徑,數據直接經過邊緣節點進行轉發至播放端;第二種,採集端與播放端並不在同一個邊緣節點覆蓋範圍內,那麼數據會經由「靠近」採集端的邊緣節點傳輸至主幹網絡,而後再發送至「靠近」播放端的邊緣節點,但這時服務器之間的傳輸、排隊還會產生延時。
在實時合唱的場景中,要解決網絡不佳、網絡抖動,須要在採集設備端、服務器、播放端增設緩衝策略。一旦觸發緩衝策略就會產生延時。若是卡頓狀況多,延時會慢慢積累。要解決卡頓、積累延時,就須要優化整個網絡情況。
唱歌的人都有一個共同的心理需求,就是但願別人誇本身唱得好聽。音質在合唱場景下就顯得尤其重要了。而影響實時合唱音質的因素主要包括:音頻採樣率、碼率、延時。
採樣率:是每秒從連續信號中提取並組成離散信號的採樣個數。採樣率越高,音頻聽起來越接近真實聲音。
碼率:它是指通過編碼(壓縮)後的音頻數據每秒鐘傳輸所表示的數據量(比特)。碼率越高,意味着每一個採樣的信息量就越大,對這個採樣的描述就越精確,音質越好。
假設網絡狀態穩定不變,那麼採樣率越高、碼率越高,音質就越好,可是相應單個採樣信息量就越大,傳輸時間可能會相對更長。也就是說,高音質也可能會影響延時。
以前咱們提到,因解決方案的不一樣,「音頻」有這不一樣的含義,這與你的實現邏輯有關。
1.音頻=歌聲+伴奏
在採集端,咱們傳輸的音頻若是是包括歌聲與伴奏。那麼就意味着是這樣的邏輯,以下圖。
在這種傳輸方式下,若是要保證 A 能聽到合唱效果,會有兩段「端到端延時」,即第二、3步產生的。因爲B聽到的是A的歌聲與伴奏,因此該方案能保證 B 的體驗。但因爲伴奏傳輸給 B,B 的歌聲又須要再傳輸回到 A,A 聽到的伴奏與B的聲音其實之間有很大延時。若是按照上文的延時推斷,你須要付出更多的努力,才能讓端到端的延時下降到歌手A能接受的程度。
2.音頻=歌聲
在這裏,並非說不要伴奏了。爲了解決伴奏、歌聲之間的延時問題,咱們還有一種方法,就是經過雲端將伴奏同時傳輸給A和B,那麼基本能夠保證二者能在同一秒聽到同一個音符。接下來要解決的就只是歌聲的傳輸了。基本實現邏輯以下,也是咱們本身的實現方式:
這種實現邏輯的好處在於,A、B幾乎同時聽到伴奏,同時演唱,二者能夠實時聽到對方的聲音。要解決的問題就是下降各自歌聲傳輸到對方的這段端到端延時了。相對來說,更加簡單。
如上文所說,咱們要作的就是優化編解碼算法,並對各個機型進行適配。同時,優化網絡傳輸策略,增長節點部署等。
你們能夠嘗試本身開發,也能夠在聲網開發者中心閱讀咱們詳細開發文檔,獲取咱們在 Github 開放的 demo 源碼。