Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

エンジンを切り離し、初回起動時にVVPPをダウンロードするような機構を備える #1194

Open
3 tasks done
y-chan opened this issue Feb 11, 2023 · 17 comments
Labels
OS:linux OS:mac OS:win 機能向上 要議論 実行する前に議論が必要そうなもの

Comments

@y-chan
Copy link
Member

y-chan commented Feb 11, 2023

内容

VOICEVOXは、コアに含まれているキャラクターの各モデルや深層学習エンジンが大きな容量を占めるので、初期ダウンロード容量がとても多くなっています。
そこで、0.14.0から実装されたVVPP機能を使い、初回起動時にダウンロードするような仕様にするのが良いのでは、という提案がなされました。
https://discord.com/channels/879570910208733277/893889888208977960/1073951061271912478
このような実装をしていくにあたり、いくつか問題がありそうです。

  • ダウンロードするVVPPのバージョン指定をどうするか
    • エンジンとエディタのバージョン値が必ず一緒になるとは限らないのでは?
  • アンインストール時に、VVPPでインストールしたエンジンが残りそう

Pros 良くなる点

インストール時の容量が少なくて済む

Cons 悪くなる点

取り組むまでに様々問題がありそう

実現方法

起動時にVVPPをダウンロードするようにする

VOICEVOXのバージョン

0.14.0

OSの種類/ディストリ/バージョン

  • Windows
  • macOS
  • Linux
@y-chan y-chan added 機能向上 要議論 実行する前に議論が必要そうなもの labels Feb 11, 2023
@Hiroshiba
Copy link
Member

すみませんissue化していませんでした! ありがとうございます!!

ダウンロードするVVPPのバージョン指定をどうするか

これは.envに書くのが丸そうに思いました!
こうしておけばActionsにすでにVOICEVOX_ENGINE_VERSIONがあるので、それを.envに書きたす感じでできそう?

アンインストール時に、VVPPでインストールしたエンジンが残りそう

これ今思えばそもそも現状でもVVPPインストールエンジン全部残りますね 😇
アンインストール時に文字列として案内するとか、使い方に書き足しておくとかで良いかもとちょっと思いました。
(さすがに後者だと案内足りないかなぁ・・・。)

@Hiroshiba
Copy link
Member

アンインストールしても残るのは一旦仕方ないとして、案内をしっかりしつつもう進めちゃっても良いのかなと思いました!!

追加の問題として、エンジンアップデートをどうエディタ側で行うのかがありました。
VVPPにアップデート機構が無いので、まずそこからかもです。

@Hiroshiba
Copy link
Member

Hiroshiba commented Aug 18, 2024

エンジンアップデートをどうエディタ側で行うのか

これとあとインストール周りも含めてですが、いいアイデアが思いついたのでメモです。


インストール時ではなく、electronが起動した後、今のレンダラープロセスを表示する前にダウンロードするのがいい気がしました!
別のレンダラープロセスで、デフォルトエンジンのアップデートやインストールを行うかのUI を表示してあげるのを想像してます。

シーケンスはこんな感じ・・・?

アプリ起動、初回

sequenceDiagram
  actor User
  participant Renderer1
  participant Renderer2
  participant Electron
  participant VVPP
  participant Engine
  User ->> Electron: 起動
  Electron -) Renderer1: 起動
  Renderer1 ->> User: 表示
  Electron ->> Electron: VVPPダウンロード
  Electron ->> +VVPP: インストール
  VVPP -->> -Electron: 完了
  Electron -) Engine: 起動
  Electron -) Renderer1: 終了
  Electron ->> Renderer2: 起動
  Renderer2 ->> User: 表示
Loading

アプリ起動、2回目以降、アップデートがある場合

sequenceDiagram
  actor User
  participant Renderer1
  participant Renderer2
  participant Electron
  participant VVPP
  participant Engine
  User ->> Electron: 起動
  Electron ->> Electron: アップデート情報取得
  Electron ->> Renderer1: 起動
  Renderer1 ->> User: 意思確認
  alt 更新する
    User -->> Renderer1: OK
    Renderer1 ->> +Electron: VVPP更新
    Electron ->> Electron: VVPPダウンロード
    Electron ->> +VVPP: インストール
    VVPP -->> -Electron: 完了
    Electron ->> +VVPP: アンインストール
    VVPP -->> -Electron: 完了
    Electron ->> +VVPP: リネーム(アップデート)
    VVPP -->> -Electron: 完了
  else 更新しない
    User -->> Renderer1: NO
    Renderer1 ->> Electron: 続行
  end
  Electron -) Engine: 起動
  Electron -) Renderer1: 終了
  Electron ->> Renderer2: 起動
  Renderer2 ->> User: 表示
Loading
  • ダウンロードやインストール状況を確認したくなりそう
  • 起動時VVPPインストールを流用する場合、たぶんアップデートに対応していない(handleMarkを呼んでない)かもなので要確認
  • デフォルトエンジンは VVPPに対応してない気がするので、そこも要確認

@Hiroshiba Hiroshiba changed the title エンジンを切り離し、初回インストール時にVVPPをダウンロードするような機構を備える エンジンを切り離し、初回起動時にVVPPをダウンロードするような機構を備える Aug 19, 2024
@Hiroshiba
Copy link
Member

Hiroshiba commented Aug 19, 2024

段取りを考えてみました!
プロジェクトブランチがいるかなと思ってましたが、たぶんなしでも進められそう。
(ビルドする際の.envを置き換えなければずっと挙動を同じにできそうなので)

  • デフォルトエンジンかつVVPPが設定できるよう型と実装を変更 完了
  • アーキテクチャごとのDL先を指定できるよう設計し、アプデ確認用の型を考える
  • .envでVVPPアプデ確認用URLを指定可能にする
  • 指定されているVVPPがなかったら確認後にインストールし、使えるようにするようにする
  • インストールできるかのテストコードを書く
  • インストール中の進捗を表示する&オンメモリじゃなくする
  • デフォルトエンジンと同じIDを持つvvppをインストールできないようにする
  • READMEでデフォルトエンジンをVVPPにする方法の案内を工事中として書く
  • 新しいVVPPがあればダウンロード&更新するようにする
  • ウェルカム画面を作ってデフォルトエンジンのインストール・アンインストール中に表示する
  • アップデートするかどうかの意思確認をし、アップデートをパスできるようにする
  • アップデートできるかのテストコードを書く
  • ファイル不足などでエンジン読み込みエラーになった場合でも再インストールできるようにする
  • mainブランチのデフォルトエンジンをVVPPにする
  • .env内のエンジン情報を整理する(type: urlもつくる?)(工程の後ろの方にあるのは変更回数を少なくするため)
  • .envの情報からエンジン情報を作る関数の処理を、エンジンマニフェストから情報を得るようにする
  • READMEでの.envの設定方法をVVPPメインに切り替える
  • アンインストールしてもエンジンは残るので、エンジンの消し方を使い方やQ&Aで案内する

@Hiroshiba
Copy link
Member

Hiroshiba commented Aug 19, 2024

最新版のVVPPを取ってくるときのデータ構造

electron-builderの自動アプデ用のlatest.ymlの仕様を見るに、

  • 最新バージョン
  • リリース日
  • リリースノート
  • OS・アーキテクチャごと
    • URL
    • ハッシュ値
    • サイズ

などがあれば良さそう。
📝 分割ダウンロードにも対応しとかないといけない

ちなみにwindowsはarm64環境でもx64のexeが動くらしく、持ってくるVVPPのアーキテクチャは注意が必要。

将来的にwindows arm64版VVPPができることを見越すと、ホストのアーキテクチャに合うものを探し、なければ実行中のNodeのアーキテクチャ(process.arch)に合うものを探すと良さそう・・・?
でも親子でアーキテクチャずれてると起動に失敗しそうな気もするので、ずっとNodeに合うアーキテクチャを使うのが丸そう!

@sevenc-nanashi

This comment was marked as off-topic.

@Hiroshiba
Copy link
Member

Hiroshiba commented Aug 19, 2024

zip版

特に特別扱いせず、エンジンを同梱しない形が良さそう!

Discordでのやりとり
サボ寝ルネ — 今日 22:50
あとはZIP版をインターネット環境のないPCへインストールするために使っている人向けの対応?

ヒホ — 今日 22:50
あ~~~~~たしかに!!!!!!!
VVPPの手動インストールでいけそう。あざます!!!!!
いや、アプデはそれでいいけど、初回インストール時は・・・・・・。
* vvpp同梱
* vvpp入れるように案内
* zip版はエディタとエンジンを分けない
ネット環境ない人向けに、初回起動時のvvppダウンロードは自動じゃなくした方が良いのかぁ。 

サボ寝ルネ — 今日 22:59
「zip版はエディタとエンジンを分けない」はmac版のautoUpdater実装時に面倒なことになりそうな気がします。
mac版のautoUpdaterはzip版をDLしてdmg版でインストールしたパッケージを置き換えるみたいな感じになっているっぽいです。
(autoUpdater用のzipとユーザー用zipに分けるとかもあるがややこしそう)

ヒホ — 今日 23:02
なるほどぉ。。。
zip版とパッケージ版でいろいろ変えるのも大変だし(たしかビルドプロセスが共通)、どちらもエンジン/vvppが付属しない形が良さそう。
公式サイトのzipダウンロードするボタンの近所に「vvpp要るよ~」って案内するか、vvppダウンロードボタンも配置すれば良さそう。
やー助かりました、ありです!!!

ネット環境がない場合

公式サイトのダウンロードボタンの近くに「エンジンは追加インストールが必要」な旨の案内をすると良さそう。
あとついでにVVPPのダウンロードボタンも近所で案内すれば良さそう。

@Hiroshiba
Copy link
Member

デフォルトエンジンのVVPPの展開先を、追加エンジンのvvpp展開先と同じにするか、別のディレクトリにするかで迷ってます。
安全方向に倒すとディレクトリは分けた方が良さそう。でもアンインストールの作業とか、消してもらわないといけないファイルの案内とかは若干複雑になる。
ディレクトリを一緒にしてしまっても実装でカバーはできそう。ただエンジン情報のロード周りは若干ややこしくなる。

一旦実装見てから判断しようと思います!
ディレクトリが一緒だったら起こりそうな問題とかあれば知りたみ・・・!

@Hiroshiba
Copy link
Member

進捗です。

デフォルトエンジンのVVPPの展開先は、とりあえず今のvvppインストール先と同じとこにしてみようかなと思います。
扱いがそっちのが簡単なはずではあるので。問題があったら(アプデまでに)変えれば良さそう。

.envでvvpp指定できるようにする前に、先にエンジン情報周りのリファクタリングをしようと思います。

  1. .envにengineInfoを書かなくて良くする。pathの指定がたぶん現状間違ってる、ディレクトリを指定しないといけない
  2. エンジン情報マネージャーとエンジンプロセスマネージャーを分ける?
  3. ついでにelectronへの依存をなくしてもよい
  4. .envの情報から、エラー情報を返す関数作っても良いかも、あとでも良いかも(エンジンが見つからないとか、vvppが未インストールとか)

@Hiroshiba
Copy link
Member

.envにengineInfoを書かなくて良くする。pathの指定がたぶん現状間違ってる、ディレクトリを指定しないといけない

ここのリファクタリングをしようとしたのですが、色々あって諦めました。

まず実行ファイルを指定する形になっているので、ディレクトリを指定する形に変えたいのですが、ビルド周りにも影響が出てくるのでちょっと手間そうでした。
あとエンジンマニフェストを信用してアクセスする URL が決まる形にしようとすると、ブラウザ版の実行に支障が出そうな気がしました。
それと.envのフォーマットが変わると開発者はそれに追従する必要がありますが、vvppをデフォルトエンジンとして利用可能になったタイミングでまた変わりそうなのもちょっと手間そうでした。

総合的に考えて、.envのエンジン情報を整理するのは一番最後あたりに回そうかなと思います。

@Hiroshiba
Copy link
Member

5番目の デフォルトエンジンと同じIDを持つvvppをインストールできないようにする を進めたいと思います!

@Hiroshiba
Copy link
Member

Hiroshiba commented Dec 6, 2024

とりあえず設計を考えたんですが、VVPPファイルからエンジンIDを簡単に得る方法がないことに気づきました 😇
とりあえずやる場合の手順メモです。

  • インストールしようとしているVVPPが、デフォルトエンジンのエンジンIDと被っているか把握したい
  • VVPPファイルはエンジンIDがわからない
  • 現状のVVPPインストールの流れの中でエンジンIDがわかるのは、VVPP断片を結合して7zでファイル展開したあとengine_manifest.jsonを読んだタイミング
  • デフォルトエンジンのエンジンIDと被ってるときにエラーにする妥当な方法は3つ
    1. vvppMangerにデフォルトエンジンの情報を渡しておき、VVPPの7z展開後にエンジンIDを確認してエラーを投げる
      • 手っ取り早いけど、vvppManagerがデフォルトエンジンの情報を知るという密結合になる
      • それは本来engineAndVvppControllerに任せたい
    2. vvppMangerにインストール前の確認用の関数を作り、VVPP結合→7z展開後にエンジンIDを返し、その後インストールするようにする
      • 展開したVVPPのパスをラップした適当なインスタンスとEngineInfoを返せば良い
      • 仮にエンジンIDが被っていた場合エラーになるけど、zip展開の完了を待たないといけず、エラーまでが長い
    3. 2とほぼ同じで、7z展開前に、VVPP結合→7zでengine_manifest.jsonの情報だけ抽出してエンジンIDを返し、その後7z展開→インストールするようにする
      • 考えられる限り一番良い
      • 7zがコマンドなので結構処理がややこしい

手っ取り早いのは1だけど、残り2つの方法もそんなにしんどくないので1は避けて良さそう?
他2つのうち妥当なのは3だけど、とりあえず2を実装が良いかも。あとで3に変えることもできるはず。

@Hiroshiba
Copy link
Member

.env周りメモ:
vvppデフォルトエンジンのテストを書こうとすると、今までのelectronテスト用の設定(.env)と、vvppデフォルトエンジン用の設定が必要になりそう。
コードを追っかけた感じ、これはテストファイルの中(.spec.tsの中)でテスト条件によって読み込む.envを切り替えるのが良さそう!

@Hiroshiba
Copy link
Member

Hiroshiba commented Dec 28, 2024

と思ってたけど、VITEの仕組みでimport.meta.envがビルド時に決まる(=playwright.configの中のdevServerのときに決まる)から、テストファイルの中で書き換えてもダメかも。( @sevenc-nanashi さんから指摘いただきました🙏)
となると・・・・・・・・こう・・・?

  • 大まかな方針としては、electron:e2eのときは2種の環境でテストを実行する
  • default_engine_infosを変更したdevServerを2つ用意する
    • .env読み込み→devServer作成→2つ目の.evn読み込み→別portでdevServer作成、みたいな感じで・・・
  • テストファイルの中で、どっちのサーバーに接続するかをテストごとに決める

だいぶ複雑だけど完成したら片方だけの経路になるはずなので、まあ許容できる・・・・・かなぁ。

@sevenc-nanashi
Copy link
Member

default_engine_infosを変更したdevServerを2つ用意する

ちなみに多分これはdist/main.js(backend/electron/main.tsの出力先)が競合するのも注意かも

@Hiroshiba
Copy link
Member

確かにdistが衝突して問題が発生しそうですね・・・・・・。
vite.config側も変更すれば迂回はできそうだけど、playwright.config・vite.config・spec.tsの三者を巻き込んだややこしい構造になりそう。

となるともう、経路が2つある間はdefault_engine_infosをprocess.envで上書きできるようにしてしまって、spec.tsのelectron.launchのenv引数経由で直接書き換える方がまだ綺麗な気がしてきました。
もちろんワークアラウンドなので上書き機構には理由をメモする感じで・・・。

@Hiroshiba
Copy link
Member

Hiroshiba commented Dec 29, 2024

インストール中の進捗を表示する&オンメモリじゃなくする

に取り組もうとしてます。
考えたことメモ:

  • 進捗表示は将来的にGUIになるのでそれに対応できるようにしたい
  • インストールはダウンロード・vvpp展開等いろいろあるので、今なにがどれくらい完了してるかわかるようにしたい
  • エラーが起こることも想定したい
  • 重い処理はファイル展開(7z、別プロセス)とダウンロードくらいで、どちらもWebWorkerはいらなそう
  • 将来的に途中でユーザーアクションを求める可能性も有り得そう
    • ボタンN個のダイアログくらい
  • キャンセルは不可で良さそう

実装方針のメモ:

  • とりあえずインストール関数から進捗をコールバックかEventEmitterで随時渡してもらう設計で良さそう
  • ユーザーアクションを求める場合がある(返り値を受け取る必要がある)からEventEmitterよりコールバック(というより関数渡し)が良さそう
  • とりあえずonProgressとonErrorだけで良さそう
  • onProgressのシグネチャはonProgress({type, progress: number, message?: string})とかで良さそう

ちょっと実装してみます!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
OS:linux OS:mac OS:win 機能向上 要議論 実行する前に議論が必要そうなもの
Projects
None yet
Development

No branches or pull requests

3 participants