Monday, October 21, 2019

WebAssembly ffmpeg.js 透過 stdio async 讀入檔案 (驗證?

在與來自烏克蘭github大大來信後,他推薦我用WebRTC方式,最後進行串流討論後得出以下結論

我覺得WebRTC預設編碼的x264,本身好像也是p2p??,雖然延遲性和安全性提高了但是在應付大規模場景下應該不適合,
别迷信 WebRtc,WebRtc只适合小范围(8人以内)音视频会议,不适合做直播:
1. 视频部分:vpx的编码器太弱,专利原因不能用264,做的好的都要自己改264/265代码才行。
2. 音频部分:音频只适合人声编码,对音乐和其他非人声的效果很糟糕。
3. 网络部分:对国内各种奇葩网络适应性太低,网络糟糕点或者人多点就卡。
4. 信号处理:同时用过 GIPS和 WebRTC 进行对比,可以肯定目前开源的代码是GIPS阉割过的。
5. 使用规模:10人以内使用,超过10人就挂了,WebEx方案支持的人数都比 RTC 强。
作者:韦易笑
链接:https://www.zhihu.com/question/25497090/answer/72397450
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
在我詢問他是否可以通過我在上回的方向去實作他說是可行的(基於商業客戶向他買解決方案)不能透漏,在分支
提到這個部分大概就可以解決我所說的問題,再來就是猜猜看怎麼處理了

在ffmpeg 轉成 ffmpeg.js 他在把 ffmpeg 裡面的 file 和 tcp 的函數裡面的意外中斷的片段程式碼
都給 remark掉 這樣在 運行 async stdio就不會意外中止 ( 或許就可以 向他說的 透過 getUserMedia 去 讀取資料這樣我們只要把 那些blob 轉成 file 跟原先一樣不用動,在結合上一個文章就可以 達到 用網路傳遞數據給後端 推送給 其他串流伺服器了前端編碼就完成囉!
再來就是 要再編譯的參數 EMTERPRETIFY_ASYNC=1 給打開
他fork出來額外新增的內容應該就是這些
提到他說可以從這方向找尋到我要的解答所以確定可以用getUesrMedia去實作還有以下要問題要解決
第一個就是blob跟輸出檔案問題一樣超過70mb可能會出現 記憶體崩潰或者溢位導致瀏覽器crash
可能要查閱 wasm fs 虛擬檔案映射那邊
第二個則是檔案的讀入方式
他提問我為什麼要用自定義ffmpeg 去做 影音上的串流,目前不是有 WebRTC可以達成目標了嗎
我當初想做是因為可以實現任意編碼的問題和可以隨意推送去任意 RTMP串流伺服器,再者就是 目前大部分主流是RTMP 又有豐富的 CDN 當然 WebRTC也可以實作CDN ,國外網友好像不怎麼贊成 好像不太怎麼穩定)
上述內容可能需要 重新compliter 整個 ffmpeg.js才能實證了,又是一個17小時?,有空再來玩 (話說 是不是該刷leetcode了

Wednesday, October 16, 2019

WebAssembly 修改 ffmpeg.js 在運行時輸出 檔案 ArrayBuffer (三)

今天要解決的問題是,之前我們遇到的,除非 wasm 權限越開越大,
不然就是 ffmpeg output 可以輸出至 其他 通訊 tcp/rtmp
那上次研究的結果還會卡到 既然是在 web worker 裡面那我們可能還會面臨 chrome 的
https/http 協議不能混用

這邊的話想了一下有沒有能在程式執行中 進行 output呢?
所以我覺得能不能在這兩個函數內找到一些結果,果然有發現
開始初始化前
Module[“preRun”]
結束後輸出
Module[“postRun”]

也就是大大們卡很久的檔案映射問題?
之前想為什麼輸出能掛載在虛擬機上,既然是虛擬機,我跑ffmpeg 的時候應該就可以讀到
掛載的檔案那麼是不是可以在ffmpeg run 的時候就可以取的檔案 buffer?

實驗結果是可以的就是在檔案輸出 stdout 的時候去呼叫原本我們在 postRun的那邊結束後呼叫的時候才會產生blob檔案只要修改這邊就可以了

再參考論壇等等有發現已經有可以從stdin 前端"解碼"的範例了,也可以讀 串流
https://cloud.tencent.com/developer/article/1453425
https://github.com/sonysuqin/WasmVideoPlayer
至於讀出呢,可以透過這些方式去 回傳 給 js 去做處理
接下來呢,後續可能會有什麼玩法?
目前的話可以,因為不同的電腦cpu呼叫 ffmpeg 編碼的話速率不同,一次解碼的量也會不同所以我們buffer的偏移量我覺得應該也會不同,至於一次要偏移有空下次研究,假設這個問題可以解決,返回函數到,js後我們可以或許我們可以做 ArrayBuffer 合併 串流 那我們就可以完成前端 "編碼"的問題,那我們之前要實作的,就只差通訊協定了 可以透過 websocket 進行傳輸,

我們目前就已經解決我之前做的範例透過 chrome mediarecoder 在傳輸給 socket.io 先進行 畫面上的錄製再傳送給後端 nodejs, nodejs 在 fork 很多個 ffmpeg 在進行推畫面上的重組送給其他串流伺服器。

現在我們是 先 透過  chrome mediarecoder 進行畫面上的 傳輸,再透過走 TCP 或 udp (謎樣方式串流)
輸入至位於webwork 裡面的 ffmpeg wasm 在這邊 執行 用戶端編碼再透過我的方式去把檔案的 ArrayBuffer ,看是要在前端進行js 編碼上的處理還是  還是透過 websocket傳輸至後端處理再推送給其他串流伺服器。

這邊可以看到我們已經大大的減少 伺服器端幫我們做的事情,這樣我們是不是更貼近 無插件進行 串流了呢(?


在2020 chrome 要徹底廢除掉 flash 的話,那我們就可以實現,在前端不加掛任何插件的方式下
透過chrome mediarecord 進行 攝像頭的讀入,再根據我們剛剛的方式,再配合偏移量的演算法寫作,應該就可以達到 無插件 進行 前端 推流,wasm 在繼續進步下去或許效能會越來越強,adobe flash 可能就要掰了哈哈

Monday, October 7, 2019

微服務初探 之可不可以不要 動不動就死掉 (一)

最近無聊來研究rabbitmq,加上之前的一些什麼微服務什麼的,
在新買了的nas看到了假設我上圖片或影音檔,它們都會跑出一欄任務顯示處理中,在其他電商的案例也有可以能是以消息佇列進行排程?
舉幾個例子
在以掏x來說訂單不可以消失,貨可以再補,馬先生絕對不會讓你漏掉的機會,
再來websocket實作的消息推播來說,在處理完使用者功能後,server要推送給client
假設使用者沒開機的話是沒法接獲這條消息的,那這條消息就這麼算了嗎? ? 當然你說可以用firebase等等去實作但是在某些地區 大陸這些地區就不能使用 google服務(當然以後說不定會開放哈哈
再者當然你想成本上不許可想自行搭建推播server或許可以使用消息佇列來實作 ,當然不只有rabbitmq
Apache 的 Kafka、阿里巴巴 RocketMq 都各有優點 請大家選擇合適的場景來選擇
那麼以我的認知來說rabbitmq 實作一個類似 nas 處理相片功能 可以做到下列功能
影片傳到後台後 呼叫大量 ffmpeg 去處理相片功能,+人臉辨識 進行分類那麼我們用
rabbitmq進行實作可能會變成下列這樣
微服務 最近幾年好像很夯,應該是它裡面的可擴展性,當然像一般的程式,你把所有功能寫在同一支
當負載太重 導致程式 crash


那摩何嘗不使用一下rabbitmq 你就可以透過水平擴展增加負載量較大的功能
rabbitmq 有支持HA - High availability
跟負載平衡很像不過又好像有點不一樣(自己去查一下
所以你的功能就掛了或許可以參考一下 rabbitmq,其二我選擇他的原因就是他以前是負責金融交易平台的重要利器所以穩定性呢可以說相當的夠,再來就是它是免費的,無聊可以玩一下
其三就是不同的消息佇列可以支持各種不同語言來編寫,這邊在應對新的世代我們可以銜接各種不同的程式語言以便擴展。
那麼 參考以我的了解跟剛剛要實作的情形是這樣
錯了別罵我,保持著討論心態
(上圖假設沒錯的話,記憶有點模糊xd,這個月在休息
這邊舉例呢可以看到,
-------->這是針對 任務處理完 沒有要返回訊息給其他佇列的情況下
那麼我們的server端 可以 開始指派任務也就是 我們的生產端將產生一個任務給我們的消費端
可以看到我們的消費端有兩個一個是負責處理 影像壓縮 一個是負責 臉部分類
那麼呢
兩個使用者上傳影片到 nas
就可以看到影像壓縮任務c1,c2放在佇列等待被消化
裡面的任務欄位中間可以我有寫 看到 同步(async) 和 非同步 (sync)
裡面的任務就算失敗了也可以被重新執行到成功這點算蠻重要的(當然你程式要寫好xd
那麼大致流程圖就是這樣,當我們的某一部分功能負載過於嚴重我們就可以

直接水平擴展一部分功能,當然你可以看到 生產端到 消費端 其實裡面還隱藏了一小部分的功能
exchange可以根據我們的chanel 選擇頻道進行 任務的派送

比如說 chanel1 的 消息佇列裡的其中一個任務c1已經完成
那麼則再通知生產端產生一個任務給chanel2
那麼chanel2這邊任務分配就會變成



進行任務上的分配 所以我們可以看到我們的功能佇列可以透過 水平擴張 依據機器 的流量以及處理能力來進行權重上的調配
-------->這是針對 任務處理完 返回訊息給原始佇列的情況下
那麼這種情況有沒有可能任務佇列跟任務佇列 要進行溝通這種情況呢?
你可以透過 grpc 進行任務上的溝通

我們的機器上c1的任務被處理中並呼叫 生產端產生 其他兩個子任務c2 c3

那麼這邊有兩種
第一種情況
c2裡面任務先被消化那麼他就要等 c3裡面的任務 消化完再 發送給訊息 給 c1
第二種情況
c3的任務消化完畢, c2的任務完成還沒完成等待c3,c2才可以發送 任務完成給 c1
解決方式就是邏輯寫在c2完成後,在透過grpc 取 任務佇列的 c3任務進行判斷完成後再 發送訊息給c1 說任務已經完成。
這邊可以看到,微服務在某些環境確實有點不錯,但是在 任務複雜度太過於多的話,可以由上方例子得知程式與程式之間的溝通不太方便雖然有rpc 通訊
,所以我們要避免的就是微服務不要拆得太細就可以解決我們的系統效能上的瓶頸。

然後最後上方的所有範例圖要等最近有空才會做簡單 demo ,等待穩定後這一篇我會詳細補充,修正其錯誤知識(ps 總覺得技術落差一直卡在兩年前