聲網管浩森:元宇宙派對場景的最佳實踐

聲網發表於2022-12-22

前言

元宇宙場景在這兩年逐漸興起,成為很多社交、娛樂產品關注的新場景。而且,目前有不少產品已經落地。本文整理自聲網解決方案架構師管浩森在 RTE 2022 大會的演講。他是元宇宙方向的專項解決方案負責人。他基於協助客戶落地元宇宙場景的經驗,以元宇宙派對為例,分享了該場景的實踐經驗。

本文內容基於演講內容進行整理,為方便閱讀略有刪改。


圖片

大家好!我叫管浩森,是一名開發者也是一名創業者。我在連續創業過程中對 toC 產品和功能,包括架構設計方面積累了豐富的經驗和看法。2021 年我加入了聲網,目前擔任元宇宙方向專項解決方案的負責人,目前致力於為客戶提供市場上更有優勢整體解決方案。

今天我們來講一個比較輕鬆的話題,“如何在元宇宙裡建立一場派對”。我會以元宇宙派對場景作為基礎,介紹從前到後、從裡到外整套的解決方案。

圖片

我們先看一下元宇宙場景目前的發展。首先,我們看一下近年來社交場景形態的變更。從“線上”到“在場”,消費者的社交形態其實是不斷升級的:從 2011 年移動端及時通訊的興起,隨著智慧手機的普及,手機 QQ 等產品帶來移動文字即時通訊,也就是 IM,包括離線留言的功能,類似於 QQ 空間。當時它的社交方式、社交屬性實際上是透過表情包+文字的方式進行即時通訊。

時間來到 2016 年,全屏短影片開始爆發。隨著抖音在 2016 年的釋出和快手的推廣,人們逐漸習慣了透過分享和評論去觀看 UGC 的內容,也就是使用者自己在平臺上釋出的影片產品。對於此類產品,社交形態主要透過錄制的影片+錄製的聲音和使用者的評論來交流。

2018 年,直播場景全面爆發。遊戲風口當年正熱,短影片、直播逐漸成熟,直播帶貨在直播行業中全面興起,對於直播而言此時交流方式變成實時的影像+實時的聲音。

2021 年,Facebook 在年底改名為 Meta,像一個重磅炸彈一樣為整個行業炸出了一條路,電影、VR、遊戲在這一年全面開花,讓元宇宙概念再次火熱起來。在元宇宙元年,人們之間的交流方式已經由實時的影像+實時的聲音變成了實時渲染的場景+實時的音影片。

對於消費者在元宇宙的瞭解這一步來看,我們找到了以下的資料。調查顯示,我們對元宇宙瞭解程度普遍較高,因為元宇宙一詞近年來接連被提及,特別是疫情情況下對於新型社交型別的強需求,Facebook 的改名、微軟收購動視暴雪、百度推出了希攘,這一系列的資訊讓網民對於元宇宙的概念已經有了一個基本的認知環境。經資料調查,所有受訪的網友都聽過元宇宙的概念,其中 61.4% 的網友對於元宇宙比較熟悉,15.9% 更是非常瞭解,對於元宇宙消費者有什麼期待呢?

圖片

資料展示,網友更多期待元宇宙社交的場景。國內泛娛樂快速發展和網際網路浪潮雙重推動下,國內的網友,特別是 Z 時代年輕人,對於新興事物接受程度和嘗試意願都非常高。根據資料調查顯示,消費者對於元宇宙的期待還優先在泛娛樂場景,特別是虛擬社交領域超過 60% 網友比較願意嘗試元宇宙型別的社交模式。

圖片

既然如此,我們該怎麼樣搭建出來一個社交元宇宙場景呢?接下來跟著我一起開一個元宇宙的派對。

01 建立元宇宙:萬物生長

首先我們先看建立元宇宙第一塊萬物生長,所謂萬物生長即我們要在元宇宙整個場景內建立山川河流、世間萬物,如何建立這是第一道難題。

圖片

首先我們講一下對於模型的構建。模型構建現在市場上已經有了一套成熟的流程,透過一系列的步驟,比如說角色設計、中模、高模、低模、烘焙貼圖、骨骼繫結等操作,便可以完整地建立一套元宇宙場景下的人物模型。當然也有整個場景的虛擬,現在還有很多的模型是可以直接購買使用的。

此外可以透過引擎和底層 API,以捏臉的形式做業務層的換裝,類似於蘋果的 Memoji,在建立標準模型基礎上可以提供給真正 C 端使用者更個性化人物定製和形象定製,聲網行業會逐步完善地推出 MetaLive 產品包,讓大家可以用 Native 的開發方式實現換裝的功能。

第二塊,我們現在有了一套虛擬場景,我們怎麼才能讓它動起來?對於動起來最重要的是模型間互動的指令碼製作。目前模型互動指令碼製作有兩個方案可以選擇,一個是使用現成渲染引擎,比如 Unity、Arnold 第三方渲染引擎,也可以透過 OpenGL、Direct3D 底層 API 自己去控制底層的硬體和渲染整個場景。聲網在這方面會提供 Metachat 等合產品包,來幫助大家實現整個場景的渲染部分邏輯,讓客戶更有精力地關心業務部分的邏輯。因為我們知道不管是元宇宙還是 2D 社交產品,它的派對或者社交本質還是人本身。

02 建立元宇宙:推杯換盞

我們怎麼才能在元宇宙的場景中互相交流,在排隊中推杯換盞?下面跟我們一起走進一個場景內,看看整個元宇宙是如何活起來的。

首先,我們看一下信令控制,包括所謂場景控制,現在建立了 3D 虛擬世界,我們該如何進行操作呢?元宇宙內會有大量的資訊、信令互動,比如說我的位置座標、我給誰送的禮物、我的動作什麼樣,隨著房間內人物越來越多,服務端對於這類資訊處理的壓力也會越來越大,對此,基於給多個客戶的打磨,聲網有以下的經驗和一些推薦的思路,分享給大家。

第一,是將不同的資料分為不同的頻次,比如我現在要同步每個人位置資訊座標,位置資訊同步很有可能是每秒 10 次甚至每秒 30 次的幀率,如此龐大資料對於伺服器儲存是無意義的,它只是一個可丟失、只需要保序的信令。對這類信令我們要和低頻次的資料進行分離,比如說我去給誰送禮物,這屬於一個低頻的資料,不同的資料透過不同的通道進行同步,這樣可以有效降低伺服器的壓力。有一些高頻的資料沒有必要儲存,有些低頻的資料包括重要資訊是適合儲存的。

第二,將同步資料按照重要型別劃分。我們把它分為了關鍵幀和非關鍵幀兩類。關鍵幀一般指事件的同步,比如開閉麥的狀態、房間內的屬性。就比如我現在在使用電腦,別人沒有辦法隨意把這臺電腦給搶走。非關鍵幀指的什麼?類似於我剛剛說對於整個場景內位置資訊的變動,包括動作細節的模型、面部結構化資料,整個臉在此刻動的結構化資訊,這個結構化資訊是沒有必要每一幀都完整傳輸,它和影片幀是類似的情況。對於此類資訊需要保證快速且保證時序,但不一定能夠保證必須到達。對於此類資料我們把它劃分為關鍵幀和非關鍵幀進行傳輸,關鍵幀更多需要記錄,而非關鍵幀更多需要保證速度。

第三,是統一的思路,對於訊息風暴的規避。如果頻道內的資訊過多很有可能造成服務中整體壓力包括客戶端的回撥壓力。對此,一般業內會這樣處理操作,比如 A 和 B 兩個人,他們之間同步資訊不是A廣播自己所有的資訊到頻道內,而是A單獨發給伺服器,B 也單獨發給伺服器,伺服器整合了之後透過每秒 10 次或者 20 次的頻率統一下發給各個端,這樣每個端收到的訊息不再是所有人的資訊疊加,而是服務端整理好整合的資訊,這樣可以規避大量的資料仿造。

其中,第二部分我們需要明確 RTM(Real-Time Messaging)幾個功能模組,我簡單介紹一下,因為接下來整個場景我會主要以聲網 RTM 功能來作為型別的串聯,大家可以類比把聲網 RTM 替換成大家現有使用的產品。

聲網 RTM 主要的功能模組有這麼幾個:

  • 頻道資訊,是作為廣播性質的訊息,常常作為非關鍵幀的廣播。
  • 頻道屬性,頻道屬性是長期儲存的,大家可以以自己業務伺服器來替代,頻道屬性每一次變更後,所有人都會收到頻道屬性變更資訊。
  • 使用者屬性,使用者屬性是各個使用者之間不會預設的訂閱,需要訂閱某個人之後,某個人的使用者屬性變更我才會收到變更資訊。

接下來,我主要會透過以下三個互動場景作為重點,來給大家介紹一下在元宇宙場景中這些場景的注意事項和實踐的方式。

第一就是“你在哪兒”。我們現在進到了一個場景內,我們怎麼才能移動?我會以人物移動為例,講解關鍵幀和非關鍵幀的同步策略,此時關鍵幀和非關鍵幀同步定義偏向於是否進行儲存。

第二就是“打招呼”。我能移動了之後,我身體各個動作該怎麼處理,我見到了同事之後、見到了同學之後,如何才能以一個方式告知讓我看到我在和他打招呼。

第三是元宇宙場景內經常被忽略一個細節,就是“先來後到”,衝突的處理和鎖的處理,對於此我會以搶椅子場景為例介紹鎖的概念和其應用。

接下來我們代入一個場景(如下圖所述):

圖片

對於此方案最主要作為目標位置移動同步資訊,對於座標位置同步我們一般分為兩大類,一類是透過點選螢幕或者按鈕進行操作,類似於下圖展示的遊戲,大家很多人玩過《夢幻西遊》,對於這類遊戲大家可以理解為我是點選某個位置之後,人物透過自動選址走到那個位置。

圖片

對於這種情況,我們知道開始位置資訊和結束位置資訊。此時,開始位置點和結束座標位置點作為兩個關鍵幀會傳輸給各個端,各個端收到了關鍵幀之後,就不可以透過每個端一致選址策略,來實現每個端走的動作是一樣的,這樣實現了偽同步。我需要同步的資訊量很小,因為不需要同步每一個位置幀,我只需要同步兩個關鍵幀即可。

當然,這個策略也會有一些弊端。我只適用於“透過點選螢幕或按鈕操作”,即透過指令開始和結束位置的操作,而透過輪盤或者手柄方式進行自由移動的場景,則需要考慮下面這種策略。

圖片

另一類則是透過輪盤或者外設的方式,自由控制角色進行走動,此類方式沒有固定的結束位置,無法透過關鍵幀的方式進行廣播,需要一個信令通道進行非關鍵幀(位置座標)的同步,在使用者移動時,快速(例如每秒 10 次)向頻道內傳送訊息,收到廣播訊息的使用者拿到對方座標位置後做位置渲染。非關鍵幀資訊可以不被伺服器記錄。

同時,為了伺服器可以定時儲存角色當前位置,可以定義例如每5秒作為一個關鍵幀儲存在頻道屬性內/伺服器內,此時若角色掉線,則重連後可以渲染回到上一次的關鍵幀位置。

那麼這兩種在元宇宙中的操作,需要怎麼實現呢?下面以 RTM 使用為例,給大家介紹一下整個使用流程。

圖片

1.如果透過指令開始和結束位置需要三步。第一加入 RTM 房間,透過獲取到開始和結束後的位置資訊,更新 RTM 的房間屬性,房間屬性變動之後同步廣播給房間內所有人,所有人拿到了遠端狀態資訊,可以透過本地處理和選址渲染出來位置變動人的移動方式,這樣每個人就可以看到對方在移動了。

2.透過自由移動位置座標方式去進行移動的話該怎麼操作呢?右邊部分各端加入 RTM 和 RTC 房間內,使用者移動的時候可以透過 RTC 的 data storage 通道或者說 RTC 頻道資訊通道傳送關鍵幀,此關鍵幀可以每秒 10 次或者每秒 25 次,和幀率保持一致情況,向頻道內傳送我自己當前的位置訊息。遠端的客戶收到了我的頻道訊息,我的非關鍵幀之後,透過自己的渲染,渲染出來我當前每一幀的位置資訊,然後就可以渲染出來我的座標了。此外,我們還需要定義一個定時器,比如說5秒一次,把當前狀態同步到房間屬性或者伺服器裡面做儲存,這樣為了完善元宇宙內離線重連業務層服務體驗的問題。

圖片

那麼接下來,我們要解決如何在元宇宙場景中 Say Hi 的問題。

大家可以知道我希望和他打招呼,為什麼此時我動不了?因為打招呼本質是信令的出發。我作為 A,我的舍友作為 B,A 和 B 打招呼,信令是 A 把打招呼動作指令傳送給 B,同時 A 和 B 同時渲染打招呼的動作,此時 A 和 B 可以同時看到我和他在招手。我們對這些指令有一些定義,比如說我們希望被某些人看到,這樣就可以透過剛剛說使用者屬性變更,大家還記得使用者屬性和頻道屬性之間區別是什麼嗎?使用者屬性是預設不被所有人訂閱的,只有訂閱自己的人才能看到自己的變動,我打招呼只有想看我的人,或者離我足夠近的人才可以渲染出來我打招呼的動作,離的遠的人不用渲染此動作了,這樣就會極大減少客戶端的渲染壓力。

或者說我希望只讓部分人可以看到打招呼的資訊,此時我就可以透過點對點的訊息,例如 IM 或者伺服器的 socket,讓部分人主動渲染出來我打招呼的資訊。

此時有一個比較重要的點,我打招呼並不是我主動渲染之後別人就可以看到,而是我透過信令讓別人知道了之後,各個端渲染遠端人打招呼資訊,這樣才是一個正確的方式。當然也可以透過業務層的限制,我給所有人去廣播,但是某些人是不會去渲染的,這樣就需要業務層伺服器去做許可權的控制或者陣列的定義。

圖片

流程大家可以看一下右邊,各端先加入 RTM 房間,角色A觸發了打招呼的動作,觸發是讓我自己看到我自己在和對方打招呼。我打招呼的同時透過屬性的變更或者頻道的訊息,廣播給房間內的其他人,其他人收到了之後大家也渲染出來我和其他人招收的動作,此時就完成了打招呼的動作,包括之後一系列的碰杯、擁抱、送花都是透過此類方式可以去執行。

圖片

對於此類資訊我們有一個先來後到的概念,如何處理衝突實際上是元宇宙場景內一個比較容易忽略,但是非常重要的一環。

這樣的衝突聲網將椅子的佔有權定義為一把“鎖”,這把“鎖”的佔有權是隻能屬於一個人。我如何才能處理整個衝突的過程呢?比如我是 A 角色,另外一個兄弟是 B 角色,我們兩個同時想坐在椅子上,需要先嚐試獲取此“鎖”的佔有權,RTM 服務端會按照到達的順序去判斷,或者我們在業務伺服器一層去處理優先權,比如我是 VIP,我肯定要比對方先佔有此座,除去這個以外是論時間到達先後。RTM 會自動處理分散式的衝突,誰先到達了之後,會返回一個“請求鎖成功”的回撥,對方會反饋一個失敗的回撥,收到此回撥之後,我們才會處理坐下動作指令碼。坐下動作指令碼和打招呼動作指令碼實現原理是一致的。

這一點其中比較重要的是,我需要去獲取“鎖”成功的回撥事件之後才會觸發動畫指令碼,而不是我點選坐下按鈕之後就會觸發,這樣就會出現我在剛才場景裡描述,我們兩個同時都坐在了椅子上,並且串模了。這樣 B 角色收到自己無比坐下或者獲取鎖失敗的操作之後,B 就會透過客戶端彈窗告知此座位已經有人了,你無法坐下了。同時,聲網把椅子佔有狀態作為房間屬性儲存在服務端或者儲存在房間資訊內,這樣每當其他人靠近椅子的時候,會感知到這個椅子上已經有人了,這樣就不會再出現坐下的按鈕去重複進行“鎖”的獲取。

圖片

整個流程大家可以看右邊部分,第一塊就是加入 RTM 房間內,角色 A 去申請椅子佔有“鎖”,如果返回失敗的話進行彈窗提示沒有此類資訊,如果返回成功的話會觸發坐下椅子的操作。

坐下椅子同時回到打招呼整個流程內,我坐下的動作觸發了之後,會透過一個頻道訊息傳送給各個端,各個端也會渲染坐下的指令,這樣大家都可以看到我坐在這把椅子上。角色 A 站起來了之後,會透過 release 的方法釋放對椅子鎖的佔用,這樣其他人在進來的時候就可以再次坐在這把椅子上了,這個就是一個衝突的處理。

圖片

我該怎麼在元宇宙場景裡像真實世界一樣交流,聲音它都去哪兒了?我們來進入第三個章節,建立元宇宙的空氣和水。

03 建立元宇宙:空氣和水

實時音影片的引入會使得元宇宙的社交場景更具有沉浸感。角色間語音的交流,場景內背景音樂的播放、和好友一起邊看電視邊聊天、甚至透過空間音訊判斷對方的位置或者距離,這都會讓元宇宙體驗更上一個臺階,實時音影片在元宇宙場景中就好像空氣和水一樣,大家注意到它,但它卻是無處不在。

我會主要把實時音影片劃分三個模組進行派對內場景的分析:

  • 第一塊會以一起看電視為例介紹如何在元宇宙房間內實現一起看、一起聽或者說 BGM 播放同步功能。
  • 第二塊我會以一個遊戲的方式,我閉著眼捉迷藏,如何透過聲音的方向去判斷其他人的位置,空間音訊的引入其實就可以像真實世界一樣,帶給元宇宙更深層次的沉浸感。
  • 第三我會以悄悄話或者心裡話為主,介紹如何透過聲網最新 SDK 多頻道方式進行不同場景融合和交流私密性的保證。

圖片

接下來我們進入場景內,一起看或者一起聽實際上為的就是保證每個人看到時間點是同步的概念,這樣大家可以保證同時感受到相同的氣氛,甚至可以實現合唱的場景。

如何才能透過聲網 RTC 功能同步一起看或者一起聽的時間進度?聲網給出了以下三種方案:

1、透過【播放者】MPK 本地播放後推流到頻道內

第一是透過播放者的概念,把某一個客戶端播放的影片推到頻道內。聲網為一起看一起聽推出了適配 MPK(Media Player Kit)媒體播放器。MPK 媒體播放器不僅可以播放音訊影片檔案,包括 CDN 媒體流,甚至可以將本地播放的影片以 RTC 影片流的形式推到聲網頻道內。此時大家透過 RTC 強同步進行時間的同步,而不需要去考慮時間戳的對齊,這樣是較好的方式。但是此方案需要有一個具備推流許可權的客戶端作為發起者,自己播放的影片將會推到頻道內,具體流程大家可以看下圖。

圖片

業務端首先發起我要播放的請求,業務端伺服器告知你可以播放之後,客戶端 APP去播放此影片,並且把播放的影片流推到聲網大網內,聲網再透過轉發,轉發給各個不同播放端進行影片共同播放,這是第一種方式。

2、透過【發起者】同步進度,各端自己播放

第二種方式可以透過發起者的同步進度,各個端自己透過 RTM 方式播放此。方案就不需要透過 RTC 作為強同步的標準,而是透過聲網提供 data stream 通道。你可以用這個通道將某一個發起者作為時間戳的主體,將發起者當前播放時間進度同步到頻道內,各個端基於播放者或者發起者角色時間播放進度來拉齊自己當前的進度。

圖片

與第一種方式的不同,各端拿到進度之後進行自己播放器時間戳對齊。這種會有一個問題。每一次傳輸的物理延遲是不一樣的,第一次傳送 data stream,我和 A 和 B 物理延遲就是鏈路延遲是 50 毫秒,下一次是 70 毫秒,這樣相差 20 毫秒對於本身時間戳進度感知不強,但如果對齊會有卡頓的感覺。所以要引入預值緩衝區的概念。如果大於預值緩衝區的預值(如 100 毫秒),比如說這一次 50 毫秒,下一次 70 毫秒,下一次變成 40 毫秒,都在預值波動內,這樣大家可以透過在播放內,不用對齊。超過了此進度的話,比如當前在 4 分 10 秒,我剛進來的人是 0 分 0 秒,4 分 10 秒減 0 分 0 秒肯定大於 100 毫秒,這樣才可以進行對齊,把 0 分 0 秒那個人進度拉齊到 4 分 10 秒。具體情況大家可以看上圖。其實和第一種方案是一致的,只不過每個端自己去播放,透過 MPK 去播放影片。

3、透過 CloudPlayer 播放後推流到頻道內

前兩種方案大家可以發現一個弊端,都需要透過發起者的概念去維護整個進度或者整個影片,如果發起者的網路條件不太好或者效能達不到的話,會影響整個房間內所有人的影片播放體驗。

圖片

對於此聲網提出了 cloud player 的概念,業務端可以透過 RESTful API 呼叫,服務端無需加入某個頻道內,就可以去開啟一個 worker,把需要播放的資料推到聲網的大網。聲網大網透過影片流的形式,保證同步,並推到各個播放客戶端。此方案就可以規避掉房主或者發起者的概念,所有人可以任意進出此房間,但是我在房間內螢幕上播放是一直進行的。

以上三種方案都可以解決一起看的功能。

圖片

對於此,聲網引入了一個空間音訊的概念,空間音訊概念可以讓沉浸感更進一步。透過 RTC 音訊、聲音辨別出使用者的方位,可以為元宇宙場景提供更好的體驗。聲網提供空間音訊可以讓使用者透過音訊感知到說話人的方向、位置高低、距離遠近的變化,同時還模擬了空氣的衰減,音障,比如我和你隔了一道牆,你說話和沒有隔一道牆說話是不一致的一個體驗。對此,其實可以豐富真實環境的變化,包括帶給元宇宙場景內的使用者更真實的體驗和更豐富的玩法。

聲網目前空間音訊還是關注 RTC 音影片本身的變化,比如人說話的聲音,而對於場景內本身的腳步聲、關門聲、環境聲效需要業務層在渲染引擎層面、指令碼層面自己去處理。

對於空間音訊的流程如下:

1.加入 RTC 頻道【頻道場景為直播,身份為主播】

2.muteAllRemoteAudioStreams(true)【預設不收流】

3.建立並初始化空間音訊物件並設定空間音效的引數

4.先後呼叫 updateSelfPosition 和 updateRemotePosition 來設定遠端和自己的位置

5.clearRemotePositions取消空間音訊效果,destroy 銷燬AgoraLocalSpatialAudioKit 物件

首先需要加入 RTC 頻道,同時把所有人遠端的人關閉收流,相當於把開關音訊許可權交由空間音訊處理。

第三塊是建立空間音訊的物件,並且設定空間音訊的引數。這時候我們可以呼叫自己在整個世界座標內的位置座標和設定遠端的位置座標,在本地渲染出來我和他的距離、我和他的相對方向、我和他的高低,這樣就可以在本地去渲染出來每個人的位置座標和空間音訊的效果。

聲網提供此方案不會影響遠端傳輸,所以每個客戶端都可以自由定義每個音訊的具體位置。

圖片

對於在元宇宙中說悄悄話,或者說小範圍交流的場景需求,我們引入了多頻道的概念。聲網新版的 SDK 允許使用者透過自由操作多個頻道來實現多頻道的推流和拉流。比如在當前場景內,我們可以透過三個頻道來實現整個元宇宙派對的概念,首先樂隊演奏可以拎出來單獨做一個頻道,所有人都可以訂閱,但是所有人在此頻道內不發流,只有樂隊可以發流。這樣大家可以同時聽到同一首背景音樂,有共情的感覺。如果大家希望也可以把樂隊當做空間音訊去處理。

第二個頻道就是在大廳場景內,所有人都可以聽到嘈雜空間音訊的聲音,比如說離我 10 米距離某個小兄弟說話聲音會比較小,離我比較近的人說話聲音比較大,讓場景更貼近現實。

第三塊是剛才說透過卡座或者小分隊的概念,可以作為單獨頻道,此頻道只允許某些使用者可以被加入,如果此頻道內的使用者說話不會被大廳內其他使用者聽到,這樣既可以保護到隱私也可以同時聽到整個大廳內的音訊傳送,既可以體驗到整個場景自由度也可以保護自己的隱私,就類似於頻道的卡座,甚至看球的時候 VIP 專座一樣。

除此之外,使用者甚至可以將頻道與一起看等結合,在某個頻道內單獨去觀看某個內容,這樣都交由開發者自己去處理。

以上就是我們搭建一個元宇宙派對場景的實現過程與原理。如果大家感興趣,希望檢視元宇宙相關的聲網解決方案,請點選此連結

相關文章