webとモバイルアプリの逆転

webアプリとモバイルアプリの開発に関する話や本・ゲームなどの趣味の話を雑多にしていきたい

雑メモ:Quest3のDepthAPIが動かなかった時

github.com

このAPIを別のUnityProjectに取り込んだ時に、うまく動かないときがあった。 具体的には、OcclusionTogglerというSceneでHard Occlusionにしても、Occlusionしてくれないことがあった その時に、解決した方法を忘れないように雑にメモ ただ、何が起きてて、どうして解決したのかがわからないため再現性がない点は注意

OcculusメニューのProjectSettingToolでAutoFixをすると直った。 おそらく、シェーダーの設定がおかしくなってしまってたのかなと推測はできる。ただ、ログが残ってないので詳細は不明。

次問題が起きたときに、どこでwarningが起きたのかをもう一度見ようと思う。

2024年の目標

年始からコロナに罹ってしまいスタートダッシュに失敗した感がある2024年になってしまった。

とはいえ、まだ1月なのでこれから計画を立ててもまだ挽回できると思って書いていこうと思う。

マストでやりたいこと

  • インプット量の増加(技術書を読む)
  • 文章力を上げる
    • ブログを書くようにする
    • わかりやすい文章を書くというのを目標に
  • 新しい言語を覚える
    • 一応、毎年言語には挑戦するようにしてるので継続したい

できたらやりたいこと

iOSアプリの開発(VisionPROの開発)

目標を立てる上で考えていること

  • できるだけ長続きできるように難しい目標は立てない
  • 途中でできなくなったとしても諦めない

2023年振り返って

せっかくなので今年を振り返ろうかなと思って記事を書いてみる 前に振り返ってたのは2019年だった。

今年は記事を書くことがなく終わってしまった…来年はもうちょっと書きたい

今年なにした?

  • Androidアプリ開発に挑戦した
    • プロダクションのコードにがっつり反映されてる状態になってるのよく考えると結構挑戦はできたなという気持ち
  • 工数管理失敗して若干修羅場になってしまった
    • 炎上というほどではないが、かなり働く週を作ってしまった
    • これまでめちゃくちゃやらないと間に合わない…って状況になったことなかったからよい経験にはなった
    • 次大変な目にあいたくないという気持ちが強くなり見積もりに対する意識やコミュニケーション意識が上がった気がする
  • 前より自分の考えをもとに意見することができるようになった気がする
    • 気がするだけなのでできてるかはわからない。けど、継続してやっていきたい
  • Rustをちょっと触れた
    • Rustを使ったアプリを作ることができたのでちょっとは触れた

何ができなかった?

  • 文章を書けなかった
    • 会社で書いた文章を除くとアドベントカレンダ-しか記事がかけてなかった。来年はもっと書きたい。文章力を上げるためにもたくさん書いていきたい
  • 本を読めてない
    • アウトプットに忙しくなってしまってインプットがおろそかになってしまった。本を買いはしたので読んでおきたい…

来年どうするの?

なんか新しいことに挑戦したい気持ちがある。 Rustを少しだけ触れたが、全然概念を理解しきれてないのでもう少し触りたい あと、アーキテクチャも学んでいきたいので意識してインプットに入れたい

会社で何か変革したいなという気持ちがあるのでやりたいな。やろうと思うとなんでもできる環境なので活かしていきたい。

Create React App + prisma + sqlite3で作られたアプリをpackage化する

問題点

Create React Appで用意したアプリにPrismaを導入したところ、npm run package でproduction buildするとDBアクセスができない現象が発生した。

解決策

package.jsonのbuildの項目にextraResourcesを追記してPrismaを追加する。

{
    "build": {
         ...
        "mac" or "win": {
        ...
        "extraResources": [
            "prisma/**/*",
            "node_modules/.prisma/**/*",
            "node_modules/@prisma/client/**/*"
        ]
        }
    }
}

何をしているか

まず、npm run package の中身を見てみる。

ts-node ./.erb/scripts/clean.js dist && npm run build && electron-builder build --publish never

最初の一つ目のコマンドはすでにビルドされている結果の削除、 ふたつめはwebpackを用いてビルドをしているだけなので、ここでは割愛する。

今回問題になっていたのは3つ目のelectron-builder build --publish neverだった。 これは、Electronのアプリを配布するためのパッケージングを行うものとなっている。

Create React Appを利用するとこのパッケージのインストールと設定が行われるようになっており、その設定はpackage.jsonの"build"の項目に記載されている。

Prismaで生成されたクライアントとデータベースをパッケージに組み込むように設定されておらずエラーとなっているみたいだった( 参考)。

なので、ビルドする際にPrisma関係のファイル・ディレクトリを含めるように指定することで動くようになった(該当するドキュメント)。

モデリング初心者がBlender 2.8でVRMモデルを作る上で覚えた操作と手順

だいぶ前に書いて下書きに放置されていたメモを発見したので投稿。
2月くらいにBlenderでのモデル作成に初挑戦して悩んだことをメモした内容になっています。
最近Blenderをいじることを再開して操作に慣れてきたので、もう少しまとめることができたらブラッシュアップしたいと思ってます。

VRMのモデルを(ほぼ)フルスクラッチで作成しようとしたときに、詰まったり悩むことがあったので、やった内容をまとめていきたいです。 ほぼと書いたのは、体の骨格的な部分は素体を公開している人がいたのでそれをありがたく使わせていただいたからです。

フルスクラッチで作ろうとしたのは、SDキャラというかミニキャラのようなモデルが欲しくて探してたのですが、見つからなかったのでじゃあ作るか…と思い立ったからです。 作ったVRMキャラは技術書典のサンプルアプリとして使いました。

できたモデルは下の画像のようになってます。 髪は途中でよくわからなくなって妥協してしまったので次回リベンジしたいなとおもっています

f:id:s-haya:20200309000548p:plain
正面
f:id:s-haya:20200309000611p:plain
横から

VRMモデルを作るうえで詰まった点

まず、自分がVRMモデルを作成する際に時間がかかってしまったポイントをまとめておきます。

  • Blenderでウェイトを設定する際に自動正規化の設定がされておらずうまく動きを設定できなかった
  • メッシュの裏表が正しく設定されておらず一部のメッシュが表示されなくなってしまった
  • Blenderで作成したモデルをUnityで読み込む際にBlendShapesの設定が正しくされておらず表情がおかしくなってしまった

Blenderでの作業

前準備

前準備としてBlenderVRMを扱うためのプラグインを導入します。

github.com

このプラグインを導入することでVRMモデル用のボーンが使えるようになります。
ここではVRM用のボーンを使うために導入しました。
ボーンとは3Dモデルの骨格のようなものであり、腕の可動域などの設定を行うのに使います。

f:id:s-haya:20200309004526p:plain
ボーン

モデルの作成

3Dモデルのキャラクターを作っていきます。 体自体は下記の素体を使用させていただきました。

booth.pm

体を導入したあと、下記のリンクを参考にしながら服を作っていきました。

かんたんBlender講座

Blenderでの3D女の子キャラモデリングの全てを完全解説するよ!

モデルの作成時にモデルのメッシュの裏表を正しく設定できているか注意する必要があります。 正しく設定できていない場合、VRMとして出力した際にモデルの一部がうまく表示されなくなってしまいます。
(私はモデルのスカートがうまく設定できておらず消えてしまいました。)

ボーンとウェイトの設定

キャラクターがどのように動くのかを設定します。 その目的を果たすために、ボーンとウェイトについて設定をします。 ボーンは骨格のようなもので、キャラクターの可動域を設定するものです。 そして、ウェイトはボーンを動かした際に、3Dモデルのキャラクターがどのように動くのかを設定するものです。

ボーンの設定

ボーンを追加するためには、ボーンを追加して、キャラクター上に重ねて配置します。
オブジェクトモードで「Shift+A」を押してアーマチュア-> VRM humanoidを選択することでボーンを追加することができます。

f:id:s-haya:20200515221124p:plain
ボーンの追加方法

ボーンを動かしたときにどのようにキャラクターが動くのかは次のウェイトの設定で行うので、 ボーンの配置は正面からみてキャラクターがなんとなく重なっているようにすれば問題ないかなと思って配置しています。

f:id:s-haya:20200515222215p:plain
ボーンと重ねた様子

ウェイトの設定

ボーンを設定したらウェイトを設定してキャラクターの動きを設定します。 流れとしては、Blenderの機能で自動でウェイトを設定し、手作業でウェイトを調整していきます。 手作業の調整を加えた理由として、意図した動きではないことがあったためです。 自動でウェイトを設定する方法としては、オブジェクトモードに設定して、キャラクタ→ボーンの順に「Shift」を押しながら選択し、「Ctr+P」を押して、自動のウェイトを選択しました。

自動で設定したウェイトでどのような動きになっているのかポーズモードでボーンを動かすことで確認していきます。 ボーンを選択した状態で「Ctr+Tab」を押すことでボーンモードに変更します。 この状態で回転などの操作を行い、自分が意図した挙動になっているのかを確認しました。 自分の場合、足を動かしたときにスカートの動きが正しく動いてなさそうだったので、足の動きを調整する流れを例にして説明します。

f:id:s-haya:20200515233839p:plain
ウェイトが設定されていなかった場合

手作業での設定はメッシュを選択し、「Ctr+Tab」を押してウェイトペイントを選択してウェイトを調整します。
ウェイトを調整する前に、メッシュの正規化を行います。この作業が大切で正規化を行わないと意図した動きをしませんでした(なぜだめだったのかは理解できていないです。後で確認したい・・・)。 ブラシの設定で自動正規化という項目があるので、そこにチェックをつけることで設定できます。

f:id:s-haya:20200515231727p:plain
正規化の選択

ボーンを選択した際に、キャラクターのどこの範囲がどれくらい動くのかは色で判断しました。 赤色がボーンの動きと強く関連して動き、青に近づくほど関連性は低くなっていきます。
自動でウェイトを調整した際にスカートの部分にウェイトが設定されておらず、足を動かしても貫通してしまう状態でした。なので、ウェイトを図のようにブラシで設定していき、調整を加えていきました。

f:id:s-haya:20200515232525p:plain
ウェイトの調整
f:id:s-haya:20200515233400p:plain
足を動かしたとき

テクスチャの設定

表情の設定

VRMにはブレンドシェイプという設定があり、 そこを調整することでモデルに表情をつけることができます。

ブレンドシェイプには事前に定義された種類があり、 その種類に該当する種類をBlenderで作成することでVRMで表情を設定できます。
Blenderではシェイプキーを設定することでこの設定を行うことができます。

シェイプキーは画像の場所から設定できます。

f:id:s-haya:20200621233635p:plain
シェイプキーの設定

例えば、プリセットの「A」を設定する場合を考えてみます。 このAは「あ」と発音しているときの表情を示しており、モデルの表情を変えてそれを表現するように設定する必要があります。 シェイプキーを設定するときには「編集モード」に設定して行います。
オブジェクトの頂点の位置を調整しながら、シェイプキーの設定を行います。
まず、ベースの表情を作成したのちに、 シェイプキーを作成し画像のように表情の調整をしていきます。

f:id:s-haya:20200621233725p:plain
ベースの表情
f:id:s-haya:20200621234031p:plain
「あ」の表情

注意点として、オブジェクトの数が上限する操作はしないようにする必要があります。 また、元に戻らない可能性もあるので、シェイプキーの設定を行う前にファイルのバックアップをとっておいたほうがよいと思います。 この表情の設定を自分が使いたいプリセットだけ繰り返していきます。

モデルの出力

最後にモデルの出力を行います。モデルはfbxの形式で出力して終了します。

Unityでの作業

前準備

UnityでVRMをあつかえるようにUniVRMというプラグインを用意する必要があります。 インストールの仕方は上記リンクに記述があるので、ここでは割愛します。

モデルの読み込み

Blenderで出力したfbx形式のモデルを読み込みます。 Unity上にfbxをドラッグアンドドロップの操作をすることで読み込むことができます。

読み込みが終わったら、fbxファイルをUnityで選択し設定を行います。 行う設定はmodelの種類とBlendShapeの種類です。

modelの種類はhumanoidを選択します。

f:id:s-haya:20200622194753p:plain
Humanoidの設定
ここでConfigureを選択することボーンの設定もできます。 Blenderでボーンの設定ができていれば、図のように緑色でボーンの対応箇所が表示されていると思います。
f:id:s-haya:20200622194035p:plain
HumanoidのCofigure

もう一つBlendShapeの設定として、Legacy Blend Shapes Normalsにチェックを付けて有効にしました。
自分の場合、このオプションを付けないとVRMの表情が正しく設定できず、「A」などのパラメーターを操作しても意図しないモデルの変形が行われてしまいました。(Unity2019.3.0a11 とBlender2.8の組み合わせで発生。Unityのバージョンによっては発生しない可能性あり)

f:id:s-haya:20200622195117p:plain
Legacy Blend Shapes Normals
上記の設定が完了したらVRMのメニューからexportを選択し、一度VRMで出力を行います。

マテリアルの設定

上記で出力したVRMモデルだとそのままだとマテリアルが正しく設定されてなかったので、もう一度読み込んで設定を追加していきます。

Blenderで作成したテクスチャの画像が必要なので用意します。

次にUnityでテクスチャを読み込んだマテリアルを作成します。 作り方はCreate->Materialを選択します。

f:id:s-haya:20201005154341p:plain
マテリアルの作成
作成したMaterialに対してshaderとColorのTextureの設定をします。 shaderは右上のshaderを選択した後にVRMー>Mtoonを選択します。
f:id:s-haya:20201005154648p:plain
sharder
Textureの設定は図の箇所で行います。用意したテクスチャの画像を図の箇所にドラッグ&ドロップで持っていくことで設定します。
f:id:s-haya:20201005160817p:plain
Texutureの設定

最後に、作成したマテリアルをVRMのモデルの該当する箇所にドラッグ&ドロップで持っていくことで適用することができます。

表情の設定

最後に表情の設定を行います。 BlendShapeに設定をすることで表情を決めることができます。

f:id:s-haya:20201005173343p:plain
BlendShapeの位置
BlendShapeをダブルクリックすることで設定を開くことができます。 各キーに対してどのような表情を割り当てるのかを下の画像で確認しながら設定することができます。 ここで設定できる表情はBlenderで設定したシェイプキーを元になっています。
f:id:s-haya:20201005175037p:plain
BlendShapeの設定

表情を設定できたらVRMー>Exportから出力することでVRMモデルの完成です!

今後やりたいことと感想

とりあえず動かすことができるようになったので、ひとまず満足しました… とりあえず動かせるようにすることを優先にしたため、髪の出来があまり納得してないままになってしまったので作り直してみたいなという気持ちがあります。

一通りやってみた感想としては、モデルの作成はほんとに大変でモデラーの人たちは偉大だな…って改めて思いました。
素人がいきなり最初からモデルの作成に手を出すとよくわからない用語に戸惑ったり、ツールの使い方がわからずに迷ってしまったので、VroidなどのVRMを出力できるソフトで作りながら学びつつ、改変をするってやり方のほうがよいかもしれないなと感じました。

2019年振り返って

1年を振り返るやつやったことなかったのでやってみる。

今年振り返って

今までよりも良い年になったなって思ってる。 そう思う一番の理由は今年の中ごろに転職をして環境ががらっと変わったことが大きい。
転職して技術へのやる気がなくなるとか起きないかな?って心配してたけどもむしろやりたいことが増していってる。 Blenderで3Dモデリング急に始めるとかやった。(最近できてないがやる気はまだある)

2019年の目標

若干おぼろげだったけども大体以下のような目標を立ててたと思う

  1. コードを毎日書く
  2. 転職をする
  3. 運動をする
  4. 本を読む

他にもあった気がするけども覚えてないので、たぶん大したことない目標だと思う。

各目標についての振り返り

コードを毎日書く

おおむね達成できたと思う。

途中からgithubのアクティビティは途絶えてしまってるけども、会社でのコードはbitbucketで管理してたためであってコード自体はかけていた。 転職で環境が変わって1か月は家でコードを書く余裕がなかったのだけれども、最近は書く余裕も生まれてきてよいなと思ってる。

ただ近年まれにみるレベルでSEKIROというゲームにドはまりしてしまい、11月は余暇をほとんどSEKIROに費やいしてしまっていた…。(トロコンまでしてしまった…)

転職をする

できました。

大手?SI系からweb系?になりました。(web系の定義がよくわからん・・・)

今年良かったともう要因の8割はこれですね。前職は割と人権がないレベルで開発環境が極悪だったのですが、ようやく人権を得られるようになってとても快適です。回線速度が1Mbpsなかったり仮想でしか開発しちゃ駄目とかそんなの無かった!!!!!
前職なかなかやばめの人がリーダーにいたりして愉快な話が大量にあるけど、まあ転職できたのでもういいやでなかったことにしてる。

それ以外にも、周りの人が自分よりもスキルが高い人がいる環境になったことでどうしてこの方法がよいのか、なぜだめなのかの理由をちゃんと説明してもらえることで、納得感のある開発を行うことやレビューが聞けるようになったのもよかったです。 自分のレベルの低さも実感できるようなったので頑張っていかないと・・・

運動をする

目標を立てたかを覚えてなく指標もなくて達成したのかを判定できるか微妙…
だけど振り返ってみる。

Fitbitを付けてるおかげで自分が運動しているかどうかを見てみたところ、1か月に1回のペースでランニングをしてました。自分にしてはまあまあしてる・・・?

話題のリングフィットを年末に手に入れることができたので来年はもっと運動してると自分を信じてます。

本を読む

amazonで今年買った本の履歴をみたところ以下の本を読んでた。

  • FACTFULNESS(ファクトフルネス)
  • 岩田さん 岩田聡はこんなことを話していた
  • エッセンシャル思考 最少の時間で成果を最大にする
  • メモの魔力 The Magic of Memos (NewsPicks Book)

思ったより読んでなかった・・・
あと購入履歴みてると転職してから本の購入頻度が激減してた…
ただ転職というよりはゲームにドはまりしたのがかなりの原因の気がする…スマブラとかSEKIROとか…
転職後に購入した漫画以外の本はSEKIROの画集と年末に理科系の作文技術を買っていた。 これを機に文章能力の向上に取り組みたい。 来年はもっと本を読むようにしたい。

来年の目標

忘れないように来年の目標もここで上げておきたい

  1. 技術書典で本を出す
  2. LTなどで発表をする
  3. 3Dのことをちょっと理解する
  4. 3Dプリンターで複雑なもの作ってみる
  5. 新しい言語を勉強する(Rust興味ある)

技術書典はもう申し込んでて確定しているので落とさないように執筆していく!

3Dは前々からやりたいと思ってて年末にThree.jsをちょっとだけかじったので継続してやりたい。

まとめ

比較的やろうとおもってたことを達成できたよい年だったと思う。 来年も頑張っていきたい。

Chrome拡張+WebWorkerでTensorflow.jsを動かそう!

この記事はJavaScript Advent Calender2の11日目の記事です。

qiita.com

初めてのAdvent Calender参加でワクワクしています・・・!
この記事ではTensorflow.jsをChrome拡張+Web Workerで動かすためにやったこととTensorFlow.jsを使ってみての感想を書きたいと思います。

対象としては、Chrome拡張を少し触ったことがある人・Tensorflow.jsを少し触ったことある人が両方を組み合わせるためにはどうするかがわかるようになるということを考えてます。

はじめに

深層学習を使うことで高度な機能も簡単にできるようになったことで、webアプリに組み込んで便利な機能を作りたいという衝動が抑えきれなくなってくることはないですか? 私はあります。
抑えきれない衝動を何にむけようかな?と考えた際に、最近の悩みを機械学習で解決しようともくろみました。Twitterでいいイラストが流れてきたのでその人のメディア欄を見に行ったら飯テロ画像をたくさん見て苦しむという悩みを思い出しました。 そこで、機械学習の力で画像の種類を特定し見たい画像だけを表示するchrome拡張を作るためにTensorFlow.jsを組み込んで画像の種類を特定して飯テロ画像を見ないようになるアプリを作って遊んでみました。

動作させるとこんな感じになりました。最初は飯画像だけ消そうと思ったのですが、ついでにソシャゲのスクショも消せるようにしてみました。猫ちゃんのイラストだけが残っています。

f:id:s-haya:20191210005509g:plain
動作画面

ストアに公開しようかと思ったけども、TwitterのウェブアプリがVirtualScrollになっているため、スクロールすると消した画像が復活するということが起きてしまい、あまり実用的でないなと思ってまだ公開はしてないです。 自分で使うぶんにはTimerで監視して定期的に削除するって処理を加えて使ってます。ただ割と重たくなってしまってるのでうーん・・・って感じです。

作ってみて学んだことやはまったポイントをまとめて共有できたらなと思っています。

Tensorflow.jsって?

深層学習といえばPythonというイメージが強いと思うのですが、Tensorflow.jsを使えばなんとブラウザ上で深層学習ができます!

特に良いと思っている点としてKerasのモデルを変換する仕組みが公式で説明されているので、Kerasで公開されているor自作のモデルをwebに組み込んて使うことができ応用がきくところが素晴らしいなと思っています。最近はAutoMLでTensorflow.jsで使うようにモデル出力、インポートまでできるようになっているみたいで更に敷居が下がってほんとに良いなと思います。

TensorFlow.jsどう?

Web Workerでもwebgl backend で高速に動作するようになってメインスレッドを専有せずに使うことができるようになってるのでかなり実用的になってるなと思います。(まだchromeだけみたいですが)

実用的になってるなとは思う一方で使い所も難しいなと思っていて、画像解析のような一回だけ演算して結果を得ればいいようなユースケースではあまりメリットを享受できないなと感じています。そのような場合はGPUましましのサーバーで処理するようなシステムを構築したほうがマシンパワーゴリ推しで高速演算できてよい気がします。

ビデオなどリアルタイムな結果が欲しいアプリではネットワークを経由せずに結果を取得できるので活用できると思っていて、そういったユースケースで使われていくと面白いなあって思います。
あと個人開発みたいなできるだけサーバー代を節約してアプリを開発したい場合でも活用できると思っています。

より実用的にするためにはモデルの軽量化や高速化の知識が必要そうな気配がぷんぷんするので機械学習の知識もつけなきゃな・・・と思っています。

chrome拡張でTensorflow.jsを動かすうえではまったところ

チュートリアルを試してみてすんなり実装できそうだなと思ってたけども意外とつまってしまうことがありました。 大きく詰まったのは以下の3点です。

  • backgroundでGPUが使えなかった
  • chrome拡張では画像のDomを直接Tensorflow.jsのモデルに入力できない
  • WebWorkerをファイルから読み込みを指定して動かせない

それぞれについて、少しだけ内容に触れていきたいと思います。

backgroundでGPUが使えない

Chrome拡張ではbackgroundというタブを閉じる、作成などのイベントを検知するための環境が提供されています。( https://developer.chrome.com/extensions/background_pages

backgroundに各ページがどのような通信をしたのかを検知できるAPIがあったので、APIで画像データの通信を監視して画像を取得するたびにモデルを動かして画像の種類を予測するというやり方を最初行おうとしました。 ところが、backgroundでモデルを動かしたところGPUを使えずcpuでの演算になってしまい低速になってしまいました。

そのためbackgroundではなくwebWorkerで動かすようにして、メイン処理を止めることなく予測するようにしました。

chrome拡張ではHTMLImageElementを直接Tensorflow.jsのモデルに入力できない

Tensorflow.jsでは画像データをTensorに変換するAPIとしてtf.browser.fromPixelsが提供されており、この入力データの形式の一つにHTMLImageElementがあるので、例えば以下のようなコードで画像データをモデルに入れる形式に変換することができます。

const img = document.getElementById('hoge');
tf.browser.fromPixels(img).print();

これと同じようなことをChrome拡張でやろうとしたところ、以下のようなエラーが出てしまいます。

Uncaught (in promise) DOMException: Failed to execute 'texImage2D' on 'WebGL2RenderingContext': Tainted canvases may not be loaded.

これはWebGLで異なるオリジンを読み込む際にCORSが設定されていないため起きてしまう問題のようです。

そのため、CORSの設定を行うかHTMLImageElementを作成して変換して使うという処理が必要みたいでした。 今回はWebWorkerを使おうとしていてどちらにせよ画像データを作成する必要があったので後者の方法を採用しました。(WebWorkerではElementにアクセスできないため)
自分はWebWorker内でOffscreenCanvasに描画してtensorに変換する処理を行いました。下記のコードでcanvasをtf.browser.fromPixelsに指定すればTensorに変換できます

const img = '' // 画像のURL
const imgBlob = await (await fetch(img)).blob();
const bitmap = imgBlob.type.match(/svg/) ? undefined : await createImageBitmap(imgBlob);
if(bitmap) {
  const canvas = new OffscreenCanvas(bitmap.width,bitmap.height);
  const c = canvas.getContext('2d');
  c && c.drawImage(bitmap,0,0);
}

WebWorkerをファイルから指定して動かせない

これがなかなかうまく動かせなくてかなり詰まったポイントでした・・・

WebWorkerを作るためには通常以下のようにファイルを指定して作成すると思います。

const worker = new Worker('hoge.js', {type: 'module'});
・・・

chrome拡張で他のファイルを読み込むためには通常のパスではなく、独自のパスを指定する必要があります。 手順としては以下のようになっています。

  1. "web_accessible_resources"に対象のファイルを指定する
  2. chrome拡張のファイル拡張子を付与するAPIであるchrome.extension.getURLを使ってファイルURLを指定する

これで取得したURLを使えば通常の画像やファイルを扱うことができます。 なので、以下のコードで動くはず・・・だったのですが、、、現実は非常、動きませんでした。

const worker = new Worker(chrome.extension.getURL('hoge.js'), {type: 'module'});
・・・

以下のようなエラーが出されてしまいました。

bundle.js:1 Uncaught (in promise) DOMException: Failed to construct 'Worker': Script at 'ワーカーのパス' cannot be accessed from origin 'URL'.

どうもChrome側のバグみたいで、アクセスできないリソースを指定しているというふうにみなされてしまっているみたいです。 159303 - chromium - An open-source project to help move the web forward. - Monorail

しょうがないのでjsのファイルをダウンロードしてURL形式に変換するようにしたらWebWorkerが動くようになりました。

const worker = await fetch(chrome.extension.getURL('worker.js'));
const js = await worker.text();
const blob = new Blob([js], {type: "text/javascript"});
const url = URL.createObjectURL(blob)
const workerClass: any = comlink.wrap(new Worker(url));

これで、あとは普通のWebWorkerを扱うようにできました。

このやり方でいいのか悩ましいのでよりよい方法があったらぜひとも教えていただきたいです。

まとめ

一応作ったコードを貼っておきます。 https://github.com/s-haya-123/showIllustOnlyExtention/tree/master/src

ただ、整理は全くしてないので可読性は保証できないですが・・・
記事では触れてなかったのですがWebWorkerを使う方法としてComlinkを使ってみたところかなり使い勝手がよかったです。 WebWorkerはMessagePassingが扱いづらいからな・・・って思ってたけども、これだったら今後も積極的に採用してもよいなと思いました。

Tensorflow.js、ブラウザで高度なことが次々試せそうなので今後もどう使っていくかを考えていきたいと思ってます。