在瀏覽器實作虛擬會議室

這一年因為武漢肺炎的關係,使用網路會議室開會的頻率變得越來越高,而現在幾個主流的服務都有提供虛擬會議室的功能,簡單來說就是無需綠幕的去背,藉此避免在家工作時背景亂糟糟的。
最近公司要我嘗試實作這功能,以下簡單紀錄一下做法與結果。
使用到的技術
可以理解到,此需求最核心的問題是如何從每一禎的視訊畫面中找出人在哪裡。
一開始去找了一些影像處理的涵式庫,例如 OpenCV 之類的,後來發現我找的方向錯了,真正需要的東西是 TensorFlow.js

TensorFlow 是個開源的機器學習工具,TensorFlow.js 就是他的 JavaScript 版,可以跑在 Node.js 或者直接跑在瀏覽器上。最棒的是它有提供幾個已經預先訓練好的模型可以使用,其中就包含辨識人體的機器學習模型 BodyPix
於是大概的思維如下:
- 使用瀏覽器的 API 擷取視訊畫面
- 把畫面丟給 TensorFlow 分離出人與背景的像素
- 在 html canvas 把背景與切割好的人物像素合成
- 把 canvas 當成視訊串流進行輸出
- 把串流接上 WebRTC
1. 取得視訊畫面
引入涵式庫
1 | <head> |
準備需要的元素
1 | <body> |
然後撰寫 js
1 | const videoElement = document.getElementById("video"); |
大致上就是取得視訊畫面,然後丟到 html video 上面播放,撥放後執行 init() 開始後續工作。
記得要存好拿到影片的長寬資訊,繪圖的時候會需要。
2. 執行 BodyPix
1 | async function init() { |
- 初始化模型,這邊設定的方式請參考官方說明文件,選擇的結果會影響判斷的準確度與需要的硬體性能。
- 從檔案讀取需要使用的背景照片。找個漂亮的風景圖或會議室照片之類的,也有公司有提供免費的圖給大家玩,如果你的老闆不介意看到你在鬼滅之刃或神隱少女的場景開會的話。
- 定時重複執行繪圖
3. 合成畫面
1 | const foregroundColor = { r: 0, g: 0, b: 0, a: 255 }; |
- 設定前景、背景色、與辨識參數(參數一樣參考官方文件設定)
- 執行主程式
bodyPix.toMask()取得遮罩 - 將遮罩與視訊畫面、背景畫面疊圖
理論上至此已經可以在瀏覽器上測試,並於螢幕上看到運算結果。
4.取得串流
最後執行 canvas.captureStream() 即可將 canvas 轉換成 MediaStream ,然後就去串接自己的 WebRTC 服務吧。
成果如何?
不好意思露臉就沒放測試的圖了。
辨識的結果我覺得還算準確,只要你不是穿跟背景顏色一樣的衣服,基本上可以精確抓出頭、手、身體。
但問題是滿吃效能的,測試過程中我的瀏覽器當掉過好幾次,沒當機也是記憶體滿載,不確定是瀏覽器性能的原罪,還是我程式撰寫還需要改善。
總之目前的成果我覺得不到可以正式上線的程度,勉強堪用而已。
有點好奇那使用 Node.js 來跑會不會比較好?之後有空再來嘗試吧。
- 封面圖片來源:elitedaily