React Native (Expo)でカメラプレビューにエフェクト


Expoでカメラを使う時ライブプレビュー画面にgl-reactでエフェクトをかけたい。

gl-reactに関してはこことかこことかここも参照。

結論を書くとあまりスマートな方法で解決はできなかったです。

 

関連リンク

仕様の理解と方策

ドキュメントを読んだ感じではプレビュー動画へのアクセスは出来なそう。

一応ソース群を見てみますがExpoでどうこうするのは無理そう。

色々調べていると同様の試みを行っているものがありました。

Mediumとshoutemで掲載していますが内容は同じ。

これを参考にしてみます。

 

内容を簡潔に言うと5ms(完成ソースだと何故か8ms)ごとに写真を撮ってURIをNodeに渡して描画してます。

Expoでない(React Native Camera使用)のと古い関数を使っている部分はありますが、大体そのままで動かすことは可能です。ただし問題もあります。

問題点

書いてるときからそうなるだろうなと思ってましたが、キャッシュデータがすごい勢いで増えていきます。最低品質にしてみても無視できるものではないです。

さらにインターバル処理がまともに動きません。

Warning: Please report: Excessive number of pending callbacks: 501. Some pending callbacks that might have leaked by never being called from native code:

まあ保存処理が5ms以下でサクッと出来なきゃ負荷が上がってプロセスもどんどん積み重なりますよね。

こっちはsetIntervalをやめてrefreshPic()で画像保存後にsetTimeoutで自分を呼びなおすことで一応対処できる。

テスト用の貧弱スマホではありますが320×240サイズを速度重視で保存するのに1~1.7秒かかるのはつらい。平均0.8fpsってカクカクで済むレベルじゃない。

代替手段

takeSnapshotAsyncでうまいこと出来ないかなと試す。

例によってexpoのtakeSnapshotAsync()は使えなかったのでreact-native-view-shotから直接使う。

遅くなると想定していたけど何故か倍近く早くなった(0.6秒前後)。

カメラの画像保存ってコスト高いのかな。

 

ここで"tmpfile""data-uri"にすることでキャッシュ問題をなくすとどうだろう。

WebGL部分でuniform t: no loader found for valueと怒られた。

この辺のIssueはちょくちょくあるけど解決策は使えそうにはない。

Node.js#L938createSurface.js#L529ExpoModuleTextureLoader.jsとソースを追って色々試すも以下のエラーで止まってしまった。

EXGL: Invalid pixel data argument for gl.texImage2D()!

ここで変換かますのも遅延の原因になるしそのまま使えないならこの方向はダメか。

結局どうするか

全てに妥協し、tmpfileに保存して使い終わったらFilesystems.deleteAsyncで消す。

もしくはejectしてreact-native-webrtcを導入。

streamgl-react/…/examples/webcamなどを参考にgl-reactに流す。

 

結構探したとは思うけど今後良い方法を見つけたら追記したい。


コメントを残す

メールアドレスが公開されることはありません。