Skip to content

Commit

Permalink
Add: Android側を実装
Browse files Browse the repository at this point in the history
  • Loading branch information
sevenc-nanashi committed Nov 15, 2023
1 parent be8b525 commit 0cb9694
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 25 deletions.
6 changes: 5 additions & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,11 @@ dependencies {
implementation project(':capacitor-cordova-android-plugins')

// TODO: ちゃんと公開されたらそれに置き換える
implementation urlZipFile("voicevoxcore-android", "jp/hiroshiba/voicevoxcore/voicevoxcore-android/0.15.0-preview.13/voicevoxcore-android-0.15.0-preview.13.aar", "https://github.com/VOICEVOX/voicevox_core/releases/download/0.15.0-preview.13/java_packages.zip")
implementation urlZipFile(
"voicevoxcore-android_0.15.0-preview.15",
"jp/hiroshiba/voicevoxcore/voicevoxcore-android/0.15.0-preview.15/voicevoxcore-android-0.15.0-preview.15.aar",
"https://github.com/VOICEVOX/voicevox_core/releases/download/0.15.0-preview.15/java_packages.zip"
)

// https://mvnrepository.com/artifact/com.google.code.gson/gson
implementation group: 'com.google.code.gson', name: 'gson', version: "2.10.1"
Expand Down
55 changes: 44 additions & 11 deletions android/app/src/main/java/jp/hiroshiba/voicevox/CorePlugin.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package jp.hiroshiba.voicevox

import android.app.Activity
import android.system.Os
import android.util.Log
import com.getcapacitor.JSObject
import com.getcapacitor.Plugin
Expand Down Expand Up @@ -34,8 +35,9 @@ class CorePlugin : Plugin() {
@PluginMethod
fun getSupportedDevicesJson(call: PluginCall) {
val ret = JSObject()
// TODO: ハードコードをやめてちゃんと取得する
ret.put("value", "{\"cpu\": true, \"cuda\": false, \"dml\": false}")
val supportedDevices = GlobalInfo.getSupportedDevices()
val supportedDevicesJson = gson.toJson(supportedDevices)
ret.put("value", supportedDevicesJson)
call.resolve(ret)
}

Expand Down Expand Up @@ -86,12 +88,22 @@ class CorePlugin : Plugin() {
Log.e("CorePlugin", "Couldn't get vvms")
return
}
vvms.sortWith(compareBy {
it.name.split(".")[0].length
})
voiceModels = vvms.map {
VoiceModel(it.absolutePath)
}

// Rustのtempfileクレートのための設定。
// /data/local/tmp はAndroid 10から書き込めなくなった。そのため、
// filesのディレクトリ内に一時フォルダを用意してそこから書き込むように設定する。
val tempDir = File(activity.filesDir.absolutePath + "/.tmp")
tempDir.mkdirs()
Os.setenv("TMPDIR", tempDir.absolutePath, true)

call.resolve()
} catch (e: VoicevoxException) {
} catch (e: Exception) {
call.reject(e.message)
}
}
Expand All @@ -112,7 +124,7 @@ class CorePlugin : Plugin() {
}
synthesizer.loadVoiceModel(model)
call.resolve()
} catch (e: VoicevoxException) {
} catch (e: Exception) {
call.reject(e.message)
}
}
Expand All @@ -135,7 +147,7 @@ class CorePlugin : Plugin() {
val ret = JSObject()
ret.put("value", result)
call.resolve(ret)
} catch (e: VoicevoxException) {
} catch (e: Exception) {
call.reject(e.message)
}
}
Expand All @@ -154,7 +166,7 @@ class CorePlugin : Plugin() {
val ret = JSObject()
ret.put("value", gson.toJson(audioQuery))
call.resolve(ret)
} catch (e: VoicevoxException) {
} catch (e: Exception) {
call.reject(e.message)
}
}
Expand All @@ -173,7 +185,7 @@ class CorePlugin : Plugin() {
val ret = JSObject()
ret.put("value", gson.toJson(accentPhrases))
call.resolve(ret)
} catch (e: VoicevoxException) {
} catch (e: Exception) {
call.reject(e.message)
}
}
Expand All @@ -194,7 +206,7 @@ class CorePlugin : Plugin() {
val ret = JSObject()
ret.put("value", gson.toJson(newAccentPhrases))
call.resolve(ret)
} catch (e: VoicevoxException) {
} catch (e: Exception) {
call.reject(e.message)
}
}
Expand All @@ -215,7 +227,7 @@ class CorePlugin : Plugin() {
val ret = JSObject()
ret.put("value", gson.toJson(newAccentPhrases))
call.resolve(ret)
} catch (e: VoicevoxException) {
} catch (e: Exception) {
call.reject(e.message)
}
}
Expand All @@ -236,7 +248,7 @@ class CorePlugin : Plugin() {
val ret = JSObject()
ret.put("value", gson.toJson(newAccentPhrases))
call.resolve(ret)
} catch (e: VoicevoxException) {
} catch (e: Exception) {
call.reject(e.message)
}
}
Expand All @@ -260,7 +272,28 @@ class CorePlugin : Plugin() {
val encodedResult = Base64.getEncoder().encodeToString(result)
ret.put("value", encodedResult)
call.resolve(ret)
} catch (e: VoicevoxException) {
} catch (e: Exception) {
call.reject(e.message)
}
}

@PluginMethod
fun useUserDict(call: PluginCall) {
val wordsJson = call.getString("wordsJson")
if (wordsJson == null) {
call.reject("Type mismatch")
return
}

try {
val words = gson.fromJson(wordsJson, Array<UserDict.Word>::class.java).asList()
val userDict = UserDict()
words.forEach { word ->
userDict.addWord(word)
}
openJtalk.useUserDict(userDict)
call.resolve()
} catch (e: Exception) {
call.reject(e.message)
}
}
Expand Down
31 changes: 23 additions & 8 deletions src/mobile/engine/dict.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,34 @@
import { Preferences } from "@capacitor/preferences";
import { v4 as uuidv4 } from "uuid";
import { VoicevoxCorePlugin } from "../plugin";
import { ApiProvider } from ".";
import { UserDictWord } from "@/openapi";

type InternalUserDict = Record<string, InternalDictWord>;

const preferenceKey = "userDict";
const getUserDictWords = async () => {
export const getUserDictWords = async () => {
const userDictJson = await Preferences.get({ key: preferenceKey });
const dict: InternalUserDict = userDictJson.value
? JSON.parse(userDictJson.value)
: {};
return dict;
};
const setUserDictWords = async (dict: InternalUserDict) => {
await Preferences.set({ key: preferenceKey, value: JSON.stringify(dict) });
export const useUserDictWords = async (
corePlugin: VoicevoxCorePlugin,
dict: InternalUserDict
) => {
await corePlugin.useUserDict({
wordsJson: JSON.stringify(
Object.values(dict).map((word) => ({
surface: word.surface,
pronunciation: word.pronunciation,
accent_type: word.accentType,
priority: word.priority,
word_type: word.wordType,
}))
),
});
};

type InternalWordType =
Expand Down Expand Up @@ -90,7 +104,11 @@ const apiWordToInternalWord = (word: UserDictWord): InternalDictWord => {
};
};

const dictProvider: ApiProvider = () => {
const dictProvider: ApiProvider = ({ corePlugin }) => {
const setUserDictWords = async (dict: InternalUserDict) => {
await Preferences.set({ key: preferenceKey, value: JSON.stringify(dict) });
await useUserDictWords(corePlugin, dict);
};
return {
async getUserDictWordsUserDictGet() {
const dict = await getUserDictWords();
Expand All @@ -112,17 +130,14 @@ const dictProvider: ApiProvider = () => {
);
},
async addUserDictWordUserDictWordPost(word) {
if (!word.wordType) {
throw new Error("wordType is required");
}
const uuid = uuidv4();
const dict = await getUserDictWords();
dict[uuid] = {
surface: word.surface,
pronunciation: word.pronunciation,
accentType: word.accentType,
priority: word.priority ?? 5,
wordType: word.wordType,
wordType: word.wordType ?? "COMMON_NOUN",
};
await setUserDictWords(dict);
return uuid;
Expand Down
8 changes: 5 additions & 3 deletions src/mobile/engine/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { VoicevoxCorePlugin } from "../plugin";
import queryProvider from "./query";
import infoProvider from "./info";
import speakerProvider from "./speaker";
import dictProvider from "./dict";
import dictProvider, { getUserDictWords, useUserDictWords } from "./dict";
import { DefaultApi, DefaultApiInterface } from "@/openapi";

let api: DefaultApi | undefined;
Expand All @@ -16,9 +16,11 @@ const loadApi = () => {
const corePlugin = window.plugins?.voicevoxCore;
if (!corePlugin) throw new Error("assert: corePlugin != null");
let isCoreInitialized = false;
corePlugin.initialize().then(() => {
(async () => {
await corePlugin.initialize();
await useUserDictWords(corePlugin, await getUserDictWords());
isCoreInitialized = true;
});
})();

// コアベースのOpenAPI Connectorライクなオブジェクト。
// - コアベースの実装がある場合は呼び出し、
Expand Down
2 changes: 1 addition & 1 deletion src/mobile/engine/manifestAssets/base.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"adjust_intonation_scale": true,
"adjust_volume_scale": true,
"interrogative_upspeak": true,
"synthesis_morphing": true,
"synthesis_morphing": false,
"manage_library": false
}
}
2 changes: 1 addition & 1 deletion src/mobile/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export type VoicevoxCorePlugin = {
enableInterrogativeUpspeak: boolean;
}) => Promise<{ value: string }>;

userDictLoad: (obj: { dictJson: string }) => Promise<void>;
useUserDict: (obj: { wordsJson: string }) => Promise<void>;
};

const loadPlugin = () => {
Expand Down

0 comments on commit 0cb9694

Please sign in to comment.