Skip to content

Commit

Permalink
ファイルの書き出し時の名前設定にプロジェクトファイル名を含められるようにする (VOICEVOX#2137)
Browse files Browse the repository at this point in the history
* 書き出しファイルにプロジェクトファイル名を含める

* README修正

* 依存関係を綺麗に保ち、書き出し時に拡張子ありで出力する

* PROJECT_NAME_WITH_EXTを作成

* 微調整

---------

Co-authored-by: Hiroshiba <hihokaruta@gmail.com>
  • Loading branch information
jdkfx and Hiroshiba committed Jun 30, 2024
1 parent e36ab85 commit bf9fd0f
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 9 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ npm ci

Windows の場合でもパスの区切り文字は`\`ではなく`/`なのでご注意ください。

また、macOS 向けの`VOICEVOX.app`を利用している場合は`/path/to/VOICEVOX.app/Contents/MacOS/run`を指定してください。
また、macOS 向けの`VOICEVOX.app`を利用している場合は`/path/to/VOICEVOX.app/Contents/MacOS/vv-engine/run`を指定してください。

Linux の場合は、[Releases](https://github.com/VOICEVOX/voicevox/releases/)から入手できる tar.gz 版に含まれる`run`コマンドを指定してください。
AppImage 版の場合は`$ /path/to/VOICEVOX.AppImage --appimage-mount`でファイルシステムをマウントできます。
Expand Down
9 changes: 7 additions & 2 deletions src/store/audio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
formatCharacterStyleName,
TuningTranscription,
filterCharacterInfosByStyleType,
DEFAULT_PROJECT_NAME,
} from "./utility";
import { createPartialStore } from "./vuex";
import { determineNextPresetKey } from "./preset";
Expand Down Expand Up @@ -1216,12 +1217,14 @@ export const audioStore = createPartialStore<AudioStoreTypes>({

const defaultFileBaseName = sanitizeFileName(headTailItemText);

return defaultFileBaseName === "" ? "Untitled" : defaultFileBaseName;
return defaultFileBaseName === ""
? DEFAULT_PROJECT_NAME
: defaultFileBaseName;
},
},

DEFAULT_AUDIO_FILE_NAME: {
getter: (state) => (audioKey) => {
getter: (state, getters) => (audioKey) => {
const fileNamePattern = state.savingSetting.fileNamePattern;

const index = state.audioKeys.indexOf(audioKey);
Expand All @@ -1241,12 +1244,14 @@ export const audioStore = createPartialStore<AudioStoreTypes>({
if (style == undefined) throw new Error("assert style != undefined");

const styleName = style.styleName || DEFAULT_STYLE_NAME;
const projectName = getters.PROJECT_NAME ?? DEFAULT_PROJECT_NAME;
return buildAudioFileNameFromRawData(fileNamePattern, {
characterName: character.metas.speakerName,
index,
styleName,
text: audioItem.text,
date: currentDateString(),
projectName,
});
},
},
Expand Down
10 changes: 9 additions & 1 deletion src/store/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,22 @@ const applySongProjectToStore = async (
};

export const projectStore = createPartialStore<ProjectStoreTypes>({
PROJECT_NAME: {
PROJECT_NAME_WITH_EXT: {
getter(state) {
return state.projectFilePath
? getBaseName(state.projectFilePath)
: undefined;
},
},

PROJECT_NAME: {
getter(state) {
return state.projectFilePath
? getBaseName(state.projectFilePath).replace(".vvproj", "")
: undefined;
},
},

SET_PROJECT_FILEPATH: {
mutation(state, { filePath }: { filePath?: string }) {
state.projectFilePath = filePath;
Expand Down
6 changes: 3 additions & 3 deletions src/store/singing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
SequencerEditTarget,
PhraseSourceHash,
} from "./type";
import { sanitizeFileName } from "./utility";
import { DEFAULT_PROJECT_NAME, sanitizeFileName } from "./utility";
import { EngineId, NoteId, StyleId } from "@/type/preload";
import { FrameAudioQuery, Note as NoteForRequestToEngine } from "@/openapi";
import { ResultError, getValueOrThrow } from "@/type/result";
Expand Down Expand Up @@ -1895,7 +1895,7 @@ export const singingStore = createPartialStore<SingingStoreTypes>({
const generateDefaultSongFileName = () => {
const projectName = getters.PROJECT_NAME;
if (projectName) {
return projectName.split(".")[0] + ".wav";
return projectName + ".wav";
}

const singer = getters.SELECTED_TRACK.singer;
Expand All @@ -1915,7 +1915,7 @@ export const singingStore = createPartialStore<SingingStoreTypes>({
}
}

return "Untitled.wav";
return `${DEFAULT_PROJECT_NAME}.wav`;
};

const exportWaveFile = async (): Promise<SaveResultObject> => {
Expand Down
4 changes: 4 additions & 0 deletions src/store/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1473,6 +1473,10 @@ export type ProjectStoreState = {
};

export type ProjectStoreTypes = {
PROJECT_NAME_WITH_EXT: {
getter: string | undefined;
};

PROJECT_NAME: {
getter: string | undefined;
};
Expand Down
5 changes: 5 additions & 0 deletions src/store/utility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
import { AccentPhrase, Mora } from "@/openapi";

export const DEFAULT_STYLE_NAME = "ノーマル";
export const DEFAULT_PROJECT_NAME = "Untitled";

export const formatCharacterStyleName = (
characterName: string,
Expand Down Expand Up @@ -120,6 +121,7 @@ export const replaceTagIdToTagString = {
styleName: "スタイル",
text: "テキスト",
date: "日付",
projectName: "プロジェクト名",
};
const replaceTagStringToTagId: { [tagString: string]: string } = Object.entries(
replaceTagIdToTagString,
Expand All @@ -134,6 +136,7 @@ const DEFAULT_AUDIO_FILE_NAME_VARIABLES = {
text: "テキストテキストテキスト",
styleName: DEFAULT_STYLE_NAME,
date: currentDateString(),
projectName: "VOICEVOXプロジェクト",
};

export function currentDateString(): string {
Expand Down Expand Up @@ -342,12 +345,14 @@ export function buildAudioFileNameFromRawData(
const index = (vars.index + 1).toString().padStart(3, "0");
const styleName = sanitizeFileName(vars.styleName);
const date = vars.date;
const projectName = sanitizeFileName(vars.projectName);
return replaceTag(pattern, {
text,
characterName,
index,
styleName,
date,
projectName,
});
}

Expand Down
5 changes: 3 additions & 2 deletions tests/unit/store/utility.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,17 +251,18 @@ describe("isAccentPhrasesTextDifferent", () => {

test("buildAudioFileNameFromRawData", () => {
const fileNamePattern =
"index=$連番$ characterName=$キャラ$ text=$テキスト$ styleName=$スタイル$ date=$日付$";
"index=$連番$ characterName=$キャラ$ text=$テキスト$ styleName=$スタイル$ date=$日付$ projectName=$プロジェクト名$";
const vars = {
index: 10,
characterName: "キャラ1",
text: "テストテキスト",
styleName: "スタイル1",
date: "20210801",
projectName: "サンプルプロジェクト",
};
const result = buildAudioFileNameFromRawData(fileNamePattern, vars);
expect(result).toBe(
"index=011 characterName=キャラ1 text=テストテキスト styleName=スタイル1 date=20210801",
"index=011 characterName=キャラ1 text=テストテキスト styleName=スタイル1 date=20210801 projectName=サンプルプロジェクト",
);
});

Expand Down

0 comments on commit bf9fd0f

Please sign in to comment.