Skip to content

Commit

Permalink
複数エンジン対応: 環境変数DEFAULT_ENGINE_INFOSの追加・INVOKE_ENGINE_CONNECTORにエンジン指定を…
Browse files Browse the repository at this point in the history
…追加 (#639)

* INVOKE_ENGINE_CONNECTOR: add host param

* INVOKE_ENGINE_CONNECTOR: fix invoker side

* add EngineHostSetting[] to SettingStore

* add VUE_APP_DEFAULT_ENGINE_HOSTS env var as default engine config

* fix test

* remove engineHosts from config file

* impl ipc to get engineHosts in ui from background

* fix ipc impl; do not read engineHosts from store in background

* add comment

* fix env name in build.yml

* remove env VUE_APP_ENGINE_URL

* fix host url ref

* rename EngineHostSetting to EngineHost

* rename ENGINE_HOSTS to ENGINES and wip synchronized init

* move INIT_VUEX call to Home from App

* add comment

* fix comment

* remove ENGINE_PATH

* remove enginekey for this pr

* fix unused warning

* remove redundant async-await

* remove redundant async-await 2

* revert src/App.vue

* execute GET_ENGINES in Home.vue

* INVOKE_ENGINE_CONNECTOR: use engineKey instead of host to identify engine

* remove url printing

* fix error message when engine not found

* add error when engine not registered

* remove redundant optional chain (impled engine undefined check)

* fix test

* remove unused import

* fix engine exec skip message

* rename Engine -> EngineInfo

* npm run fmt

* rename ENGINES to ENGINE_INFOS

* add engineKey to build.yml
  • Loading branch information
aoirint authored Feb 20, 2022
1 parent 00c80e8 commit 391f902
Show file tree
Hide file tree
Showing 16 changed files with 144 additions and 21 deletions.
5 changes: 2 additions & 3 deletions .env.production
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
ENGINE_PATH=run.exe
VUE_APP_ENGINE_URL=http://127.0.0.1:50021
VUE_APP_GTM_CONTAINER_ID=GTM-DUMMY
DEFAULT_ENGINE_INFOS=[{"key":"074fc39e-678b-4c13-8916-ffca8d505d1d","executionEnabled":true,"executionFilePath":"run.exe","host":"http://127.0.0.1:50021"}]
VUE_APP_GTM_CONTAINER_ID=GTM-DUMMY
3 changes: 1 addition & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,7 @@ jobs:
if: startsWith(matrix.os, 'ubuntu-') || startsWith(matrix.os, 'macos-')
shell: bash
run: |
echo "ENGINE_PATH=./run" > .env.production
echo "VUE_APP_ENGINE_URL=http://127.0.0.1:50021" >> .env.production
echo 'DEFAULT_ENGINE_INFOS=[{"key":"074fc39e-678b-4c13-8916-ffca8d505d1d","executionEnabled":true,"executionFilePath":"./run","host":"http://127.0.0.1:50021"}]' >> .env.production
echo "VUE_APP_GTM_CONTAINER_ID=GTM-DUMMY" >> .env.production
- name: Checkout Product Version Resource
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ npm ci

## 実行

`.env.production`をコピーして`.env`を作成し、`ENGINE_PATH``voicevox_engine`があるパスを指定します。
`.env.production`をコピーして`.env`を作成し、`DEFAULT_ENGINE_INFOS`内の`executionFilePath``voicevox_engine`があるパスを指定します。
とりあえず [製品版 VOICEVOX](https://voicevox.hiroshiba.jp/) のディレクトリのパスを指定すれば動きます。

```bash
Expand Down
1 change: 0 additions & 1 deletion src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export default defineComponent({
setup() {
const store = useStore();
store.dispatch("INIT_VUEX");
store.dispatch("START_WAITING_ENGINE");
// Google Tag Manager
const gtm = useGtm();
Expand Down
31 changes: 30 additions & 1 deletion src/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
AcceptTermsStatus,
ToolbarSetting,
ActivePointScrollMode,
EngineInfo,
} from "./type/preload";

import log from "electron-log";
Expand All @@ -58,6 +59,16 @@ if (isDevelopment) {
);
}

const engineInfos: EngineInfo[] = (() => {
const defaultEngineInfosEnv = process.env.DEFAULT_ENGINE_INFOS;

if (defaultEngineInfosEnv) {
return JSON.parse(defaultEngineInfosEnv) as EngineInfo[];
}

return [];
})();

let win: BrowserWindow;

// 多重起動防止
Expand Down Expand Up @@ -335,6 +346,19 @@ const store = new Store<{
let willQuitEngine = false;
let engineProcess: ChildProcess;
async function runEngine() {
const engineInfo = engineInfos[0]; // TODO: 複数エンジン対応
if (!engineInfo) throw new Error(`No such engineInfo registered: index == 0`);

if (!engineInfo.executionEnabled) {
log.info("Skipped engineInfo execution: disabled");
return;
}

if (!engineInfo.executionFilePath) {
log.info("Skipped engineInfo execution: empty executionFilePath");
return;
}

willQuitEngine = false;

// 最初のエンジンモード
Expand Down Expand Up @@ -363,7 +387,7 @@ async function runEngine() {
// エンジンプロセスの起動
const enginePath = path.resolve(
appDirPath,
process.env.ENGINE_PATH ?? "run.exe"
engineInfo.executionFilePath ?? "run.exe"
);
const args = useGpu ? ["--use_gpu"] : [];

Expand Down Expand Up @@ -830,6 +854,11 @@ ipcMainHandle("LOG_INFO", (_, ...params) => {
log.info(...params);
});

ipcMainHandle("ENGINE_INFOS", () => {
// エンジン情報を設定ファイルに保存しないためにstoreではなくグローバル変数を使用する
return engineInfos;
});

/**
* エンジンを再起動する。
* エンジンの起動が開始したらresolve、起動が失敗したらreject。
Expand Down
4 changes: 4 additions & 0 deletions src/electron/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ const api: Sandbox = {
return ipcRenderer.invoke("LOG_INFO", ...params);
},

engineInfos: () => {
return ipcRendererInvoke("ENGINE_INFOS");
},

restartEngine: () => {
return ipcRendererInvoke("RESTART_ENGINE");
},
Expand Down
56 changes: 50 additions & 6 deletions src/store/audio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,10 @@ export const audioStore: VoiceVoxStoreOptions<
actions: {
START_WAITING_ENGINE: createUILockAction(
async ({ state, commit, dispatch }) => {
const engineInfo = state.engineInfos[0]; // TODO: 複数エンジン対応
if (!engineInfo)
throw new Error(`No such engineInfo registered: index == 0`);

let engineState = state.engineState;
for (let i = 0; i < 100; i++) {
engineState = state.engineState;
Expand All @@ -465,12 +469,14 @@ export const audioStore: VoiceVoxStoreOptions<

try {
await dispatch("INVOKE_ENGINE_CONNECTOR", {
engineKey: engineInfo.key,
action: "versionVersionGet",
payload: [],
}).then(toDispatchResponse("versionVersionGet"));
} catch {
await new Promise((resolve) => setTimeout(resolve, 1000));
window.electron.logInfo("waiting engine...");

window.electron.logInfo(`Waiting engine ${engineInfo.key}`);
continue;
}
engineState = "READY";
Expand All @@ -483,8 +489,13 @@ export const audioStore: VoiceVoxStoreOptions<
}
}
),
LOAD_CHARACTER: createUILockAction(async ({ commit, dispatch }) => {
LOAD_CHARACTER: createUILockAction(async ({ state, commit, dispatch }) => {
const engineInfo = state.engineInfos[0]; // TODO: 複数エンジン対応
if (!engineInfo)
throw new Error(`No such engineInfo registered: index == 0`);

const speakers = await dispatch("INVOKE_ENGINE_CONNECTOR", {
engineKey: engineInfo.key,
action: "speakersSpeakersGet",
payload: [],
})
Expand Down Expand Up @@ -521,7 +532,12 @@ export const audioStore: VoiceVoxStoreOptions<
return styles;
};
const getSpeakerInfo = async function (speaker: Speaker) {
const engineInfo = state.engineInfos[0]; // TODO: 複数エンジン対応
if (!engineInfo)
throw new Error(`No such engineInfo registered: index == 0`);

const speakerInfo = await dispatch("INVOKE_ENGINE_CONNECTOR", {
engineKey: engineInfo.key,
action: "speakerInfoSpeakerInfoGet",
payload: [{ speakerUuid: speaker.speakerUuid }],
})
Expand Down Expand Up @@ -662,7 +678,7 @@ export const audioStore: VoiceVoxStoreOptions<
commit("SET_AUDIO_QUERY", payload);
},
FETCH_ACCENT_PHRASES(
{ dispatch },
{ state, dispatch },
{
text,
styleId,
Expand All @@ -673,7 +689,12 @@ export const audioStore: VoiceVoxStoreOptions<
isKana?: boolean;
}
) {
const engineInfo = state.engineInfos[0]; // TODO: 複数エンジン対応
if (!engineInfo)
throw new Error(`No such engineInfo registered: index == 0`);

return dispatch("INVOKE_ENGINE_CONNECTOR", {
engineKey: engineInfo.key,
action: "accentPhrasesAccentPhrasesPost",
payload: [
{
Expand All @@ -693,13 +714,18 @@ export const audioStore: VoiceVoxStoreOptions<
});
},
FETCH_MORA_DATA(
{ dispatch },
{ dispatch, state },
{
accentPhrases,
styleId,
}: { accentPhrases: AccentPhrase[]; styleId: number }
) {
const engineInfo = state.engineInfos[0]; // TODO: 複数エンジン対応
if (!engineInfo)
throw new Error(`No such engineInfo registered: index == 0`);

return dispatch("INVOKE_ENGINE_CONNECTOR", {
engineKey: engineInfo.key,
action: "moraDataMoraDataPost",
payload: [{ accentPhrase: accentPhrases, speaker: styleId }],
})
Expand Down Expand Up @@ -739,10 +765,15 @@ export const audioStore: VoiceVoxStoreOptions<
return accentPhrases;
},
FETCH_AUDIO_QUERY(
{ dispatch },
{ dispatch, state },
{ text, styleId }: { text: string; styleId: number }
) {
const engineInfo = state.engineInfos[0]; // TODO: 複数エンジン対応
if (!engineInfo)
throw new Error(`No such engineInfo registered: index == 0`);

return dispatch("INVOKE_ENGINE_CONNECTOR", {
engineKey: engineInfo.key,
action: "audioQueryAudioQueryPost",
payload: [
{
Expand Down Expand Up @@ -845,8 +876,16 @@ export const audioStore: VoiceVoxStoreOptions<
return offsets;
},
CONNECT_AUDIO: createUILockAction(
async ({ dispatch }, { encodedBlobs }: { encodedBlobs: string[] }) => {
async (
{ dispatch, state },
{ encodedBlobs }: { encodedBlobs: string[] }
) => {
const engineInfo = state.engineInfos[0]; // TODO: 複数エンジン対応
if (!engineInfo)
throw new Error(`No such engineInfo registered: index == 0`);

return dispatch("INVOKE_ENGINE_CONNECTOR", {
engineKey: engineInfo.key,
action: "connectWavesConnectWavesPost",
payload: [
{
Expand All @@ -866,6 +905,10 @@ export const audioStore: VoiceVoxStoreOptions<
),
GENERATE_AUDIO: createUILockAction(
async ({ dispatch, state }, { audioKey }: { audioKey: string }) => {
const engineInfo = state.engineInfos[0]; // TODO: 複数エンジン対応
if (!engineInfo)
throw new Error(`No such engineInfo registered: index == 0`);

const audioItem: AudioItem = JSON.parse(
JSON.stringify(state.audioItems[audioKey])
);
Expand All @@ -880,6 +923,7 @@ export const audioStore: VoiceVoxStoreOptions<
}

return dispatch("INVOKE_ENGINE_CONNECTOR", {
engineKey: engineInfo.key,
action: "synthesisSynthesisPost",
payload: [
{
Expand Down
2 changes: 1 addition & 1 deletion src/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export const indexStore: VoiceVoxStoreOptions<
promises.push(dispatch("GET_ACCEPT_TERMS"));
promises.push(dispatch("GET_EXPERIMENTAL_SETTING"));

Promise.all(promises).then(() => {
await Promise.all(promises).then(() => {
dispatch("ON_VUEX_READY");
});
},
Expand Down
13 changes: 11 additions & 2 deletions src/store/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,17 @@ const proxyStoreCreator = (
getters: {},
mutations: {},
actions: {
INVOKE_ENGINE_CONNECTOR({ rootState }, payload) {
const instance = _engineFactory.instance(rootState.engineHost);
INVOKE_ENGINE_CONNECTOR({ state }, payload) {
const engineKey = payload.engineKey;
const engineInfo = state.engineInfos.find(
(engineInfo) => engineInfo.key === engineKey
);
if (!engineInfo)
throw new Error(
`No such engineInfo registered: engineKey == ${engineKey}`
);

const instance = _engineFactory.instance(engineInfo.host);
const action = payload.action;
const args = payload.payload;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
Expand Down
2 changes: 1 addition & 1 deletion src/store/setting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const settingStoreState: SettingStoreState = {
},
hotkeySettings: [],
toolbarSetting: [],
engineHost: process.env.VUE_APP_ENGINE_URL as unknown as string,
engineInfos: [],
themeSetting: {
currentTheme: "Default",
availableThemes: [],
Expand Down
10 changes: 9 additions & 1 deletion src/store/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
UpdateInfo,
Preset,
ActivePointScrollMode,
EngineInfo,
} from "@/type/preload";
import { IEngineConnectorFactory } from "@/infrastructures/EngineConnector";
import { QVueGlobals } from "quasar";
Expand Down Expand Up @@ -720,7 +721,7 @@ export type SettingStoreState = {
savingSetting: SavingSetting;
hotkeySettings: HotkeySetting[];
toolbarSetting: ToolbarSetting;
engineHost: string;
engineInfos: EngineInfo[];
themeSetting: ThemeSetting;
acceptRetrieveTelemetry: AcceptRetrieveTelemetryStatus;
experimentalSetting: ExperimentalSetting;
Expand Down Expand Up @@ -905,6 +906,12 @@ type UiStoreTypes = {
action(payload: { useGpu: boolean }): void;
};

GET_ENGINE_INFOS: {
action(): void;
};

SET_ENGINE_INFOS: { mutation: { engineInfos: EngineInfo[] } };

GET_INHERIT_AUDIOINFO: {
action(): void;
};
Expand Down Expand Up @@ -1023,6 +1030,7 @@ export type IEngineConnectorFactoryActions = ReturnType<
type IEngineConnectorFactoryActionsMapper<K> =
K extends keyof IEngineConnectorFactoryActions
? (payload: {
engineKey: string;
action: K;
payload: Parameters<IEngineConnectorFactoryActions[K]>;
}) => ReturnType<IEngineConnectorFactoryActions[K]>
Expand Down
10 changes: 9 additions & 1 deletion src/store/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
UiStoreState,
VoiceVoxStoreOptions,
} from "./type";
import { ActivePointScrollMode } from "@/type/preload";
import { ActivePointScrollMode, EngineInfo } from "@/type/preload";

export function createUILockAction<S, A extends ActionsBase, K extends keyof A>(
action: (
Expand Down Expand Up @@ -117,6 +117,9 @@ export const uiStore: VoiceVoxStoreOptions<UiGetters, UiActions, UiMutations> =
SET_USE_GPU(state, { useGpu }: { useGpu: boolean }) {
state.useGpu = useGpu;
},
SET_ENGINE_INFOS(state, { engineInfos }: { engineInfos: EngineInfo[] }) {
state.engineInfos = engineInfos;
},
SET_INHERIT_AUDIOINFO(
state,
{ inheritAudioInfo }: { inheritAudioInfo: boolean }
Expand Down Expand Up @@ -302,6 +305,11 @@ export const uiStore: VoiceVoxStoreOptions<UiGetters, UiActions, UiMutations> =
useGpu: await window.electron.useGpu(useGpu),
});
},
async GET_ENGINE_INFOS({ commit }) {
commit("SET_ENGINE_INFOS", {
engineInfos: await window.electron.engineInfos(),
});
},
async GET_INHERIT_AUDIOINFO({ commit }) {
commit("SET_INHERIT_AUDIOINFO", {
inheritAudioInfo: await window.electron.inheritAudioInfo(),
Expand Down
7 changes: 7 additions & 0 deletions src/type/ipc.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { EngineInfo } from "@/type/preload";

/**
* invoke, handle
*/
Expand Down Expand Up @@ -149,6 +151,11 @@ type IpcIHData = {
return: void;
};

ENGINE_INFOS: {
args: [];
return: EngineInfo[];
};

RESTART_ENGINE: {
args: [];
return: void;
Expand Down
Loading

0 comments on commit 391f902

Please sign in to comment.