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

50021番ポートが空いてなくて他のポートを使ったとき、それがサードパーティからわかるようにしたい #1738

Closed
Hiroshiba opened this issue Jan 21, 2024 · 23 comments
Labels
優先度:中 初心者歓迎タスク 初心者にも優しい簡単めなタスク 機能向上

Comments

@Hiroshiba
Copy link
Member

内容

50021番ポートが空いていなければ、ユーザーに通知しつつ他の空いてるポートで起動するようになりました。

もしこうなった場合サードパーティアプリからわからないので、最悪「VOICEVOX.exeは立ち上がったのにサードパーティアプリからエンジンと通信できない」状況になります。
これがどれくらい問題になるかはわかりませんが、できれば対処法を確立しておき、もっといえば解決策を実装したいです。

Pros 良くなる点

サードパーティの利便性が上がる

実現方法

パッと思いつく方法が3つあります。

  1. stdoutで特定の文字列を出力する
    • 例えばvoicevox:message=1行json参考
      • 1行jsonは例えば{"type": "enginePorts", "message": {エンジンID: 元のポートとか今のポートとかエンジン名とかの情報}}`
    • VOICEVOXを直接起動する系のサードパーティアプリならこれでOK
    • ぶっちゃけこれが良さそう
  2. ファイルに保存する
    • config.jsonが保存されてる辺りにmessage/enginePorts.jsonとか保存すれば良さそう
      • 書き込んだ時間も書いとくと軽いバリデーションに使えるかもしれない
    • ファイルアクセスが衝突したとか起こり得そう
  3. voicevox.exe --getEnginePortsと叩くとstdoutで返すようにする
    • electronの取り回しがかなり複雑になりそう
    • やるにしても1と2が実現してからで良さそう

その他

やり方とフォーマットさえ決まればかなり簡単だと思います。(特に1の方法)

まずはそれを決めるとこからかなと。ご意見募集中です。(もちろん実装でも大歓迎です)

@nmori
Copy link
Contributor

nmori commented Jan 21, 2024

すみません、Issue起こしていただいてありがとうございます。

手段としては

  • プロセス間通信(IPCなど)
  • 標準入出力
  • ファイル
  • レジストリ

出力方法としては

  • 単純なテキスト or CSV
  • JSON
  • XML

などがパッと思いつきます。(元提案にもありました)

マルチエンジンみたいなものがあるので、フォーマットはJSONあたりが良さそうかなぁとおもいました。
反面、出力手段については プラットフォームに汎用性をもたせようとするとファイルになります。

UXを考えたときには、EXEファイル位置の特定/指示が必要になるという点はサードパーティからすれば できれば解消したい課題になるかもしれません。
(そういう意味では、出力手段はいくつか用意したくなるかもしれません)

あと、ツールからVOICEVOXを立ち上がることが前提にすると、1つのツールしか連携できなくなるので、案2、3は使いやすそうです。(ファイルが格納されるフォルダがある程度決まっていれば、何も設定せずに連携できそうです)

(もう少し議論&本作業にかかわれたらとおもってます)

@manju-summoner
Copy link

誘導ありがとうございます。
標準出力かファイルへの保存が良いかなと思います。

標準出力

サード側がVOICEVOXの実行ファイルのパスを把握していることを前提とするのであれば、この方法が一番簡単かつ直感的なのかなと思いました。

ファイル

こちらも使い勝手は良さそうです。
ただし、VOICEVOXの設定フォルダだけでも%AppData%\voicevox%AppData%\voicevox-cpu %AppData%\voicevox-cudaと別れている他、SHAREVOX等のVOICEVOXをフォークしている他のアプリへの対応のことも考えると、設定フォルダのパスを取得する方法が別途無いとファイルの場所を見つけるのが大変かもしれません。

具体的には

  • editor_manifest.jsonといったファイルに設定フォルダのパスを記載してvoicevox.exeと同じフォルダに配置する
  • %AppData%\voicevox_editor\エディターの名前やUUID\等、決め打ちできるフォルダに出力する

などでしょうか。

UXを考えたときには、EXEファイル位置の特定/指示が必要になるという点はサードパーティからすれば できれば解消したい課題になるかもしれません。

このissueの趣旨からは外れますが、%AppData%\voicevox_editor\エディターの名前やUUID\等の固定されたフォルダ内にvoicevoxの実行ファイルのパスが保存されるようになれば、サードパーティー側はエディターの名前やUUIDを知っておくだけでエディタの実行ファイルを見つけられるようになるのでとても嬉しいです。

@Hiroshiba
Copy link
Member Author

@nmori さん、 @manju-summoner さん、ご意見ありがとうございます!!

使い勝手を考えると、固定ディレクトリに直接配置がいいのかなと思いました!
保存タイミングとかの不正確性はありますが、スケールしやすいかなと。

voicevox.exeと同じフォルダに配置する

こちらは確か場合によって結構難しくて、管理者権限がある場所とかだとファイル保存が難しかったりするかもです。
なのでやるならホームの下の%APPDATA%以下なのかなと思いました!

VOICEVOXの設定フォルダだけでも%AppData%\voicevoxや%AppData%\voicevox-cpu %AppData%\voicevox-cudaと別れている他

ちなみにこちらは1年くらい前にvoicevox統一されていたりします!
最近のバージョンのボイボエディタをフォークしているアプリは全部%AppData%/アプリ名/confg.jsonに設定ファイルがある・・・はず・・・?


まとめるとこうでしょうか。

  • ファイル出力が良い
  • 決め打ちフォルダが良い
    • %AppData%\アプリ名\の下で統一

他の情報も保存できるように、実行中の情報を保存できるようruntime-info.jsonを作り、中でengineInfosキーを作って、エンジン名やエンジンIDやポートをリストで保存するのはどうでしょう?
(エンジンIDをキーにした情報にしていないのは、エンジンIDがわからない時用のためです)

@manju-summoner
Copy link

最近のバージョンのボイボエディタをフォークしているアプリは全部%AppData%/アプリ名/confg.jsonに設定ファイルがある・・・はず・・・?

なるほど、そうだったんですね。
それであれば決め打ちでファイルの場所を探せるので実装も簡単そうです。
ありがとうございます!

'runtime-info.json'に保管する情報も、特に不足は無いかと思います。

@nmori
Copy link
Contributor

nmori commented Jan 26, 2024

いったん、上記の話をコード化したものを、PRしてみようとおもいます。

nmori added a commit to nmori/voicevox that referenced this issue Jan 26, 2024
* ファイルは runtime-info.json に書き出し
* エンジン全起動もしくは個別起動/終了のタイミングで更新
@Hiroshiba
Copy link
Member Author

@nmori おー!!!!ぜひぜひ・・・!!!
不明な点あればなんでもお聞きください!!

@nmori
Copy link
Contributor

nmori commented Feb 3, 2024

実装側で会話が進んでいますが、こちらの方が会話に埋もれないので 書き込んでみます。

吐き出すデータ形式をこういう形に据えています。
型を一度決めると変えづらいところがあるとおもうので、この情報を使われる方がいれば
これでよいか、他に情報が必要か コメントいただきたいです
(特に、サードパーティに関係されている方お願いします)

{
    "versions": {
        "fileFormat": "1.0",
        "VOICEVOX": "999.999.999"
    },
    "engineInfos": [
        {
            "uuid": "074fc39e-678b-4c13-8916-ffca8d505d1d",
            "url": "http://127.0.0.1:50021",
            "name": "VOICEVOX Engine",
            "executionEnabled": true,
            "executionFilePath": "D:\\VOICEVOX0.15.0\\run.exe",
            "executionArgs": [],
            "type": "default"
        },
        {
             
        }
    ]
}

@manju-summoner
Copy link

必要な情報がわかりやすく保存されていて良いと思います!

@nmori
Copy link
Contributor

nmori commented Feb 4, 2024

ありがとうございます。
では、他に反応がなければ ver1としてはこのスタイルで行ってみたいと思います。
(まぁ、問題があれば次のIssueで修正ということで)

@Hiroshiba
Copy link
Member Author

Hiroshiba commented Feb 6, 2024

@nmori まとめありがとうございます!!

ファイルフォーマットのバージョンはルート直下が良いかもです!(versionsの下だとずっとversionsを変えられなくなるため)
あとはまあ、整数値のが意外と管理が楽かもです(経験則ですが😇)。既存のキーが消えるなどの破壊的変更で数値を増やす、みたいな感じかなと。
minorも必要な場合は、破壊的変更はmajorを、キーが増えるだけならminorを更新…とかでしょうか。

VOICEVOXとなってる部分は、エディタをforkしている場合は名前が異なるので汎用的な名前が良いかもです。有用な情報でしょうし、appVersionとかにしてroot直下に置くのはどうでしょう?
(editorの下にversion作るとかでも良いかも)

エンジンの情報はYAGNI原則に従い、必要なものだけにしておきたい気持ちがちょっとだけあります。
けどまあいろいろあると便利だとは思うので、「name,uuid,url以外は将来変わりうるし、変更しても破壊的変更として扱わない」としてドキュメントで案内するとかどうでしょう?

@nmori
Copy link
Contributor

nmori commented Feb 6, 2024

@Hiroshiba ありがとうございます。ではこのような形にシンプルにする感じで進めてみましょうか。

  • ファイルバージョンは細かく見たほうがいいかなと思ったものの、構造が変わらなければサードパーティ側の対処でなんとかなるので、構造を判断するバージョンを数字でいれる
  • YAGNI原則に沿って、サードパーティが具体的に使わなさそうなものを削る
{
    "formatVersion": 1,
    "appVersion":"999.999.999",
    "engineInfos": [
        {
            "uuid": "074fc39e-678b-4c13-8916-ffca8d505d1d",
            "url": "http://127.0.0.1:50021",
            "name": "VOICEVOX Engine",
            "executionFilePath": "D:\\VOICEVOX0.15.0\\run.exe",
            "executionArgs": []
        }
    ]
}

@Hiroshiba
Copy link
Member Author

Hiroshiba commented Feb 7, 2024

@nmori 方針良いと思います!

「構造が変わったらバージョンを変える」だと、動作に問題がない変更(要素を足すとか)と、動作に問題がある変更(要素が消えたとか、入ってる内容の意味を変えるとか)を区別できなくて不便かなと思います。
なので、「意味や構造に破壊的変更が入った時にバージョンを変える」方針が良いかなと!

ちなみにexecutionFilePathが入ってますが、これは起動に便利だからでしょうか?
このファイルは実行後にできる、実行中のアプリの状態を調べるためのファイルなので、もうすでに起動済みだから起動に必要なパラメータ書いても使い道がないかも…?

@nmori
Copy link
Contributor

nmori commented Feb 7, 2024

たしかに。サードパーティサイド側で想定していた項目からいけば、

  • 辞書やプリセットなどの情報のやりとりをしたくなる ⇒ APIでやればOK
  • プロセスがおきてるかみたくなる ⇒ APIにアクセスすればわかる
  • ツールからエンジンを個別起動するためのパスをしりたい ⇒関連ツールがエンジンだけ起動したいケースでは必要。今はファイルが残るので、パス情報だけはつかえる。このあたりは A.I.Voiceあたりも似た感じではある。
  • ツール終了時にVOICEVOXも終わらせたい ⇒ 今のデータだけでは達成できない。本体のプロセスIDの追記が必要

@manju-summoner
このあたり(executionFilePathを記載するかどうか)、ご意見伺いたいです。
ツールからはエンジンを直接起動したいケースはまぁあるかなぁと思う反面、ポート情報を得るという主目的としてはズレがあります。最小にしたいものの、必要だとわかっているならば実装するのがよいだろうとおもうので、その境界線を判断したい感じです。

ここでの会話でいいね、となれば追加、んまぁ・・・という感じならYAGNI原則に従って削除という感じにしたいので、ご意見伺いたいです。

@Hiroshiba
Copy link
Member Author

Hiroshiba commented Feb 7, 2024

@nmori あ、すみません!言葉足らずでした。

このruntime-info.jsonファイルはVOICEVOX.exe起動後に手に入る情報なんですよね。つまりここに書き込まれてる情報は、いったんVOICEVOX.exeを1回以上起動しないと得られない。
なのでもしエンジンのパスが必要なのであっても、未起動だった場合はファイルがなかったり、かつ起動済みであってもVOICEVOXのアプデをしていれば情報が変わっている可能性があるので、サードパーティから使う場合を考えると不便だよなーという感じです。
もし必要な場合は別の手段にしたほうが良いかも?

@nmori
Copy link
Contributor

nmori commented Feb 7, 2024

@Hiroshiba
「A.I.Voiceあたりも似た感じ」と書いてた点がこの部分で、あちらの思想は「本体がエンジンを認識して駆動できることを確認したらファイルに残す」みたいになっていました。なので、未起動だったりすると情報を参照するサードパーティからは使えなかったり。A.I.Voiceが処理フローにおちついているのは、処理タイミング的に合理的だったからなのかな?と思って参考にしました。(実際にアプデまで考えると、ファイルを吐き出すタイミングなど結構ややこしくなるのかなぁ、と。まぁTTSは別にWindows側からの参照の仕組みがあるから実際にはあまり問題になってないだけかもしれません)

ですが、A.I.Voiceに合わせる必要もないので、別手段として作って体感をあげるというのもありですね。では、他の方にもコメント頂いた上で、「そこまで難しくしなくても…」という感じであれば最小実装、いやいや必要だねとなれば、これとは別に実装提案していくことにしますね。

@Hiroshiba
Copy link
Member Author

Hiroshiba commented Feb 8, 2024

AIVOICEの仕様なるほどです。
VOICEVOXも、将来的にもしエンジンがエディタに付属しない形になった場合はエンジンの場所が固定ではなくなるので、実行後にしかしゅとくできなくなるかもです。そうなったらruntime-info.jsonに書き加えたほうが良いかも。

他の方にもコメント頂いた上で、「そこまで難しくしなくても…」という感じであれば最小実装、いやいや必要だねとなれば、これとは別に実装提案していくことにしますね。

ぜひぜひ!!
例えばissueを作って頂くだけでもとてもありがたいです。もし誰かその機能を求められた時に意見を集められるので…!

@manju-summoner
Copy link

いったんVOICEVOX.exeを1回以上起動しないと得られない

インストーラー版であればインストール処理中に実行ファイルのパスをファイルやレジストリに保存するというのが正道なのですが、zip版の場合はインストール処理というものが存在しない都合上、どうしても実行後にしか実行ファイルのパスを記録できないという事情があります。
実行後にしか情報を取得できず、実行ファイルのパスが変わる可能性があることを考えても、あれば嬉しい情報であることは確かです。

とはいえ、この情報がなくてもインストーラーのデフォルトのインストール場所を決め打ちするだけでも大半のユーザーをカバーできる上、zip版だけを想定して実行後にしか保存されないファイルに実行ファイルのパスを記録するという気持ち悪さもあるのも確かです。

いずれにせよ、最優先されるべきはポート番号の保存処理なので、まずは最小実装を行い続きは別Issueでというのが良いかと思います。

@nmori
Copy link
Contributor

nmori commented Feb 8, 2024

コメント頂きありがとうございます。

議論をみながら感じたのは、この情報ファイル書き出し機能はエンジン側に実装すべきものかもしれませんね。
(PRのほうは最小実装で出しますね。最終的にマージとするか、エンジン側へPRを移すかは相談とさせてください)

nmori added a commit to nmori/voicevox that referenced this issue Feb 8, 2024
Hiroshiba added a commit that referenced this issue Feb 13, 2024
* 未対応エンジン追加時にリストが消える件(#1168)
・追加されたエンジンが未対応である場合には追加を阻止
・追加されてしまっている場合には、エラーで処理中断しないように

* lintチェックエラー部分の修正

* コードレビューの反映 (ref #1179)
・MinimumEngineManifestの更新

* コードレビュー分の反映② ref #1179
・engineManifests[selectedId]自体が undefined であるケースに対応

* サードパーティがエンジンへのアクセス情報を得るための設定書き出し機能(ref #1738)

* ファイルは runtime-info.json に書き出し
* エンジン全起動もしくは個別起動/終了のタイミングで更新

* * 関数名の変更 : writeEngineInfoFor3rdParty
* 排他ロックの追加
* 処理の非同期化

* * コンストラクタ引数でファイルパスを渡すように
* 関数をシンプルに
* ログメッセージ修正
* コメント位置修正

* * エクスポートファイパスを渡す所を引数にした
* 変数、関数名修正
* いくつかの構造をクラス化

* 議論 #1738 に基づき、最小項目の書き出しに変更

* * ファイル書き出しクラスに機能を集約
* 変数名、コメントの修正

* RuntimeInfoManager.tsをブラッシュアップ

* EngineManagerとRuntimeInfoManagerを疎結合に

* データ構造調整、テスト追加

* Apply suggestions from code review

---------

Co-authored-by: Hiroshiba <hihokaruta@gmail.com>
@nmori
Copy link
Contributor

nmori commented Feb 14, 2024

@Hiroshiba
採用ありがとうございます。

こちらで会話があった件ですが
#1765 (review)
サードパーティ向けのドキュメントを執筆する方向性でよいでしょうか?
(もしOKであれば、 docs/サードパーティの方へ.md みたいなファイル素案を書いてみようと思います)

@Hiroshiba
Copy link
Member Author

@nmori こちらこそありがとうございます!!

サードパーティ向けのドキュメントを執筆する方向性でよいでしょうか?
(もしOKであれば、 docs/サードパーティの方へ.md みたいなファイル素案を書いてみようと思います)

ぜひお願いしたいです!!

あ、ちなみに書く内容ってどういう感じを想像されてますか? 👀
素案より更に前に箇条書きでいただけると調整しやすいのかなとか思いました!
書くのが速ければ先に書いてくださった方が早いかもです。(僕はかなり遅いので。。。)

@nmori
Copy link
Contributor

nmori commented Feb 16, 2024

そうですね、書くとするとこんな感じでしょうか

  • サードパーティが利用するときの注意
  1. サードパーティがVOICEVOXにアクセスする場合は、APIをベースにアクセスすること
  2. API を使う場合に、実際問題としてポート番号が起動状況によって変わるということ
  3. そのために、情報を知るためのファイルがあるということ
  • 情報ファイルについて
  1. ファイルの場所 (OS毎の場所もかく?)
  2. ファイルの中身と意味
  3. 生成されるタイミング
  • 情報ファイルについての注意点
  1. ファイルの構成が変わる場合にファイルバージョンが変わるので、使う前に確認すること
  2. ファイルは長時間ロックしないこと(読み取り終わったらすぐ閉じること)
  3. ファイル内のJSON要素、項目がない可能性もあるから、利用前に存在を確認してつかうこと
  4. サードパーティサイドからこのファイルを書き換えないこと

@Hiroshiba
Copy link
Member Author

@nmori ありがとうございます!! とても良さそうに思いました!!

情報ファイルについての注意点

こちらの項目に関してはあげだすとキリがないので、いったん書かなくてもいいのかなと思いました!
重要な項目をシンプルに伝えるほうがメンテもしやすく情報も伝わりやすいのでいいかなと。(いろんな考えがあると思いますが)

@Hiroshiba
Copy link
Member Author

Hiroshiba commented Feb 25, 2024

こちらのissue内容は一旦達成だと思うのでcloseしたいと思います!
あとはドキュメントを書き足すフェーズなので、必要であれば新しくissue を作成したいと思います。
(でももう @nmori さんがプルリクエストを出してくださっているので、issueは作らなくても大丈夫かなと思ってます!)

@nmori さん、ありがとうございました!!

Hiroshiba added a commit that referenced this issue Mar 6, 2024
* 未対応エンジン追加時にリストが消える件(#1168)
・追加されたエンジンが未対応である場合には追加を阻止
・追加されてしまっている場合には、エラーで処理中断しないように

* lintチェックエラー部分の修正

* コードレビューの反映 (ref #1179)
・MinimumEngineManifestの更新

* コードレビュー分の反映② ref #1179
・engineManifests[selectedId]自体が undefined であるケースに対応

* ref #1738 の会話にあった「情報ファイルに関するドキュメント」(新規執筆)

* markdown lint でエラーが出てた件の修正

* Update docs/サードパーティ開発者の方へ.md

Co-authored-by: Hiroshiba <hihokaruta@gmail.com>

* フォーマット表記提案サジェストの適用

Co-authored-by: Nanashi. <sevenc7c@sevenc7c.com>

* * 表の表記をJSONP内コメント追記に
* VOICEVOXの仕組みを追記

* 環境変数の修正

Co-authored-by: Hiroshiba <hihokaruta@gmail.com>

* コメントいただいた部分を中心に追記

* Update docs/サードパーティ開発者の方へ.md

---------

Co-authored-by: Hiroshiba <hihokaruta@gmail.com>
Co-authored-by: Nanashi. <sevenc7c@sevenc7c.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
優先度:中 初心者歓迎タスク 初心者にも優しい簡単めなタスク 機能向上
Projects
None yet
Development

No branches or pull requests

4 participants
@Hiroshiba @nmori @manju-summoner and others