摘要:組件提供了一系列的操作接口以方便用戶對彈幕的相關特性進行定制。對于這種類型的圖像,我們可以使用色鍵的方式進行摳圖生成蒙版。其中,用于更新蒙版的接口為。
導讀:本文內容是筆者最近實現的 web 端彈幕組件—— Barrage UI 的一個延伸。在閱讀本文的實例和相關代碼之前,不妨先瀏覽項目文檔,對組件的使用方式和相關接口進行了解。
各位童鞋如果經常上 B 站(bilibili.com) ,應該對 蒙版彈幕 這個概念并不陌生。
蒙版彈幕 是由知名彈幕視頻網站 bilibili 于 2018 年中推出的一種彈幕渲染效果,可以有效減少彈幕文字對視頻主體信息的干擾。
關于 B 站蒙版彈幕的實現原理,其實網上已經有很多細致的討論和研究。個人總結了一下,大致要點如下:
基于用戶數據和一些機器學習的相關應用,可以提煉出視頻的關鍵主體
服務端預先對視頻進行處理,并生成相應的蒙版數據
客戶端播放視頻時,實時地加載對應資源
通過一些前端的技術手段,實現彈幕的蒙版處理
客戶端方面,由于 B 站彈幕是基于 div+css 的實現,因而采用了 svg 格式來傳輸矢量蒙版(至少目前是這樣),通過 CSS 遮罩的方式實現渲染。
逼乎上有一篇關于這個方案的討論,感興趣的童鞋可以移步 這里 進行了解。
Barrage UIBarrage UI 是個人最近實現的一個前端彈幕組件,主要用于在前端頁面中掛載彈幕動畫。
組件提供了一系列的操作接口以方便用戶對彈幕的相關特性進行定制。你也可以在渲染層面對動畫中的每一幀圖像進行處理,比如:
實時讀取視頻信息
對每一幀視頻圖像進行實時處理,計算出摳圖蒙版
將計算出的蒙版傳給彈幕組件,以實現實時的蒙版彈幕
下面是基于 Barrage UI 組件實現的蒙版彈幕效果:
由于文中不方便嵌入視頻,Demo 的實際效果請移步到 此處 查看。
下面我們來介紹如何實現上圖的動畫效果。
色鍵(色度鍵控)Demo 中使用了初音小姐姐跳舞的視頻。最主要的特點是除了人物外,視頻的背景是比較一致的純色。對于這種類型的圖像,我們可以使用 色鍵 的方式進行摳圖(生成“蒙版”)。
色度鍵控,又稱色彩嵌空,是一種去背合成技術。Chroma 為純色之意,Key 則是抽離顏色之意。把被拍攝的人物或物體放置于綠幕的前面,并進行去背后,將其替換成其他的背景。此技術在電影、電視劇及游戲制作中被大量使用,色鍵也是虛擬攝影棚(Virtual studio)與視覺效果(Visual effects)當中的一個重要環節。
下圖是色鍵技術的一個示例:在綠幕前穿著藍色衣服的小姐姐,左圖為去背前,右圖為去背后的新背景。
如何扣取視頻圖像在瀏覽器環境中,我們可以通過 canvas 畫布實時地繪制視頻的每一幀,并從畫布中讀取到圖像中每個像素的 RGBA 信息,檢測每個點的 R(red)、G(green)、B(blue) 值是否滿足要求,最終將需要扣除的像素的 A(alpha) 值置為 0,即可得到用于合成蒙版彈幕的蒙版圖像。
注意:
Barrage UI 組件的蒙版功能是基于 Canvas 2D API 的 CanvasRenderingContext2D.globalCompositeOperation 屬性實現的(使用了 source-in 的混合模式),因而只需將不需要的像素設置為透明(alpha=0)即可,并不需要改變圖像的 RGB 色值。
下面介紹此案例的代碼實現。
具體實現 安裝 Barrage UI 組件直接使用 yarn 或 npm 安裝此組件:
yarn add barrage-ui or npm install --save barrage-ui
HTML + CSS準備一個 video 元素用于播放視頻,video 的父級元素用于掛載彈幕:
根據視頻的實際尺寸(880×540)設置 #container 與 #video 的樣式:
html, body { font: 14px/18px Helvetica, Arial, "Microsoft Yahei", Verdana, sans-serif; width: 100%; margin: 0; padding: 0; background: #eee; overflow: hidden; } #container, #video { width: 880px; height: 540px; } #container { margin: 0 auto; margin-top: 50vh; margin-left: 50vw; transform: translate(-50%, -50%); background-color: #ffffd; }創建彈幕
import Barrage from "barrage-ui"; import data from "utils/mockData"; // 獲取父級容器 const container = document.getElementById("container"); // 創建彈幕實例 const barrage = new Barrage({ container: container, }); // 重置畫布高度,避免彈幕遮擋視頻播放控件 barrage.canvas.height = container.clientHeight - 80; // 裝填彈幕數據 barrage.setData(data);
其中,mockData 是用于生成隨機彈幕數據的方法。
關于彈幕數據的內容與格式,詳見 Barrage UI 項目文檔實時獲取視頻圖像
// 獲取 video 元素 const video = document.getElementById("video"); // 新建一個畫布來實時繪制視頻(純繪圖,不用添加進頁面) const vCanvas = document.createElement("canvas"); vCanvas.width = video.clientWidth; vCanvas.height = video.clientHeight; const vContext = vCanvas.getContext("2d"); // 實時繪制視頻到畫布 barrage.afterRender = () => { vContext.drawImage(video, 0, 0, vCanvas.width, vCanvas.height); };
使用組件提供的渲染周期鉤子 .afterRender() 可以在彈幕動畫的每一幀圖像渲染后,將視頻圖像繪制到中間畫布 vCanvas 上。注意這里的 vCanvas 畫布主要用于實時地獲取視頻圖像,并不需要添加到頁面中。
實時計算蒙版信息// 渲染前讀取畫布 vCanvas 的數據,并處理為蒙版圖像 barrage.beforeRender = () => { // 讀取圖像 const frame = vContext.getImageData(0, 0, vCanvas.width, vCanvas.height); // 圖像總像素個數 const pxCount = frame.data.length / 4; // 將 frame 構造成我們需要的蒙版圖像 for (let i = 0; i < pxCount; i++) { // 這里不用 ES6 解構賦值的寫法,主要為了保證性能 // PS: 這里如果用解構賦值語法將導致大量新對象的創建,是個很耗時的過程 const r = frame.data[i * 4 + 0]; const g = frame.data[i * 4 + 1]; const b = frame.data[i * 4 + 2]; // 將黑色區域以外的內容設為透明 if (r > 15 || g > 15 || b > 15) { frame.data[4 * i + 3] = 0; } } // 設置蒙版 barrage.setMask(frame); };
使用組件提供的渲染周期鉤子 .beforeRender() 可以在彈幕動畫的每一幀圖像渲染前計算出蒙版圖像。其中,用于更新蒙版的接口為 .setMask()。
視頻、彈幕的操作綁定最后,為了讓彈幕的行為與視頻播放的操作協同,還需要進行一些綁定的操作:
// 綁定播放事件 video.addEventListener( "play", () => { barrage.play(); }, false ); // 綁定暫停事件 video.addEventListener( "pause", () => { barrage.pause(); }, false ); // 切換播放進度 video.addEventListener( "seeked", () => { barrage.goto(video.currentTime * 1000); }, false );
這里分別用到 Brrage UI 組件的 .play() .pause .goto() 三個接口,分別用于播放、暫停和切換彈幕動畫的進度。需要注意的是,通過 video.currentTime 屬性獲取到的視頻播放進度是一個單位為 秒 的浮點數,需要轉換為 毫秒數 再傳給彈幕組件。
源碼奉上本文的案例已上傳 github,感興趣的童鞋可以點擊 這里 查看源碼細節。
關于 Barrage UI 組件如果有什么建議和疑問,歡迎大家在項目中提 issue 給我,幫助我持續改進和迭代,更歡迎 star 和 PR。
感謝您能耐心讀到此處,如果覺得有趣或有用,不妨 點贊/評論/轉發 此文,再謝。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/101217.html
摘要:將圖片的處理方法放到視頻中的每一幀,再加上彈幕飛過的效果,就完成了版的智能防擋彈幕。不知道站的實現方法是怎樣,是否有人工干預,是否有預計算。 某天代碼寫得老眼昏花,去B站上摸魚,突然發現奇怪的現象: showImg(https://segmentfault.com/img/remote/1460000017911829?w=600&h=284); 喲呵,B站竟然做了 視頻前景提取 ,把...
摘要:全屏蒙版彈窗遮不住的層級還是很高的,當出現全屏蒙版彈窗時,是無法蓋住的,可以調用微信的,不過需要注意兼容低版本在類設置的顏色并沒有變化。 從6月份開始到現在,寫小程序將近4個月了開發時給自己埋了不少坑~給大家分享下我的填坑經驗~~ 開發部分 1.小程序的組件修改不能觸發頁面刷新?需要在父級文件上保存下才會觸發(使用wepy開發) 2.接口請求出現的問題?記得勾選調試開發工具上 不校驗...
摘要:想要快速實現這些功能,需要進行怎樣的操作呢其實,實現直播彈幕功能只需四個步驟和幾行代碼現在,我們使用云巴,手把手教你實現直播彈幕功能吧步驟一注冊云巴賬號打開網址,或直接搜索云巴,進行注冊并登錄。 在視頻直播中,互動是不可缺少、不容小覷的內容,主要包括發送彈幕、打賞、點贊等。想要快速實現這些功能,需要進行怎樣的操作呢? 其實,實現直播彈幕功能只需四個步驟和幾行代碼! 現在,我們使用云巴 ...
摘要:實時彈幕使用云巴,直播平臺可快速實現視頻直播中發送彈幕打賞點贊等實時互動功能。云巴聊天室支持圖片上傳文件發送文檔評論系統正式上線新增搜索功能,我們會做得更好。 SDK 篇 Android SDK 更新 Release 1.6.3后臺進程相互拉起的特殊版本 Release 1.6.4增加 so 文件 Release 1.8.0支持小米、華為推送,無需注冊第三方賬號 Release 1....
閱讀 2604·2021-09-23 11:21
閱讀 1896·2021-09-22 15:15
閱讀 985·2021-09-10 11:27
閱讀 3453·2019-08-30 15:54
閱讀 667·2019-08-30 15:52
閱讀 1344·2019-08-30 15:44
閱讀 2359·2019-08-29 15:06
閱讀 2986·2019-08-28 18:21