From f83ca5f5a63be00638c5d64eb06edc540824d3bc Mon Sep 17 00:00:00 2001 From: Hiroshiba Date: Thu, 24 Mar 2022 23:45:16 +0900 Subject: [PATCH 01/42] =?UTF-8?q?=E8=BE=9E=E6=9B=B8=E3=83=80=E3=82=A4?= =?UTF-8?q?=E3=82=A2=E3=83=AD=E3=82=B0=E5=86=85=E3=81=AEUILock=E3=82=92?= =?UTF-8?q?=E5=88=86=E3=81=91=E3=82=8B=20(#768)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/DictionaryManageDialog.vue | 63 +++++++++++++++-------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/src/components/DictionaryManageDialog.vue b/src/components/DictionaryManageDialog.vue index fa8d5bd689..853efa74fb 100644 --- a/src/components/DictionaryManageDialog.vue +++ b/src/components/DictionaryManageDialog.vue @@ -246,17 +246,26 @@ export default defineComponent({ get: () => props.modelValue, set: (val) => emit("update:modelValue", val), }); - const uiLocked = computed(() => store.getters.UI_LOCKED); + const uiLocked = ref(false); // ダイアログ内でstore.getters.UI_LOCKEDは常にtrueなので独自に管理 const nowGenerating = ref(false); const nowPlaying = ref(false); const loadingDict = ref(false); const userDict = ref>({}); + const createUILockAction = function (action: Promise) { + uiLocked.value = true; + return action.finally(() => { + uiLocked.value = false; + }); + }; + const loadingDictProcess = async () => { loadingDict.value = true; try { - userDict.value = await store.dispatch("LOAD_USER_DICT"); + userDict.value = await createUILockAction( + store.dispatch("LOAD_USER_DICT") + ); } catch { $q.dialog({ title: "辞書の取得に失敗しました", @@ -354,11 +363,13 @@ export default defineComponent({ text = convertHiraToKana(text); text = convertLongVowel(text); accentPhrase.value = ( - await store.dispatch("FETCH_ACCENT_PHRASES", { - text: text + "ガ'", - styleId: styleId.value, - isKana: true, - }) + await createUILockAction( + store.dispatch("FETCH_ACCENT_PHRASES", { + text: text + "ガ'", + styleId: styleId.value, + isKana: true, + }) + ) )[0]; if ( selectedId.value && @@ -379,10 +390,12 @@ export default defineComponent({ if (accentPhrase.value) { accentPhrase.value.accent = accent; accentPhrase.value = ( - await store.dispatch("FETCH_MORA_DATA", { - accentPhrases: [accentPhrase.value], - styleId: styleId.value, - }) + await createUILockAction( + store.dispatch("FETCH_MORA_DATA", { + accentPhrases: [accentPhrase.value], + styleId: styleId.value, + }) + ) )[0]; } }; @@ -415,9 +428,11 @@ export default defineComponent({ audioItem, }); if (!blob) { - blob = await store.dispatch("GENERATE_AUDIO_FROM_AUDIO_ITEM", { - audioItem, - }); + blob = await createUILockAction( + store.dispatch("GENERATE_AUDIO_FROM_AUDIO_ITEM", { + audioItem, + }) + ); if (!blob) { nowGenerating.value = false; $q.dialog({ @@ -499,11 +514,13 @@ export default defineComponent({ } } else { try { - await store.dispatch("ADD_WORD", { - surface: surface.value, - pronunciation: yomi.value, - accentType: accent, - }); + await createUILockAction( + store.dispatch("ADD_WORD", { + surface: surface.value, + pronunciation: yomi.value, + accentType: accent, + }) + ); } catch { $q.dialog({ title: "単語の登録に失敗しました", @@ -539,9 +556,11 @@ export default defineComponent({ }, }).onOk(async () => { try { - await store.dispatch("DELETE_WORD", { - wordUuid: selectedId.value, - }); + await createUILockAction( + store.dispatch("DELETE_WORD", { + wordUuid: selectedId.value, + }) + ); } catch { $q.dialog({ title: "単語の削除に失敗しました", From 5a301ad1fd7fbb70c95f4e5e39885eb6f73711f1 Mon Sep 17 00:00:00 2001 From: nebocco <73807432+nebocco@users.noreply.github.com> Date: Tue, 29 Mar 2022 00:09:54 +0900 Subject: [PATCH 02/42] =?UTF-8?q?=E3=82=A2=E3=82=AF=E3=82=BB=E3=83=B3?= =?UTF-8?q?=E3=83=88=E5=8F=A5=E5=88=86=E5=89=B2=E3=81=AE=E5=BD=93=E3=81=9F?= =?UTF-8?q?=E3=82=8A=E5=88=A4=E5=AE=9A=E3=82=92=E5=BA=83=E3=81=92=E3=82=8B?= =?UTF-8?q?=20(#772)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: hide next button * fix: expand hit area --- src/components/AudioAccent.vue | 11 +++++------ src/components/AudioDetail.vue | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/components/AudioAccent.vue b/src/components/AudioAccent.vue index 2c0ca4bce5..7f0318f4d5 100644 --- a/src/components/AudioAccent.vue +++ b/src/components/AudioAccent.vue @@ -37,7 +37,7 @@ 'grid-column': `1 / span ${accentPhrase.moras.length * 2 - 1}`, }" > - + @@ -53,8 +53,8 @@ ]" :style="{ 'grid-column': `${moraIndex * 2 + 1} / span 1` }" > - - + + @@ -99,7 +99,7 @@ export default defineComponent({ const accent = previewAccentSlider.state.currentValue.value ?? 0; return [...Array(props.accentPhrase.moras.length).keys()].map( (index) => - `${index * 40 + 15} ${ + `${index * 40 + 10} ${ index + 1 == accent || (index != 0 && index < accent) ? 5 : 45 }` ); @@ -132,8 +132,7 @@ div { right: 0; bottom: 0; > div { - padding-left: 10px; - padding-right: 5px; + padding-left: 5px; } } } diff --git a/src/components/AudioDetail.vue b/src/components/AudioDetail.vue index ab798193a6..b3b0d824ba 100644 --- a/src/components/AudioDetail.vue +++ b/src/components/AudioDetail.vue @@ -802,15 +802,15 @@ $pitch-label-height: 24px; div { padding: 0px; &.text-cell { - min-width: 30px; - max-width: 30px; + min-width: 20px; + max-width: 20px; grid-row-start: 3; text-align: center; color: colors.$display; } &.text-cell-hovered { - min-width: 30px; - max-width: 30px; + min-width: 20px; + max-width: 20px; grid-row-start: 3; text-align: center; color: colors.$display; @@ -818,8 +818,8 @@ $pitch-label-height: 24px; cursor: pointer; } &.splitter-cell { - min-width: 10px; - max-width: 10px; + min-width: 20px; + max-width: 20px; grid-row: 3 / span 1; z-index: vars.$detail-view-splitter-cell-z-index; } @@ -833,14 +833,14 @@ $pitch-label-height: 24px; grid-row: 1 / span 3; } &.splitter-cell-be-split-pause { - min-width: 10px; - max-width: 10px; + min-width: 20px; + max-width: 20px; } &.accent-cell { grid-row: 2 / span 1; div { - min-width: 30px + 10px; - max-width: 30px + 10px; + min-width: 20px + 20px; + max-width: 20px + 20px; display: inline-block; cursor: pointer; } From 07f3497a68712662e353aa8f42980acefa2f4667 Mon Sep 17 00:00:00 2001 From: madosuki Date: Tue, 29 Mar 2022 11:18:50 +0900 Subject: [PATCH 03/42] =?UTF-8?q?=E3=83=86=E3=82=AD=E3=82=B9=E3=83=88?= =?UTF-8?q?=E3=82=92audio=20cell=E3=81=AB=E3=83=9A=E3=83=BC=E3=82=B9?= =?UTF-8?q?=E3=83=88=E3=81=97=E3=81=9F=E6=99=82=E3=81=AE=E6=8C=99=E5=8B=95?= =?UTF-8?q?=E3=82=92=E5=A4=89=E6=9B=B4=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB=E3=81=99=E3=82=8B=20(#773)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add detectNvidia function * follow to menu bar * remove no longer a variable * run fmt * fix typo * remove utils.ts and some changes in background.ts * change message box type and detail, and change behaviour of setOnLaunchModeItemClicked * recreate package-lock.json using node 12.18.2 * re recreate package-lock.json using node 12.18.2 and npm 7.20.5 * recreate package-lock.json using node 12.18.2 and npm 6.14.5 * recreate package-lock.json using node 12.18.2 and npm 7.20.3 * fix conflict * add settings to splitTextWhenPaste * remove KUTEN * add some template and change text * change label * remove comment * fix forgot add to Vuex.spec.ts * rename BOTH to PREIOD_AND_NEW_LINE --- src/background.ts | 6 +++ src/components/AudioCell.vue | 19 +++++++--- src/components/SettingDialog.vue | 63 ++++++++++++++++++++++++++++++++ src/store/setting.ts | 1 + src/type/preload.d.ts | 3 ++ tests/unit/store/Vuex.spec.ts | 1 + 6 files changed, 88 insertions(+), 5 deletions(-) diff --git a/src/background.ts b/src/background.ts index 7931b48260..678fd0a3ce 100644 --- a/src/background.ts +++ b/src/background.ts @@ -229,6 +229,11 @@ const store = new Store<{ outputStereo: { type: "boolean", default: false }, outputSamplingRate: { type: "number", default: 24000 }, audioOutputDevice: { type: "string", default: "default" }, + splitTextWhenPaste: { + type: "string", + enum: ["PERIOD_AND_NEW_LINE", "NEW_LINE", "OFF"], + default: "PERIOD_AND_NEW_LINE", + }, }, default: { fileEncoding: "UTF-8", @@ -240,6 +245,7 @@ const store = new Store<{ outputStereo: false, outputSamplingRate: 24000, audioOutputDevice: "default", + splitTextWhenPaste: "PERIOD_AND_NEW_LINE", }, }, // To future developers: if you are to modify the store schema with array type, diff --git a/src/components/AudioCell.vue b/src/components/AudioCell.vue index 3862443ba8..69aca15404 100644 --- a/src/components/AudioCell.vue +++ b/src/components/AudioCell.vue @@ -278,13 +278,22 @@ export default defineComponent({ store.dispatch("STOP_AUDIO", { audioKey: props.audioKey }); }; + const isEnableSplitText = computed( + () => store.state.savingSetting.splitTextWhenPaste + ); // コピペしたときに句点と改行で区切る const pasteOnAudioCell = async (event: ClipboardEvent) => { - if (event.clipboardData) { - const texts = event.clipboardData - .getData("text/plain") - .replaceAll("。", "。\n\r") - .split(/[\n\r]/); + if (event.clipboardData && isEnableSplitText.value !== "OFF") { + let texts: string[] = []; + const clipBoardData = event.clipboardData.getData("text/plain"); + switch (isEnableSplitText.value) { + case "PERIOD_AND_NEW_LINE": + texts = clipBoardData.replaceAll("。", "。\n\r").split(/[\n\r]/); + break; + case "NEW_LINE": + texts = clipBoardData.split(/[\n\r]/); + break; + } if (texts.length > 1) { event.preventDefault(); diff --git a/src/components/SettingDialog.vue b/src/components/SettingDialog.vue index e7f0412c75..7e06619702 100644 --- a/src/components/SettingDialog.vue +++ b/src/components/SettingDialog.vue @@ -263,6 +263,69 @@ + +
テキストを貼り付け時に行われる分割の挙動を変えます
+ + + + + + + diff --git a/src/store/setting.ts b/src/store/setting.ts index b6d6e289e5..3d2514f70c 100644 --- a/src/store/setting.ts +++ b/src/store/setting.ts @@ -32,6 +32,7 @@ export const settingStoreState: SettingStoreState = { outputStereo: false, outputSamplingRate: 24000, audioOutputDevice: "default", + splitTextWhenPaste: "PERIOD_AND_NEW_LINE", }, hotkeySettings: [], toolbarSetting: [], diff --git a/src/type/preload.d.ts b/src/type/preload.d.ts index 2f1e7e2a03..4facf5dde0 100644 --- a/src/type/preload.d.ts +++ b/src/type/preload.d.ts @@ -133,6 +133,8 @@ export type AcceptTermsStatus = "Unconfirmed" | "Accepted" | "Rejected"; export type ActivePointScrollMode = "CONTINUOUSLY" | "PAGE" | "OFF"; +export type SplitTextWhenPasteType = "PERIOD_AND_NEW_LINE" | "NEW_LINE" | "OFF"; + export type SavingSetting = { exportLab: boolean; fileEncoding: Encoding; @@ -143,6 +145,7 @@ export type SavingSetting = { outputStereo: boolean; outputSamplingRate: number; audioOutputDevice: string; + splitTextWhenPaste: SplitTextWhenPasteType; }; export type DefaultStyleId = { diff --git a/tests/unit/store/Vuex.spec.ts b/tests/unit/store/Vuex.spec.ts index db73cb121b..86b4b9d681 100644 --- a/tests/unit/store/Vuex.spec.ts +++ b/tests/unit/store/Vuex.spec.ts @@ -54,6 +54,7 @@ describe("store/vuex.js test", () => { outputStereo: false, outputSamplingRate: 24000, audioOutputDevice: "default", + splitTextWhenPaste: "PERIOD_AND_NEW_LINE", }, themeSetting: { currentTheme: "Default", From 64044d1ea1389406de8a234517377d9e5aef69c1 Mon Sep 17 00:00:00 2001 From: kchop Date: Mon, 4 Apr 2022 00:36:47 +0900 Subject: [PATCH 04/42] =?UTF-8?q?=E3=82=A2=E3=82=AF=E3=82=BB=E3=83=B3?= =?UTF-8?q?=E3=83=88=E3=81=8B=E3=82=89=E3=82=A4=E3=83=B3=E3=83=88=E3=83=8D?= =?UTF-8?q?=E3=83=BC=E3=82=B7=E3=83=A7=E3=83=B3=E3=82=92=E5=86=8D=E8=A8=AD?= =?UTF-8?q?=E5=AE=9A=E3=81=99=E3=82=8B=E6=A9=9F=E8=83=BD=20(#776)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * FETCH_MORA_DATAで取ってきたaccentPhrasesでまるっと上書きするactionを追加 * ショートカットキーで実行できるように * 何をリセットするのか明確にする * FETCH_MORA_PITCHを追加してそちらを使うように * デフォルトショートカットキーをRに変更 * FETCH_MORA_DATAを使い音素長もリセットする * 長さも変更することを示すためaction名の変更 --- src/background.ts | 4 ++++ src/components/AudioDetail.vue | 10 ++++++++++ src/store/audio.ts | 27 +++++++++++++++++++++++++++ src/store/type.ts | 4 ++++ src/type/preload.d.ts | 3 ++- 5 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/background.ts b/src/background.ts index 678fd0a3ce..8816c973c5 100644 --- a/src/background.ts +++ b/src/background.ts @@ -172,6 +172,10 @@ const defaultHotkeySettings: HotkeySetting[] = [ action: "テキスト読み込む", combination: "", }, + { + action: "イントネーションをリセット", + combination: "R", + }, ]; const defaultToolbarButtonSetting: ToolbarSetting = [ diff --git a/src/components/AudioDetail.vue b/src/components/AudioDetail.vue index b3b0d824ba..9d86c4bb02 100644 --- a/src/components/AudioDetail.vue +++ b/src/components/AudioDetail.vue @@ -283,6 +283,16 @@ export default defineComponent({ } }, ], + [ + "イントネーションをリセット", + () => { + if (!uiLocked.value && store.getters.ACTIVE_AUDIO_KEY) { + store.dispatch("COMMAND_RESET_MORA_PITCH_AND_LENGTH", { + audioKey: store.getters.ACTIVE_AUDIO_KEY, + }); + } + }, + ], ]); // このコンポーネントは遅延評価なので手動でバインディングを行う setHotkeyFunctions(hotkeyMap, true); diff --git a/src/store/audio.ts b/src/store/audio.ts index 4d49f88c7a..c38b51e7e7 100644 --- a/src/store/audio.ts +++ b/src/store/audio.ts @@ -1808,6 +1808,33 @@ export const audioCommandStore: VoiceVoxStoreOptions< }); } }, + async COMMAND_RESET_MORA_PITCH_AND_LENGTH( + { state, dispatch, commit }, + { audioKey } + ) { + const styleId = state.audioItems[audioKey].styleId; + if (styleId == undefined) throw new Error("styleId == undefined"); + + const query = state.audioItems[audioKey].query; + if (query == undefined) throw new Error("query == undefined"); + + try { + const newAccentPhases = await dispatch("FETCH_MORA_DATA", { + accentPhrases: query.accentPhrases, + styleId, + }); + + commit("COMMAND_CHANGE_ACCENT", { + audioKey, + accentPhrases: newAccentPhases, + }); + } catch (error) { + commit("COMMAND_CHANGE_ACCENT", { + audioKey, + accentPhrases: query.accentPhrases, + }); + } + }, COMMAND_SET_AUDIO_MORA_DATA( { commit }, payload: { diff --git a/src/store/type.ts b/src/store/type.ts index 5c6a500fc4..97aaa0b73f 100644 --- a/src/store/type.ts +++ b/src/store/type.ts @@ -462,6 +462,10 @@ type AudioCommandStoreTypes = { }): void; }; + COMMAND_RESET_MORA_PITCH_AND_LENGTH: { + action(payload: { audioKey: string }): void; + }; + COMMAND_SET_AUDIO_MORA_DATA: { mutation: { audioKey: string; diff --git a/src/type/preload.d.ts b/src/type/preload.d.ts index 4facf5dde0..86c54e5fb7 100644 --- a/src/type/preload.d.ts +++ b/src/type/preload.d.ts @@ -198,7 +198,8 @@ export type HotkeyAction = | "プロジェクトを名前を付けて保存" | "プロジェクトを上書き保存" | "プロジェクト読み込み" - | "テキスト読み込む"; + | "テキスト読み込む" + | "イントネーションをリセット"; export type HotkeyCombo = string; From 09c1a18b5585a3797b35472fda1edc72150cc3f0 Mon Sep 17 00:00:00 2001 From: Hiroshiba Date: Tue, 5 Apr 2022 19:56:39 +0900 Subject: [PATCH 05/42] =?UTF-8?q?=E3=83=86=E3=82=AD=E3=82=B9=E3=83=88?= =?UTF-8?q?=E8=AA=AD=E3=81=BF=E8=BE=BC=E3=81=BF=E6=99=82=E3=81=AB=E3=83=87?= =?UTF-8?q?=E3=83=95=E3=82=A9=E3=83=AB=E3=83=88=E3=82=B9=E3=82=BF=E3=82=A4?= =?UTF-8?q?=E3=83=AB=E3=81=8C=E9=81=A9=E7=94=A8=E3=81=95=E3=82=8C=E3=82=8B?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E5=A4=89=E6=9B=B4=20(#765)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/store/audio.ts | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/store/audio.ts b/src/store/audio.ts index c38b51e7e7..b624c0fbdf 100644 --- a/src/store/audio.ts +++ b/src/store/audio.ts @@ -68,26 +68,28 @@ function parseTextFile( userOrderedCharacterInfos: CharacterInfo[] ): AudioItem[] { const characters = new Map(); - { - const uuid2StyleIds = new Map(); - for (const defaultStyleId of defaultStyleIds) { - const speakerUuid = defaultStyleId.speakerUuid; - const styleId = defaultStyleId.defaultStyleId; - uuid2StyleIds.set(speakerUuid, styleId); - } - for (const characterInfo of userOrderedCharacterInfos) { - const uuid = characterInfo.metas.speakerUuid; - const styleId = - uuid2StyleIds.get(uuid) ?? characterInfo.metas.styles[0].styleId; - const speakerName = characterInfo.metas.speakerName; - characters.set(speakerName, styleId); - } + const uuid2StyleIds = new Map(); + for (const defaultStyleId of defaultStyleIds) { + const speakerUuid = defaultStyleId.speakerUuid; + const styleId = defaultStyleId.defaultStyleId; + uuid2StyleIds.set(speakerUuid, styleId); + } + for (const characterInfo of userOrderedCharacterInfos) { + const uuid = characterInfo.metas.speakerUuid; + const styleId = uuid2StyleIds.get(uuid); + const speakerName = characterInfo.metas.speakerName; + if (styleId == undefined) + throw new Error(`styleId is undefined. speakerUuid: ${uuid}`); + characters.set(speakerName, styleId); } if (!characters.size) return []; const audioItems: AudioItem[] = []; const seps = [",", "\r\n", "\n"]; - let lastStyleId = userOrderedCharacterInfos[0].metas.styles[0].styleId; + let lastStyleId = uuid2StyleIds.get( + userOrderedCharacterInfos[0].metas.speakerUuid + ); + if (lastStyleId == undefined) throw new Error(`lastStyleId is undefined.`); for (const splittedText of body.split(new RegExp(`${seps.join("|")}`, "g"))) { const styleId = characters.get(splittedText); if (styleId !== undefined) { From be239a1bbc4e9f093a8a6396c063b2e4e40ee5b5 Mon Sep 17 00:00:00 2001 From: Hiroshiba Date: Fri, 8 Apr 2022 14:19:23 +0900 Subject: [PATCH 06/42] =?UTF-8?q?.env=E3=81=AE=E3=82=A8=E3=83=B3=E3=82=B8?= =?UTF-8?q?=E3=83=B3=E3=81=B8=E3=81=AE=E3=83=91=E3=82=B9=E3=81=AF\?= =?UTF-8?q?=E5=8C=BA=E5=88=87=E3=82=8A=E3=81=A7=E3=81=AF=E3=81=AA=E3=81=8F?= =?UTF-8?q?/=E5=8C=BA=E5=88=87=E3=82=8A=E3=81=A0=E3=81=A8=E3=82=8F?= =?UTF-8?q?=E3=81=8B=E3=82=8A=E3=82=84=E3=81=99=E3=81=8F=E3=81=99=E3=82=8B?= =?UTF-8?q?=20(#778)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * .envのエンジンへのパスは\ではなく * Update .env.production * Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 10f3d43474..14ec4d9911 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,8 @@ npm ci ## 実行 `.env.production`をコピーして`.env`を作成し、`DEFAULT_ENGINE_INFOS`内の`executionFilePath`に`voicevox_engine`があるパスを指定します。 -とりあえず [製品版 VOICEVOX](https://voicevox.hiroshiba.jp/) のディレクトリのパスを指定すれば動きます。 +[製品版 VOICEVOX](https://voicevox.hiroshiba.jp/) のディレクトリのパスを指定すれば動きます。 +Windowsの場合でもパスの区切り文字は`\`ではなく`/`なのでご注意ください。 ```bash npm run electron:serve From b641f4b47dc6b1c85af8eedd14c21faa90d1b928 Mon Sep 17 00:00:00 2001 From: madosuki Date: Fri, 8 Apr 2022 22:43:51 +0900 Subject: [PATCH 07/42] Fix UNLOCK_UI (#774) * add detectNvidia function * follow to menu bar * remove no longer a variable * run fmt * fix typo * remove utils.ts and some changes in background.ts * change message box type and detail, and change behaviour of setOnLaunchModeItemClicked * recreate package-lock.json using node 12.18.2 * re recreate package-lock.json using node 12.18.2 and npm 7.20.5 * recreate package-lock.json using node 12.18.2 and npm 6.14.5 * recreate package-lock.json using node 12.18.2 and npm 7.20.3 * fix conflict * add process of check whether 0 for state.uiLockCount * add console.warn * add eslint disable line * fix --- src/store/ui.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/store/ui.ts b/src/store/ui.ts index 52fa38390a..5fc9b0a3d8 100644 --- a/src/store/ui.ts +++ b/src/store/ui.ts @@ -69,7 +69,12 @@ export const uiStore: VoiceVoxStoreOptions = state.uiLockCount++; }, UNLOCK_UI(state) { - state.uiLockCount--; + if (state.uiLockCount !== 0) { + state.uiLockCount--; + } else { + // eslint-disable-next-line no-console + console.warn("UNLOCK_UI is called when state.uiLockCount == 0"); + } }, LOCK_MENUBAR(state) { state.dialogLockCount++; From 8aa6157785d97365fe882fcd537c4672e8efc2e5 Mon Sep 17 00:00:00 2001 From: kchop Date: Fri, 8 Apr 2022 22:47:08 +0900 Subject: [PATCH 08/42] =?UTF-8?q?=E9=81=B8=E6=8A=9E=E4=B8=AD=E3=81=AE?= =?UTF-8?q?=E3=82=A2=E3=82=AF=E3=82=BB=E3=83=B3=E3=83=88=E5=8F=A5=E3=82=92?= =?UTF-8?q?=E3=83=AA=E3=82=BB=E3=83=83=E3=83=88=E3=81=99=E3=82=8B=E6=A9=9F?= =?UTF-8?q?=E8=83=BD=E3=82=92=E8=BF=BD=E5=8A=A0=20(#779)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 選択中のアクセント句のみリセットするコマンドとショートカットキー追加 * 全体リセットのショートカットキー * エラーが起きたことが分からなくなるのでここでcatchしない --- src/background.ts | 4 ++++ src/components/AudioDetail.vue | 15 ++++++++++++ src/store/audio.ts | 44 ++++++++++++++++++++++------------ src/store/type.ts | 4 ++++ src/type/preload.d.ts | 3 ++- 5 files changed, 54 insertions(+), 16 deletions(-) diff --git a/src/background.ts b/src/background.ts index 8816c973c5..1a41da3b2d 100644 --- a/src/background.ts +++ b/src/background.ts @@ -174,6 +174,10 @@ const defaultHotkeySettings: HotkeySetting[] = [ }, { action: "イントネーションをリセット", + combination: !isMac ? "Ctrl G" : "Meta G", + }, + { + action: "選択中のアクセント句のイントネーションをリセット", combination: "R", }, ]; diff --git a/src/components/AudioDetail.vue b/src/components/AudioDetail.vue index 9d86c4bb02..6773d2113e 100644 --- a/src/components/AudioDetail.vue +++ b/src/components/AudioDetail.vue @@ -293,6 +293,21 @@ export default defineComponent({ } }, ], + [ + "選択中のアクセント句のイントネーションをリセット", + () => { + if ( + !uiLocked.value && + store.getters.ACTIVE_AUDIO_KEY && + store.state.audioPlayStartPoint !== undefined + ) { + store.dispatch("COMMAND_RESET_SELECTED_MORA_PITCH_AND_LENGTH", { + audioKey: store.getters.ACTIVE_AUDIO_KEY, + accentPhraseIndex: store.state.audioPlayStartPoint, + }); + } + }, + ], ]); // このコンポーネントは遅延評価なので手動でバインディングを行う setHotkeyFunctions(hotkeyMap, true); diff --git a/src/store/audio.ts b/src/store/audio.ts index b624c0fbdf..2959e7c56f 100644 --- a/src/store/audio.ts +++ b/src/store/audio.ts @@ -1820,22 +1820,36 @@ export const audioCommandStore: VoiceVoxStoreOptions< const query = state.audioItems[audioKey].query; if (query == undefined) throw new Error("query == undefined"); - try { - const newAccentPhases = await dispatch("FETCH_MORA_DATA", { - accentPhrases: query.accentPhrases, - styleId, - }); + const newAccentPhases = await dispatch("FETCH_MORA_DATA", { + accentPhrases: query.accentPhrases, + styleId, + }); - commit("COMMAND_CHANGE_ACCENT", { - audioKey, - accentPhrases: newAccentPhases, - }); - } catch (error) { - commit("COMMAND_CHANGE_ACCENT", { - audioKey, - accentPhrases: query.accentPhrases, - }); - } + commit("COMMAND_CHANGE_ACCENT", { + audioKey, + accentPhrases: newAccentPhases, + }); + }, + async COMMAND_RESET_SELECTED_MORA_PITCH_AND_LENGTH( + { state, dispatch, commit }, + { audioKey, accentPhraseIndex } + ) { + const styleId = state.audioItems[audioKey].styleId; + if (styleId == undefined) throw new Error("styleId == undefined"); + + const query = state.audioItems[audioKey].query; + if (query == undefined) throw new Error("query == undefined"); + + const newAccentPhases = await dispatch("FETCH_AND_COPY_MORA_DATA", { + accentPhrases: [...query.accentPhrases], + styleId, + copyIndexes: [accentPhraseIndex], + }); + + commit("COMMAND_CHANGE_ACCENT", { + audioKey, + accentPhrases: newAccentPhases, + }); }, COMMAND_SET_AUDIO_MORA_DATA( { commit }, diff --git a/src/store/type.ts b/src/store/type.ts index 97aaa0b73f..368162cfdb 100644 --- a/src/store/type.ts +++ b/src/store/type.ts @@ -466,6 +466,10 @@ type AudioCommandStoreTypes = { action(payload: { audioKey: string }): void; }; + COMMAND_RESET_SELECTED_MORA_PITCH_AND_LENGTH: { + action(payload: { audioKey: string; accentPhraseIndex: number }): void; + }; + COMMAND_SET_AUDIO_MORA_DATA: { mutation: { audioKey: string; diff --git a/src/type/preload.d.ts b/src/type/preload.d.ts index 86c54e5fb7..32a85c93d9 100644 --- a/src/type/preload.d.ts +++ b/src/type/preload.d.ts @@ -199,7 +199,8 @@ export type HotkeyAction = | "プロジェクトを上書き保存" | "プロジェクト読み込み" | "テキスト読み込む" - | "イントネーションをリセット"; + | "イントネーションをリセット" + | "選択中のアクセント句のイントネーションをリセット"; export type HotkeyCombo = string; From 15763fcff7af59dd349023f0a6af9268bc959b0b Mon Sep 17 00:00:00 2001 From: Haruki Tazoe <40142697+jdkfx@users.noreply.github.com> Date: Fri, 8 Apr 2022 22:49:49 +0900 Subject: [PATCH 09/42] =?UTF-8?q?=E8=A8=AD=E5=AE=9A=E7=94=BB=E9=9D=A2?= =?UTF-8?q?=E3=81=AE=E9=A0=85=E7=9B=AE=E3=81=AE=E8=A9=B3=E7=B4=B0=E6=83=85?= =?UTF-8?q?=E5=A0=B1=E3=82=92=E3=83=98=E3=83=AB=E3=83=97=E3=81=A8=E3=81=97?= =?UTF-8?q?=E3=81=A6=E8=A1=A8=E7=A4=BA=E3=81=99=E3=82=8B=20(#780)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * パラメータの引き継ぎの詳細表示アイコンを追加 * 書き出し先を固定についての詳細表示アイコンを追加 * 上書き防止の詳細表示アイコンを追加 * txtファイルを書き出しの詳細表示アイコンを追加 * labファイルを書き出しの詳細表示アイコンを追加 * 音声をステレオ化の詳細表示アイコンを追加 * プリセット機能の詳細表示アイコンを追加 * 疑問文を自動調整の詳細表示アイコンを追加 * 利用状況のデータ収集の詳細表示アイコンを追加 * 再生位置を追従の詳細表示アイコンを追加 * エンジンモードの詳細表示アイコンを追加 * 文字コードの詳細表示アイコンを追加 * 分割の挙動の詳細表示アイコンを追加 * 再生デバイスの詳細表示アイコンを追加 * 音声のサンプリングレートの詳細表示アイコンを追加 --- src/components/SettingDialog.vue | 386 ++++++++++++++++++++++--------- 1 file changed, 276 insertions(+), 110 deletions(-) diff --git a/src/components/SettingDialog.vue b/src/components/SettingDialog.vue index 7e06619702..2d12d2b788 100644 --- a/src/components/SettingDialog.vue +++ b/src/components/SettingDialog.vue @@ -34,6 +34,24 @@
エンジンモード
+
+ + + GPUモードの利用には NVIDIA™ GPU が必要です + + +
- - GPUモードの利用には NVIDIA™ GPU が必要です -
@@ -67,24 +76,51 @@
パラメータの引き継ぎ
+
+ + + テキスト欄を追加する際、現在の話速等のパラメータを引き継ぎます + + +
- - テキスト欄を追加する際、現在の話速等のパラメータを引き継ぎます -
再生位置を追従
+
+ + + 再生位置を追従し、自動でスクロールするモードを選ぶことができます + + +
文字コード
+
+ + + 文字コードを選ぶことができます + + +
書き出し先を固定
+
+ + + 音声ファイルを設定したフォルダに書き出す + + +
- - 音声ファイルを設定したフォルダに書き出す -
上書き防止
+
+ + + 上書きせずにファイルを連番で保存します + + +
- - 上書きせずにファイルを連番で保存します -
txtファイルを書き出し
+
+ + + テキストをtxtファイルとして書き出します + + +
- - テキストをtxtファイルとして書き出します -
labファイルを書き出し
+
+ + + リップシンク用のlabファイルを書き出します + + +
- - リップシンク用のlabファイルを書き出します -
-
テキストを貼り付け時に行われる分割の挙動を変えます
+
分割の挙動
+
+ + + テキストを貼り付け時に行われる分割の挙動を変えます + + +
音声をステレオ化
+
+ + + 音声データをモノラルからステレオに変換してから再生・保存を行います + + +
- - 音声データをモノラルからステレオに変換してから再生・保存を行います -
再生デバイス
+
+ + + 音声の再生デバイスを変更し再生を行います + + +
- - 音声の再生デバイスを変更し再生を行います -
音声のサンプリングレート
+
+ + + 再生・保存時の音声のサンプリングレートを変更します(サンプリングレートを上げても音声の品質は上がりません。) + + +
- - 再生・保存時の音声のサンプリングレートを変更します(サンプリングレートを上げても音声の品質は上がりません。) -
@@ -437,6 +572,24 @@
-->
プリセット機能
+
+ + + プリセット機能を有効にする + + +
- - プリセット機能を有効にする -
疑問文を自動調整
+
+ + + 疑問文のとき語尾の音高を自動的に上げる + + +
- - 疑問文のとき語尾の音高を自動的に上げる -
@@ -485,21 +638,30 @@
ソフトウェア利用状況のデータ収集を許可する
+
+ + + 各UIの利用率などのデータを送信してVOICEVOXの改善に役立てます。テキストデータ・音声データは送信しません。 + + +
- - 各UIの利用率などのデータを送信してVOICEVOXの改善に役立てます。テキストデータ・音声データは送信しません。 -
@@ -808,6 +970,10 @@ export default defineComponent({ diff --git a/src/components/SettingDialog.vue b/src/components/SettingDialog.vue index 793a69532a..7a3eb0494b 100644 --- a/src/components/SettingDialog.vue +++ b/src/components/SettingDialog.vue @@ -293,7 +293,6 @@ self="center right" transition-show="jump-left" transition-hide="jump-right" - v-if="!savingSetting.fixedExportEnabled" > 音声ファイルを設定したフォルダに書き出す @@ -343,6 +342,44 @@ + + + +
書き出しファイル名パターン
+
+ + + 書き出すファイル名のパターンをカスタマイズする + + +
+ +
+ {{ savingSetting.fileNamePattern }} +
+ +
+
上書き防止
@@ -680,10 +717,15 @@ import { ActivePointScrollMode, SplitTextWhenPasteType, } from "@/type/preload"; +import FileNamePatternDialog from "./FileNamePatternDialog.vue"; export default defineComponent({ name: "SettingDialog", + components: { + FileNamePatternDialog, + }, + props: { modelValue: { type: Boolean, @@ -958,6 +1000,8 @@ export default defineComponent({ store.dispatch("SET_SPLIT_TEXT_WHEN_PASTE", { splitTextWhenPaste }); }; + const showsFilePatternEditDialog = ref(false); + return { settingDialogOpenedComputed, engineMode, @@ -979,6 +1023,7 @@ export default defineComponent({ acceptRetrieveTelemetryComputed, splitTextWhenPaste, changeSplitTextWhenPaste, + showsFilePatternEditDialog, }; }, }); @@ -1015,6 +1060,12 @@ export default defineComponent({ background: colors.$primary; } +.text-ellipsis { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + .scroll-mode-button:hover { background: rgba(colors.$primary-rgb, 0.2); } diff --git a/src/store/audio.ts b/src/store/audio.ts index fdbe6bd429..8fdef5311e 100644 --- a/src/store/audio.ts +++ b/src/store/audio.ts @@ -29,11 +29,12 @@ import { import Encoding from "encoding-japanese"; import { PromiseType } from "./vuex"; import { + buildFileNameFromRawData, buildProjectFileName, convertHiraToKana, convertLongVowel, createKanaRegex, - sanitizeFileName, + currentDateString, } from "./utility"; async function generateUniqueIdAndQuery( @@ -103,9 +104,12 @@ function parseTextFile( } function buildFileName(state: State, audioKey: string) { + const fileNamePattern = state.savingSetting.fileNamePattern; + const index = state.audioKeys.indexOf(audioKey); const audioItem = state.audioItems[audioKey]; let styleName: string | undefined = ""; + const character = state.characterInfos?.find((info) => { const result = info.metas.styles.findIndex( (style) => style.styleId === audioItem.styleId @@ -122,20 +126,13 @@ function buildFileName(state: State, audioKey: string) { throw new Error(); } - const characterName = sanitizeFileName(character.metas.speakerName); - let text = sanitizeFileName(audioItem.text); - if (text.length > 10) { - text = text.substring(0, 9) + "…"; - } - - const preFileName = (index + 1).toString().padStart(3, "0"); - // デフォルトのスタイルだとstyleIdが定義されていないのでundefinedになる。なのでファイル名に入れてしまうことを回避する目的で分岐させています。 - if (styleName === undefined) { - return preFileName + `_${characterName}_${text}.wav`; - } - - const sanitizedStyleName = sanitizeFileName(styleName); - return preFileName + `_${characterName}(${sanitizedStyleName})_${text}.wav`; + return buildFileNameFromRawData(fileNamePattern, { + characterName: character.metas.speakerName, + index, + styleName, + text: audioItem.text, + date: currentDateString(), + }); } const audioBlobCache: Record = {}; diff --git a/src/store/setting.ts b/src/store/setting.ts index ace681b83a..bbd209ea4c 100644 --- a/src/store/setting.ts +++ b/src/store/setting.ts @@ -24,6 +24,7 @@ const hotkeyFunctionCache: Record HotkeyReturnType> = {}; export const settingStoreState: SettingStoreState = { savingSetting: { fileEncoding: "UTF-8", + fileNamePattern: "", fixedExportEnabled: false, fixedExportDir: "", avoidOverwrite: false, diff --git a/src/store/utility.ts b/src/store/utility.ts index c9aad029b2..3672b71a33 100644 --- a/src/store/utility.ts +++ b/src/store/utility.ts @@ -45,6 +45,83 @@ export function buildProjectFileName(state: State, extension?: string): string { : defaultFileNameStem; } +export const replaceTagIdToTagString = { + index: "連番", + characterName: "キャラ", + styleName: "スタイル", + text: "テキスト", + date: "日付", +}; +const replaceTagStringToTagId: { [tagString: string]: string } = Object.entries( + replaceTagIdToTagString +).reduce((prev, [k, v]) => ({ ...prev, [v]: k }), {}); + +export const DEFAULT_FILE_NAME_TEMPLATE = + "$連番$_$キャラ$($スタイル$)_$テキスト$.wav"; +const DEFAULT_FILE_NAME_VARIABLES = { + index: 0, + characterName: "四国めたん", + text: "テキストテキストテキスト", + styleName: "ノーマル", + date: currentDateString(), +}; + +export function currentDateString(): string { + const currentDate = new Date(); + const year = currentDate.getFullYear(); + const month = currentDate.getMonth().toString().padStart(2, "0"); + const date = currentDate.getDate().toString().padStart(2, "0"); + + return `${year}${month}${date}`; +} + +function replaceTag( + template: string, + replacer: { [key: string]: string } +): string { + const result = template.replace(/\$(.+?)\$/g, (match, p1) => { + const replaceTagId = replaceTagStringToTagId[p1]; + if (replaceTagId === undefined) { + return match; + } + return replacer[replaceTagId] ?? ""; + }); + + return result; +} + +export function buildFileNameFromRawData( + fileNamePattern = DEFAULT_FILE_NAME_TEMPLATE, + vars = DEFAULT_FILE_NAME_VARIABLES +): string { + let pattern = fileNamePattern; + if (pattern === "") { + // ファイル名指定のオプションが初期値("")ならデフォルトテンプレートを使う + pattern = DEFAULT_FILE_NAME_TEMPLATE; + } + + let text = sanitizeFileName(vars.text); + if (text.length > 10) { + text = text.substring(0, 9) + "…"; + } + + const characterName = sanitizeFileName(vars.characterName); + + const index = (vars.index + 1).toString().padStart(3, "0"); + + const styleName = sanitizeFileName(vars.styleName); + + const date = currentDateString(); + + return replaceTag(pattern, { + index, + characterName, + styleName: styleName, + text, + date, + }); +} + export const getToolbarButtonName = (tag: ToolbarButtonTagType): string => { const tag2NameObj: Record = { PLAY_CONTINUOUSLY: "連続再生", diff --git a/src/type/preload.d.ts b/src/type/preload.d.ts index 46dbe03bb4..62a4d704ab 100644 --- a/src/type/preload.d.ts +++ b/src/type/preload.d.ts @@ -146,6 +146,7 @@ export type SplitTextWhenPasteType = "PERIOD_AND_NEW_LINE" | "NEW_LINE" | "OFF"; export type SavingSetting = { exportLab: boolean; fileEncoding: Encoding; + fileNamePattern: string; fixedExportEnabled: boolean; fixedExportDir: string; avoidOverwrite: boolean; diff --git a/tests/unit/store/Vuex.spec.ts b/tests/unit/store/Vuex.spec.ts index e32308ceca..22b73beab6 100644 --- a/tests/unit/store/Vuex.spec.ts +++ b/tests/unit/store/Vuex.spec.ts @@ -46,6 +46,7 @@ describe("store/vuex.js test", () => { savedLastCommandUnixMillisec: null, savingSetting: { fileEncoding: "UTF-8", + fileNamePattern: "", fixedExportEnabled: false, fixedExportDir: "", avoidOverwrite: false, @@ -161,6 +162,7 @@ describe("store/vuex.js test", () => { assert.propertyVal(store.state.savingSetting, "fixedExportDir", ""); assert.propertyVal(store.state.savingSetting, "avoidOverwrite", false); assert.propertyVal(store.state.savingSetting, "exportLab", false); + assert.propertyVal(store.state.savingSetting, "fileNamePattern", ""); assert.equal(store.state.isPinned, false); assert.isObject(store.state.presetItems); assert.isEmpty(store.state.presetItems); From c3d67b1d93c3e354128ca8af1083d33f55a1dca9 Mon Sep 17 00:00:00 2001 From: Gray Suitcase <41382894+PickledChair@users.noreply.github.com> Date: Wed, 11 May 2022 01:04:48 +0900 Subject: [PATCH 20/42] =?UTF-8?q?Fix:=20Linux=E3=81=A8macOS=E3=81=AE?= =?UTF-8?q?=E9=85=8D=E5=B8=83=E3=83=91=E3=83=83=E3=82=B1=E3=83=BC=E3=82=B8?= =?UTF-8?q?=E3=82=92=E5=8B=95=E4=BD=9C=E5=8F=AF=E8=83=BD=E3=81=AB=E3=81=99?= =?UTF-8?q?=E3=82=8B=20(#798)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ビルド後はappDirPathにある.envを読みに行く * .envのパス指定に関するコメントを追加 --- src/background.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/background.ts b/src/background.ts index eed5659919..78371ca859 100644 --- a/src/background.ts +++ b/src/background.ts @@ -79,7 +79,18 @@ process.on("unhandledRejection", (reason) => { // .envから設定をprocess.envに読み込み const appDirPath = path.dirname(app.getPath("exe")); -dotenv.config({ override: true }); + +// NOTE: 開発版では、カレントディレクトリにある .env ファイルを読み込む。 +// 一方、配布パッケージ版では .env ファイルが実行ファイルと同じディレクトリに配置されているが、 +// Linux・macOS ではそのディレクトリはカレントディレクトリとはならないため、.env ファイルの +// パスを明示的に指定する必要がある。Windows の配布パッケージ版でもこの設定で起動できるため、 +// 全 OS で共通の条件分岐とした。 +if (isDevelopment) { + dotenv.config({ override: true }); +} else { + const envPath = path.join(appDirPath, ".env"); + dotenv.config({ path: envPath }); +} protocol.registerSchemesAsPrivileged([ { scheme: "app", privileges: { secure: true, standard: true, stream: true } }, From f40f4adcff22e0321b701fb9e3e628b4cfe08c9e Mon Sep 17 00:00:00 2001 From: Hiroshiba Date: Wed, 11 May 2022 01:06:36 +0900 Subject: [PATCH 21/42] =?UTF-8?q?=E3=82=AD=E3=83=A3=E3=83=A9=E6=95=B0?= =?UTF-8?q?=E3=81=8C=E5=A4=9A=E3=81=84=E3=81=A8=E3=81=8D=E3=81=AB=E3=82=B9?= =?UTF-8?q?=E3=82=AF=E3=83=AD=E3=83=BC=E3=83=AB=E3=83=90=E3=83=BC=E3=82=92?= =?UTF-8?q?=E8=A1=A8=E7=A4=BA=E3=81=99=E3=82=8B=20(#749)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * キャラ数が多いときにスクロールバーを表示する * .transparent-backdropクラス追加、seamless除去 * 追加し忘れ --- src/components/AcceptRetrieveTelemetryDialog.vue | 3 +-- src/components/AcceptTermsDialog.vue | 3 +-- src/components/CharacterOrderDialog.vue | 11 ++++++++++- src/components/DefaultStyleSelectDialog.vue | 3 +-- src/components/DictionaryManageDialog.vue | 3 +-- src/components/HeaderBarCustomDialog.vue | 3 +-- src/components/HelpDialog.vue | 3 +-- src/components/HotkeySettingDialog.vue | 3 +-- src/components/SettingDialog.vue | 3 +-- src/styles/_index.scss | 5 +++++ 10 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/components/AcceptRetrieveTelemetryDialog.vue b/src/components/AcceptRetrieveTelemetryDialog.vue index aba9eea973..14b6bed4ca 100644 --- a/src/components/AcceptRetrieveTelemetryDialog.vue +++ b/src/components/AcceptRetrieveTelemetryDialog.vue @@ -1,10 +1,9 @@