雲剪輯-B端在線剪輯⼯具架構設計與演進

騰訊雲音視頻的雲剪輯致力於讓客戶在自己的應用(Web、小程序)中快速集成剪輯能力,同時強大的模板能力能夠極大地提升視頻生產效率。我們在探索B端在線剪輯產品的過程中遇到不少挑戰:如何滿足快速與定製兩種集成場景?如何設計通用、高性能、可靈活拓展的渲染引擎?如何保證雲端視頻合成的效率與質量?LiveVideoStackCon 2022北京站邀請到了成銳林老師爲我們分享他們團隊是如何解答這一系列問題的。

文/成銳林

編輯/LiveVideoStack

大家好,我叫成銳林,是騰訊雲智能創造平臺雲剪輯模塊的負責人。今天和大家分享我在做雲視頻前端剪輯工具過程中一些有趣的事情。今天的分享主要是三個內容:

①第一個是爲什麼會有云剪輯的存在,讓大家瞭解一下B端雲剪輯的應用場景;

②第二個內容是雲剪輯的前後端架構的設計與演進,這部分主要關注在渲染引擎的設計部分以及Web主要相關的應用以及圍繞這樣引擎的前端頁面的設計和服務端的設計;

③第三部分是在線視頻剪輯業務的技術展望。在線視頻剪輯業務的從業者自然會對Chrome 94正式支持的WebCodecs比較感興趣,聊一聊它在視頻製作領域的一些應用限制和展望。

圖片

雲剪輯是騰訊智能創作平臺的一個子模塊。它的誕生的業務背景是方便客戶的用戶們能夠在客戶的平臺上面便捷的生產視頻內容。在視頻內容生產完成後就可以進行例如視頻審覈、視頻直播、視頻分享等一系列的流程。

-01-

雲剪輯應用

圖片

雲剪輯的應用場景,在Web端,我們實現了一個功能強大的在線剪輯工具,讓用戶打開網頁就可以完成視頻剪輯工作,相應的能力也遷移到了微信的小程序上,做成了一個叫微簡小程序的插件,可以讓大家在自家的小程序中快速集成一個剪輯服務。

圖片

同時也支持了功能強大的視頻模板。主要有兩種視頻模板的形式。第一種是通過剪輯項目生成的視頻模板。在剪輯頁面做完一個視頻項目之後,可以把裏面的元素標記爲卡槽,之後就可以在Web端、小程序端或者是服務端通過替換卡槽的內容來批量生成新的視頻。第二種是通過AE插件將AE項目導出爲視頻模板。系統會自動識別AE裏面的卡槽內容,在Web端和服務端替換裏面的卡槽內容來生成一個新的視頻。

圖片

 

這是AE做出來的視頻模板在前端頁面上面的預覽效果。可以在右邊替換裏面的視頻圖片或者文字的內容做成一個新的視頻,同時對外開放的API可以通過API的形式來替換裏面的內容批量生成這個模板。

圖片

近期我們也推出了一個全新的數字人剪輯能力。主要有三個特點。

首先數字人與剪輯軌道做了深度的結合。使用者可以靈活的配置和剪輯數字人的視頻;

第二個特點是它支持了文本驅動和音頻驅動的兩種模式來製作數字人視頻;

第三個特點,它可以快速定製個人專屬形象,可以提供照片或者視頻做成一個專屬的數字人,之後通過文字或者語音的方式驅動它生產更多專屬的個人數字人視頻。

圖片

客戶可以通過兩個方法使用雲剪輯功能。下面來看一下客戶是如何使用我們雲剪輯的。第一種方法是PaaS接入。只要按照騰訊雲官網的起步開發就可以將完整的剪輯功能嵌入到客戶自己的Web應用中。左圖是騰訊會議通過iFrame的方式來接入前端剪輯項目。第二個方法是通過我們的前端組件和服務端的API。右圖是騰訊會議中類似於YouTube裏簡單裁剪的場景,可以讓客戶開完會之後,簡單的對視頻進行重點內容的裁剪生成新的視頻。同時有一個C端的地址。本質上來說,我們的C端地址也是雲剪輯的B端客戶,所有能力與接口和外部客戶是一樣的。騰訊會議使用前端組件和服務端API,搭建了一個簡單剪輯的場景。雲剪輯提供的能力遠不止於此。客戶可以結合自己Web應用的設計風格和業務能力,構建一個完全不一樣的前端剪輯頁面。

圖片

雲剪輯通過三步實現B端化。第一步,創建一個騰訊雲的賬號,開通雲點播。騰訊雲所有媒體資源都是存儲在雲點播上的。第二步,通過API創建一個項目,把雲點播裏面的媒體資源導入到這個項目,再返回一個簽名給前端。第三步,前端通過上一步返回的簽名,初始化iFrame頁面,此時可以立刻打開剪輯項目,並且裏面擁有由服務端注入的媒體資源,並且前端頁面外部可以通過API和iFrame進行交互,可以隨時修改裏面的內容、注入新的元素,讓用戶上傳自己的媒體資源。

-02-

雲剪輯前後端架構的設計與演進

前面介紹了B端雲剪輯的基本能力和應用場景,下面介紹雲剪輯前後端架構的設計與演進。

圖片

雲剪輯的技術要求主要有三個。第一個是要求能夠實時渲染。畫面要能夠實時響應時間軸的更新。第二個要求可以進行比較複雜的交互。包括媒體資源的操作、時間軸的操作以及畫布元素的更新,保證操作的流暢性和數據的穩定性。第三個是多端渲染。上圖展示了Web端、小程序端和服務端三個渲染場景。通過設計來實現多端渲染效果的一致性。

圖片

這是我們渲染引擎的一個整體的架構。首先,騰訊雲的渲染引擎通過軌道數據和時間進行驅動,團隊做很多的工作保證每一幀的內容能夠被精確渲染。在前端很容易寫出一些非阻塞性的代碼。很多在線剪輯工具上面可以看到,當播放或者seek到某一幀,某些元素會延遲出現。由網絡帶來的渲染不確定性是不能接受的。第二,通過遊戲化父子關係分層樹的設計來設計渲染引擎,極大的提升了素材類型的可拓展性。我們把一切軌道元素都稱之爲Clip。騰訊雲也對PAG素材進行了支持,可以很好的與PAG素材特效和模板生態進行互通。

圖片

前面提到,我們的渲染是由數據和時間進行驅動的,這裏主要有四個內容的更新。

首先是timer的更新。數據準備好之後,會由timer驅動整個畫布的更新。畫面的更新分爲兩步,第一步是用戶播放行爲,第二步是用戶在畫布裏實際的操作行爲。每一幀的更新,都需要一定的準備工作,找出時間軸上面當前應該被渲染的元素、不應該被渲染的元素以及根據預測即將要被渲染的元素。其次是緩存的更新。由preloader進行元素預加載,並進緩存的創建和銷燬的管理。

第三個是Clip的更新。Clip是所有元素的基類。例如元素的寬高位置等基礎的屬性拖拽旋轉縮放等操作。最後是用戶行爲的更新。用戶在渲染引擎中可以進行很多操作,例如拖拽視頻貼紙等。我們會把畫面元素的更新同步回軌道數據,保證數據的一致性。

圖片

視頻剪輯項目少不了各種特效的添加。在項目中通過Shader實現了一些視頻的效果,例如特效轉場、蒙版、主場動畫等。

 

這些都是常見的在短視頻裏面的一些效果。如何實現這類效果的開發與複用呢?

圖片

 

這是片源着色器的代碼,這個代碼最核心的部分是一個main函數。函數的返回值是一個顏色值,也就是RGBA。什麼操作都不做就返回0000,那麼右邊的畫面是全黑的。如果右邊畫面的分辨率是720×1280,main函數就會執行720×1280次。第二個是紋理的輸入。在這個程序中輸入兩個圖片紋理,在main函數裏面可以拿到這個紋理像素點映射後的顏色值。什麼都不做就返回圖一的顏色值,那最終的畫面是圖一的完整的畫面。如果返回圖二的顏色值,最終的畫面就是圖二。

這是動畫的邏輯。假如動畫時長是2秒,當前運行時間是一秒,這個百葉窗效果就會處於一個動畫的中間狀態,通過計算讓一部分像素顯示圖1的像素顏色,一部分像素顯示圖2的像素顏色。這裏有個比較意思的電,#iChannel、#iUniform 這種 # 開頭的形式不是標準的 Shader 寫法,會被我們的 VSCode 插件解析成一個標準的入參。

圖片

編寫完之後可以通過調節右下角這個東西進行實時的Shader調試。編寫Shader較爲隨意,可以在編寫特效的時候入參任意的紋理和變量,同時沒有原生的這種import組件複用的模式,不利於程序的設計和複用。騰訊雲通過VSCode插件的方案解決這些問題。在設計渲染引擎的Shader Controller模塊時,對入參的uniform進行嚴格的約束,只使用規定好變量的入參,並且儘可能把可以重用的方法進行封裝。後面的開發者只需要編寫他渲染的部分,不用關心通用的邏輯。通用的uniform就是上面提到 # 開頭的變量。例如進度變量,有了進度變量就可以在 main 函數中得到當前的動畫進度,從而在 main 函數中根據當前進度計算應該展示的動畫樣式。類似的公共入參還有一些標準化的像素座標、UV、畫布比例等,可以通過右下角調節實現實時的預覽。

Import方法是通過合併Shader實現。Shader本身不提供原生的input階段和機制。在工具的編譯階段採用通用方法的拼接。在編寫的階段,開發者只需要編寫main函數裏具體的邏輯,就可以使用其通用的方法,例如計算比例、計算位置、計算取色、計算進度等,在生成代碼的階段,把這部分代碼和後面開發者編寫的渲染部分的代碼進行合併,調試完成之後點擊右上角的導出就可以新生成剪輯器所需要Shader文件,上架新的特效。

圖片

渲染引擎不是孤立的存在,需要配合軌道數據,拼裝軌道數據也離不開編輯器。前端編輯器主要有四個模塊。第一個是已經提到的實時渲染引擎。第二個是素材的模塊。每引入一種類型的素材都會經過仔細的調研與思考。一開始只允許使用Web主要的模式進行渲染,不允許在校園引擎上面疊加環境依賴的東西。第三,剪輯軌道。第四,素材的補充模塊。方便客戶導入通用的AE模板用於製作平臺專屬的貼紙、文字特效等。

圖片

第一版剪輯軌道性能比較差。通過視圖中控,在元素被點擊的時候,把被點擊的數據提交到視圖中控,並生成拖拽的實體,其他所有元素都可以通過監聽視圖中控這個實體的變化來更新。拖拽的過程中,驅動座標更新,尋找允許拼接的區域或者自動對齊的區域,隨後進行影子元素的渲染。當用戶拖拽放鎖時,才進行真正的軌道更新。通過這樣的設計,使軌道操作面有很大的提升。

圖片

操作邏輯離不開媒體元素。目前在線剪輯工具的資源管理主要有兩種模式。一種是純雲端,一種是純本地。一開始使用的是純雲端的模式,所有的資源都圍繞雲點播。純本地模式類似國外的Clipchamp。純本地模式不能跨設備協作,而且存在緩存文件丟失的風險。但純雲端模式用戶得等待視頻上傳和轉碼完成後,才能編輯該視頻。騰訊雲採用本地雲端雙模式支撐剪輯工作流。當一個文件導入時,解析視頻,判斷媒體資源能不能被直接編輯。如果能被直接被編輯,開啓本地剪輯工作流,進行封面圖、雪碧圖的截取,並將視頻導入到剪輯軌道。剪輯器的背後會進行資源的上傳和轉碼工作。等上傳和轉碼完成之後,就進行雲端化的替換。此後,用戶無論是更換設備還是更換用戶,項目始終保持數據穩定和可用。

圖片

綠色的部分是前端的應用場景。騰訊雲的實時渲染引擎,已經很好地支持Web端和小程序端的渲染工作。在服務端導出部分,通過協議和後臺進行對接,約定同一個渲染協議,後臺通過FFmpeg、OpenGL拼接最終的軌道數據。這樣做不僅會導致前後端不一致,而且會消耗大量的後端人力。

圖片

經過驗證,將渲染引擎丟到服務端是可行的。整個程序由渲染引擎的Node進程進行驅動,封裝一個共享內存的Node拓展模塊,用於快速傳遞其中的視頻幀和音頻幀數據,再封裝一個Node編解碼拓展模塊。底層是基於改造後的FFmpeg。渲染引擎在前端應用時,是基於數據和時間進行驅動的。由於採用分層架構的設計,大部分的改造只需要改造preloader加載數據的部分,Clip對外渲染的API是一致的,可以很好的複用一部分渲染的邏輯。

圖片

爲了避免IO損耗,不可避免的要封裝一個共享內存拓展,用於提供給渲染引擎和編解碼模塊進行音視頻幀數據的傳遞。共享內存分爲兩個部分——共享內存寫模塊和共享內存讀模塊。FFmpeg在接收到預加載的事件後,會預取視頻幀放到共享內存。當渲染引擎的某一幀需要某個視頻幀的時候,就會通過handle從共享內存裏面取出這部分的buffer進行渲染。渲染完之後,再把渲染結果放到共享內存供編碼器讀取。

圖片

編解碼模塊的Node拓展。這裏封裝了一個編解碼的Node拓展程序,提供給渲染引擎的主進程進行調用。渲染引擎一開始就會創建一個編碼的子進程,在渲染的過程中,也會根據預加載的結果按需創建解碼子進程。進程間通過共享內存的信息進行傳遞。幀率對齊,多少幀解碼,就會返回相應數據量的音頻幀和視頻幀。渲染引擎就會拿到這一幀的數據進行畫面的渲染和音頻的處理。

圖片

視頻的整體合成調度流程如圖。由於渲染引擎具有幀精確的設計,無論分片多少,始終可以保持渲染的一致性。30秒的視頻,可以分三片,也可以分十片。不管從幾片開始渲染,最終的渲染結果都完全一致。這爲分佈式渲染提供了很好的底層支撐。

我們同時會對軌道數據逐幀去分析,只有真正需要渲染的內容纔會走進渲染的邏輯,否則會送去編碼或者是轉碼。在完成所有的分片任務之後,會進行總分片的轉封裝,完成視頻合成的流程。

圖片

上述流程做完之後就可以上線。如何保證渲染效果的一致性呢?通過編寫所有元素和效果的測試用例集,先生成預期結果的MP4,後續每次迭代都通過SSMI結構相似性來逐幀比對兩個視頻的差異,最終保證合成的視頻跟原本是沒有差別的。但很多時候視頻剪輯效果複雜,想要保證複雜情況下的渲染一致性就要直接把線上的數據作爲測試用例集。每次發佈前,會有影子環境進行抽樣比對,每一次的任務也是通過SSMI結構相似性比對每一幀的差異。只有通過了所有的比對,纔會允許發佈。把容易出錯的case,會彙總到bad case,之後我們也會不斷完善,在迭代過程保證發佈的質量。本地的測試用例集加上發佈前的影子環境,後臺服務發佈是整個中心裏最沒有負擔的,能跑過就證明可以發佈。

-03-

瀏覽器原生編解碼能力助力雲剪輯

圖片

Chrome從86版本開始引入WebCodecs。也是從86版本開始,渲染總會有一些莫名其妙的bug。大概92版本才修復好並穩定下來。WebCodecs意在在瀏覽器提供高效的音視頻編解碼API。在WebCodecs出現之前,已經有VideoRecorder和MSE兩套編解碼相關的API,但他們都有很多限制。WebCodecs的出現,讓音視頻業務有了更大的想象空間。

圖片

純瀏覽器剪輯雖然不涉及服務端,但繞不開視頻轉碼。因爲瀏覽器對視頻格式的支持有限,很多格式不能夠直接在瀏覽器播放。在剪輯之前需要對一些不支持的視頻格式進行轉碼。相信大家都已經聽過,或者在業務中使用過FFmpeg的wasm版本。Wasm的內存限制,導致對於視頻剪輯場景來說比較緊張的。此外最關鍵的一點就是性能問題。就算支持了SIMD,1080p的MOV視頻轉碼也只能夠達到0.3倍數,用戶體驗很差。爲了提升轉碼效率,可以在瀏覽器裏面起十個worker,誰閒就用誰。首先獲取視頻的原信息,分佈式的進行轉碼,最後轉封裝。爲了避免聲音出問題,可以把聲音直接取出來轉封裝。這個模式下可以達到三四倍速轉碼效率,一分鐘的視頻,大概十幾秒就可以裝碼完成。

圖片

WebCodecs與渲染引擎進行結合,效率提升十分明顯。33秒的原片,只需要九秒多的時間就完成解碼渲染編碼的整個流程。做的過程中發現,WebCodecs的API它只負責解碼和編碼,解封裝和封裝需要你自己搞定的。Video frame和Audio data都是很輕量級的對象,但持有很重的內存引用。在編碼的時候,如果傳入不同的寬高,編碼器會自動進行縮放,這個時候可以把一些縮放的邏輯放到編碼器,這樣可以減少渲染的概率,提升性能。

圖片

WebCodecs有着出色的性能。但完全使用它代替瀏覽器端的FFmpeg還有比較大的差距。直到21年的年底,它的音頻編碼格式還只是Opus格式,還不能被MAC、 WINDOWS的原生播放器支持。雖然可以用FFmpeg的wasm版本把它的音頻再轉成AEC,但這就失去了純瀏覽器製作視頻的快樂。22年5月份終於定下 AAC 編碼協議。H265的支持呼聲在論壇一直很高,Chrome在104的版本終於支持了H265的硬解。與此同時,WebCodecs也支持了H265的解碼。解封裝和封裝的整合,主流方案是通過FFmpeg的wasm版本進行支持。或者通過MP4 box純手動來拼接。WebCodecs開發者被逼無奈,做解封裝器 wasm 的開發。

編碼的部分也有不少可以優化的地方。配置緩衝區的大小,是得開發者能夠根據瀏覽器的性能來進行一些精細化的控制。

得益於我們渲染引擎的構建方式,以及分層設計,可以很快地將loader部分替換成WebCodecs。如果音視頻的解碼就能夠像在服務端,以幀對齊的方式進行返回,對於很多開發者來說是非常便利。解碼和編碼的配置項可以讓開發者更方便地使用WebCodecs。

今天的分享就到這裏,謝謝大家!


圖片

LiveVideoStackCon 2023上海講師招募中

LiveVideoStackCon是每個人的舞臺,如果你在團隊、公司中獨當一面,在某一領域或技術擁有多年實踐,並熱衷於技術交流,歡迎申請成爲LiveVideoStackCon的講師。請提交演講內容至郵箱:[email protected]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章