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

複数選択:キャラクターを変更できるように #1546

Merged
merged 9 commits into from
Sep 19, 2023
10 changes: 6 additions & 4 deletions src/components/AudioCell.vue
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,8 @@ const userOrderedCharacterInfos = computed(() => {
throw new Error("USER_ORDERED_CHARACTER_INFOS == undefined");
return infos;
});
const isInitializingSpeaker = computed(
() => store.state.audioKeyInitializingSpeaker === props.audioKey
const isInitializingSpeaker = computed(() =>
store.state.audioKeysWithInitializingSpeaker.includes(props.audioKey)
);
const audioItem = computed(() => store.state.audioItems[props.audioKey]);

Expand Down Expand Up @@ -262,8 +262,10 @@ const selectedVoice = computed<Voice | undefined>({
},
set(voice: Voice | undefined) {
if (voice == undefined) return;
store.dispatch("COMMAND_CHANGE_VOICE", {
audioKey: props.audioKey,
store.dispatch("COMMAND_MULTI_CHANGE_VOICE", {
audioKeys: isMultiSelectEnabled.value
? store.getters.SELECTED_AUDIO_KEYS
: [props.audioKey],
voice,
});
},
Expand Down
5 changes: 4 additions & 1 deletion src/components/CharacterPortrait.vue
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ const portraitPath = computed(

const isInitializingSpeaker = computed(() => {
const activeAudioKey = store.getters.ACTIVE_AUDIO_KEY;
return store.state.audioKeyInitializingSpeaker === activeAudioKey;
return (
activeAudioKey &&
store.state.audioKeysWithInitializingSpeaker.includes(activeAudioKey)
);
});

const isMultipleEngine = computed(() => store.state.engineIds.length > 1);
Expand Down
172 changes: 90 additions & 82 deletions src/store/audio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ const getAudioElement = (() => {

export const audioStoreState: AudioStoreState = {
characterInfos: {},
audioKeysWithInitializingSpeaker: [],
morphableTargetsInfo: {},
audioItems: {},
audioKeys: [],
Expand Down Expand Up @@ -504,30 +505,30 @@ export const audioStore = createPartialStore<AudioStoreTypes>({
/**
* AudioItemに設定される話者(スタイルID)に対してエンジン側の初期化を行い、即座に音声合成ができるようにする。
*/
async action({ commit, dispatch }, { engineId, audioKey, styleId }) {
async action({ commit, dispatch }, { engineId, audioKeys, styleId }) {
const isInitialized = await dispatch("IS_INITIALIZED_ENGINE_SPEAKER", {
engineId,
styleId,
});
if (isInitialized) return;

commit("SET_AUDIO_KEY_INITIALIZING_SPEAKER", {
audioKey,
commit("SET_AUDIO_KEYS_WITH_INITIALIZING_SPEAKER", {
audioKeys,
});
await dispatch("INITIALIZE_ENGINE_SPEAKER", {
engineId,
styleId,
}).finally(() => {
commit("SET_AUDIO_KEY_INITIALIZING_SPEAKER", {
audioKey: undefined,
commit("SET_AUDIO_KEYS_WITH_INITIALIZING_SPEAKER", {
audioKeys: [],
});
});
},
},

SET_AUDIO_KEY_INITIALIZING_SPEAKER: {
mutation(state, { audioKey }: { audioKey?: AudioKey }) {
state.audioKeyInitializingSpeaker = audioKey;
SET_AUDIO_KEYS_WITH_INITIALIZING_SPEAKER: {
mutation(state, { audioKeys }: { audioKeys: AudioKey[] }) {
state.audioKeysWithInitializingSpeaker = audioKeys;
},
},

Expand Down Expand Up @@ -2095,10 +2096,10 @@ export const audioCommandStore = transformCommandStore(
},
},

COMMAND_CHANGE_VOICE: {
COMMAND_MULTI_CHANGE_VOICE: {
mutation(
draft,
payload: { audioKey: AudioKey; voice: Voice } & (
payload: { audioKeys: AudioKey[]; voice: Voice } & (
| { update: "RollbackStyleId" }
| {
update: "AccentPhrases";
Expand All @@ -2110,93 +2111,100 @@ export const audioCommandStore = transformCommandStore(
}
)
) {
audioStore.mutations.SET_AUDIO_VOICE(draft, {
audioKey: payload.audioKey,
voice: payload.voice,
});
for (const audioKey of payload.audioKeys) {
audioStore.mutations.SET_AUDIO_VOICE(draft, {
audioKey,
voice: payload.voice,
});
}

if (payload.update === "RollbackStyleId") return;

const presetKey = draft.audioItems[payload.audioKey].presetKey;

const { nextPresetKey, shouldApplyPreset } = determineNextPresetKey(
draft,
payload.voice,
presetKey,
"changeVoice"
);
for (const audioKey of payload.audioKeys) {
const presetKey = draft.audioItems[audioKey].presetKey;

audioStore.mutations.SET_AUDIO_PRESET_KEY(draft, {
audioKey: payload.audioKey,
presetKey: nextPresetKey,
});
const { nextPresetKey, shouldApplyPreset } = determineNextPresetKey(
draft,
payload.voice,
presetKey,
"changeVoice"
);

if (payload.update == "AccentPhrases") {
audioStore.mutations.SET_ACCENT_PHRASES(draft, {
audioKey: payload.audioKey,
accentPhrases: payload.accentPhrases,
});
} else if (payload.update == "AudioQuery") {
audioStore.mutations.SET_AUDIO_QUERY(draft, {
audioKey: payload.audioKey,
audioQuery: payload.query,
audioStore.mutations.SET_AUDIO_PRESET_KEY(draft, {
audioKey,
presetKey: nextPresetKey,
});
}

if (shouldApplyPreset) {
audioStore.mutations.APPLY_AUDIO_PRESET(draft, {
audioKey: payload.audioKey,
});
if (payload.update == "AccentPhrases") {
audioStore.mutations.SET_ACCENT_PHRASES(draft, {
audioKey,
accentPhrases: payload.accentPhrases,
});
} else if (payload.update == "AudioQuery") {
audioStore.mutations.SET_AUDIO_QUERY(draft, {
audioKey,
audioQuery: payload.query,
});
}

if (shouldApplyPreset) {
audioStore.mutations.APPLY_AUDIO_PRESET(draft, {
audioKey,
});
}
}
},
async action(
{ state, dispatch, commit },
{ audioKey, voice }: { audioKey: AudioKey; voice: Voice }
{ audioKeys, voice }: { audioKeys: AudioKey[]; voice: Voice }
) {
const query = state.audioItems[audioKey].query;
const engineId = voice.engineId;
const styleId = voice.styleId;
try {
await dispatch("SETUP_SPEAKER", { audioKey, engineId, styleId });

if (query !== undefined) {
const accentPhrases = query.accentPhrases;
const newAccentPhrases: AccentPhrase[] = await dispatch(
"FETCH_MORA_DATA",
{
accentPhrases,
engineId,
styleId,
await dispatch("SETUP_SPEAKER", { audioKeys, engineId, styleId });
await Promise.all(
audioKeys.map(async (audioKey) => {
try {
const query = state.audioItems[audioKey].query;
if (query !== undefined) {
const accentPhrases = query.accentPhrases;
const newAccentPhrases: AccentPhrase[] = await dispatch(
"FETCH_MORA_DATA",
{
accentPhrases,
engineId,
styleId,
}
);
commit("COMMAND_MULTI_CHANGE_VOICE", {
audioKeys,
voice,
update: "AccentPhrases",
accentPhrases: newAccentPhrases,
});
} else {
const text = state.audioItems[audioKey].text;
const query: AudioQuery = await dispatch("FETCH_AUDIO_QUERY", {
text: text,
engineId,
styleId,
});
commit("COMMAND_MULTI_CHANGE_VOICE", {
audioKeys,
voice,
update: "AudioQuery",
query,
});
}
);
commit("COMMAND_CHANGE_VOICE", {
audioKey,
voice,
update: "AccentPhrases",
accentPhrases: newAccentPhrases,
});
} else {
const text = state.audioItems[audioKey].text;
const query: AudioQuery = await dispatch("FETCH_AUDIO_QUERY", {
text: text,
engineId,
styleId,
});
commit("COMMAND_CHANGE_VOICE", {
audioKey,
voice,
update: "AudioQuery",
query,
});
}
} catch (error) {
commit("COMMAND_CHANGE_VOICE", {
audioKey,
voice,
update: "RollbackStyleId",
});
throw error;
}
} catch (error) {
commit("COMMAND_MULTI_CHANGE_VOICE", {
audioKeys,
voice,
update: "RollbackStyleId",
});
throw error;
}
})
);
},
},

Expand Down
14 changes: 7 additions & 7 deletions src/store/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export type StoreType<T, U extends "getter" | "mutation" | "action"> = {
export type AudioStoreState = {
characterInfos: Record<EngineId, CharacterInfo[]>;
morphableTargetsInfo: Record<EngineId, MorphableTargetInfoTable>;
audioKeyInitializingSpeaker?: string;
audioKeysWithInitializingSpeaker: AudioKey[];
audioItems: Record<AudioKey, AudioItem>;
audioKeys: AudioKey[];
audioStates: Record<AudioKey, AudioState>;
Expand Down Expand Up @@ -182,14 +182,14 @@ export type AudioStoreTypes = {

SETUP_SPEAKER: {
action(payload: {
audioKey: AudioKey;
audioKeys: AudioKey[];
engineId: EngineId;
styleId: StyleId;
}): void;
};

SET_AUDIO_KEY_INITIALIZING_SPEAKER: {
mutation: { audioKey?: AudioKey };
SET_AUDIO_KEYS_WITH_INITIALIZING_SPEAKER: {
mutation: { audioKeys: AudioKey[] };
};

SET_ACTIVE_AUDIO_KEY: {
Expand Down Expand Up @@ -529,8 +529,8 @@ export type AudioCommandStoreTypes = {
action(payload: { audioKey: AudioKey; text: string }): void;
};

COMMAND_CHANGE_VOICE: {
mutation: { audioKey: AudioKey; voice: Voice } & (
COMMAND_MULTI_CHANGE_VOICE: {
mutation: { audioKeys: AudioKey[]; voice: Voice } & (
| { update: "RollbackStyleId" }
| {
update: "AccentPhrases";
Expand All @@ -541,7 +541,7 @@ export type AudioCommandStoreTypes = {
query: AudioQuery;
}
);
action(payload: { audioKey: AudioKey; voice: Voice }): void;
action(payload: { audioKeys: AudioKey[]; voice: Voice }): void;
};

COMMAND_CHANGE_ACCENT: {
Expand Down
7 changes: 5 additions & 2 deletions src/views/EditorHome.vue
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,10 @@ watch(userOrderedCharacterInfos, (userOrderedCharacterInfos) => {
};

// FIXME: UNDOができてしまうのでできれば直したい
store.dispatch("COMMAND_CHANGE_VOICE", { audioKey: first, voice: voice });
store.dispatch("COMMAND_MULTI_CHANGE_VOICE", {
audioKeys: [first],
voice: voice,
});
}
});

Expand Down Expand Up @@ -574,7 +577,7 @@ onMounted(async () => {

// 最初の話者を初期化
store.dispatch("SETUP_SPEAKER", {
audioKey: newAudioKey,
audioKeys: [newAudioKey],
engineId: audioItem.voice.engineId,
styleId: audioItem.voice.styleId,
});
Expand Down
10 changes: 10 additions & 0 deletions tests/e2e/browser/複数選択/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Page } from "@playwright/test";

export async function addAudioCells(page: Page, count: number) {
for (let i = 0; i < count; i++) {
await page.getByRole("button", { name: "テキストを追加" }).click();
await page.waitForTimeout(100);
}
}

export const ctrlLike = process.platform === "darwin" ? "Meta" : "Control";
Loading