Neutralinojs + VOICEVOX
Nuxt3で作ったVOICEVOXのフロントエンドアプリをクロスプラットフォームなネイティブアプリケーションにしてみました。
https://github.com/ktkr3d/neutralinojs-nuxt3-voicevox
リポジトリの使い方
ビルド
- クローン
git clone https://github.com/ktkr3d/neutralinojs-nuxt3-voicevox.git
- ビルド
cd neutralinojs-nuxt3-voicevox
neu update
cd nuxt3-src
npm install
npm run generate
cd ..
neu build
実行
- あらかじめVOICEVOX(docker版でも可)を起動しておきます
- neutralinojs-nuxt3-voicevox の起動
2.1neu
コマンドから起動する場合2.2 各OS用の実行プログラムを直接起動する場合cd neutralinojs-nuxt3-voicevox
neu run
neutralinojs-nuxt3-voicevox/dist/neutralinojs-nuxt3-voicevox/
フォルダの実行形式ファイルを実行
注意事項
- Windows 環境でクローズボタンを押してもすぐに終了しない
https://github.com/neutralinojs/neutralinojs/issues/618
アプリケーションが終了するまで10秒くらい待つ必要があります。 - Linux環境でダウンロードボタンが機能しない。調査中。
window
モードの場合にボタン押下でダウンロードが始まらない。Inspector経由でリンク先blobのダウンロードはできたので、libwebkit2gtk 4.0-37やパーミッション設定の問題かもしれない。browser
モード,chrome
モードでは問題なくダウンロードできる。
環境
開発環境
- node v20.10.0
- npm 10.2.3
- Neutralinojs binaries: v4.14.1
- Neutralinojs client: v3.12.0
- vue 3.4.3
- nuxt 3.9.0
- veutify 3.4.9
- VOICEVOX 0.14.5
実行環境
- Windows 11
- Ubuntu 23.10
- Arch Linux
構築
プロジェクトフォルダ構成
- フォルダ階層と主なファイル
neutralinojs-nuxt3-voicevox/
bin/ # Neutrianojsから提供される各OSのローダ
dist/ # Neutrianojsプロジェクトのビルド結果
nuxt3-src/ # Nuxt3 プロジェクト
components/
sidebar.vue
layouts/
default.vue
pages/
index.vue
voicevox.vue # VOICEVOX フロントエンドアプリ
plugins/
veutify.ts
nuxtconfig.ts # Nuxt プロジェクトの設定
resources/
neutralinojs.config.json # Neutralinojs プロジェクトの設定
Neutralinojs
- Neutralinojs インストール
npm install -g @neutralinojs/neu
- Neutralinojs プロジェクト作成
neu create neutralinojs-nuxt3-voicevox
Nuxt
- Neutralinojs プロジェクト配下にNuxtプロジェクトを作成
cd neutralinojs-nuxt3-voicevox
npx nuxi@latest init nuxt3-src
cd nuxt3-src
npm install
Vuetify
- Vuetify Plugin のインストール
npm i -D vuetify vite-plugin-vuetify
npm i @mdi/font - Vuetify Plugin の設定
src/plugins/vuetify.ts // import this after install `@mdi/font` package
import '@mdi/font/css/materialdesignicons.css'
import 'vuetify/styles'
import { createVuetify } from 'vuetify'
export default defineNuxtPlugin((app) => {
const vuetify = createVuetify({
// ... your configuration
})
app.vueApp.use(vuetify)
})
アプリケーション
- VOICEVOX フロントエンドアプリケーション
nuxt3-src/pages/voicevox.vue <template>
<div>
<form @submit.prevent="submitForm">
<v-table>
<thead>
<tr>
<td>
<v-container fluid>
<v-textarea id="text" v-model="formData.text" counter prepend-inner-icon="mdi-comment" class="mx-2" label="メッセージを入力..." rows="3"></v-textarea>
</v-container>
</td>
<td><v-btn type="submit">音声合成</v-btn></td>
<td></td>
</tr>
</thead>
<tbody>
<tr v-for="(message, index) in messages" :key="index">
<td>{{ message.text }}</td>
<td><audio :src="message.url" controls/></td>
<td><a :href="message.url" download title="ダウンロード"><v-btn elevation="8" fab icon="mdi-file-download"></v-btn></a></td>
</tr>
</tbody>
</v-table>
</form>
</div>
</template>
<script setup>
import { ref } from "vue";
const formData = ref({
text: "",
url: "",
});
const messagesData = [];
const messages = ref(messagesData);
function addMessage() {
if (formData.value.text) {
messages.value.push({
text: formData.value.text,
url: formData.value.url,
});
formData.value.text = "";
}
}
const submitForm = async () => {
const { data: queryJson } = await useFetch("http://localhost:50021/audio_query", {
method: "POST",
query: { style_id: "1", text: formData.value.text },
});
const { data: audioData } = await useFetch("http://localhost:50021/synthesis", {
method: "POST",
query: { style_id: "1" },
body: queryJson,
responseType: "blob",
onResponse({ request, response, options }) {
formData.value.url = window.URL.createObjectURL(response._data);
},
});
addMessage();
};
</script>
<style lang="css">
td {
padding: 16px ;
}
</style>
設定
- Neutralinojs の設定(変更点)
neutralinojs.config.json {
"documentRoot": "/nuxt3-src/dist/",
}{
"modes": {
"window": {
"enableInspector": false,
"exitProcessOnClose": true
}
}
} - Nuxt の設定
src/nuxt.config.ts import vuetify, { transformAssetUrls } from 'vite-plugin-vuetify'
export default defineNuxtConfig({
//...
build: {
transpile: ['vuetify'],
},
modules: [
(_options, nuxt) => {
nuxt.hooks.hook('vite:extendConfig', (config) => {
// @ts-expect-error
config.plugins.push(vuetify({ autoImport: true }))
})
},
//...
],
vite: {
vue: {
template: {
transformAssetUrls,
},
},
},
})
ビルド
注意事項
- Windows 環境でビルドする場合は以下を対策する (2022-07-12の記事)
https://ktkr3d.github.io/2022/07/12/Neutralinojs-Nuxt3/#Windows-環境でのneu-build-失敗対策
ビルド手順
- ビルド
cd neutralinojs-nuxt3-voicevox
cd nuxt3-src; npm run generate; cd ..; neu build --release - 実行
neu run
生成されたファイル
- ファイル一覧
tree -h dist/
[ 512] dist/
├── [ 512] neutralinojs-nuxt3-voicevox
│ ├── [1.8M] neutralinojs-nuxt3-voicevox-linux_arm64
│ ├── [1.4M] neutralinojs-nuxt3-voicevox-linux_armhf
│ ├── [1.6M] neutralinojs-nuxt3-voicevox-linux_x64
│ ├── [1.9M] neutralinojs-nuxt3-voicevox-mac_arm64
│ ├── [3.9M] neutralinojs-nuxt3-voicevox-mac_universal
│ ├── [1.9M] neutralinojs-nuxt3-voicevox-mac_x64
│ ├── [2.5M] neutralinojs-nuxt3-voicevox-win_x64.exe
│ └── [6.9M] resources.neu
└── [7.4M] neutralinojs-nuxt3-voicevox-release.zip - 各OSのローダはNeutralinojsのリリースファイルをコピーしたもの。
bin
に存在するファイル。 resources.neu
ファイルがプログラム。Veutifyを使う前は1MB未満で、Veutifyを使うほどサイズが大きくなった。
実行の準備
Windowsの場合
- 管理者モードのコマンドプロンプトで以下を実行しておく
https://github.com/neutralinojs/v2-specification/blob/main/webview.mdCheckNetIsolation.exe LoopbackExempt -a -n="Microsoft.Win32WebViewHost_cw5n1h2txyewy"
- VOICEVOXを起動しておく
- 実行
neutralinojs-nuxt3-voicevox-win_x64.exe
Ubuntuの場合
- docker版VOICEVOXを実行
https://hub.docker.com/r/voicevox/voicevox_engine - ライブラリ
sudo apt install libwebkit2gtk-4.0-37
sudo apt install gstreamer1.0-plugins-bad - 実行権限付与
- 実行
./neutralinojs-nuxt3-voicevox-linux_x64
Arch Linuxの場合
- docker版VOICEVOXを実行
https://hub.docker.com/r/voicevox/voicevox_engine - 実行権限付与
- 実行
./neutralinojs-nuxt3-voicevox-linux_x64
Comment