import {
defineVQChronologicalScenario,
defineVQScenarioAssetWorkflow,
totalVQChronologicalScenarioDurationInFrames,
} from "../../lib/VQRemotionLib/scenario";
import {timeline, type SpeechEvent, type TimelineEvent} from "./script";
import voicevoxManifest from "./voicevox-manifest.json";
type ManifestEntry = {
id: string;
character?: string;
speakerName?: string;
styleName?: string;
speakerId?: number;
file: string;
durationSeconds: number;
};
const manifestEntries = voicevoxManifest as ManifestEntry[];
const manifestById = new Map(
manifestEntries.map((entry) => [entry.id, entry])
);
export const PIZZA_OVEN_PROJECT_01_FPS = 30;
export const PIZZA_OVEN_PROJECT_01_GAP_FRAMES = 6;
export const hasAudioForSpeech = (speech: SpeechEvent) =>
manifestById.has(speech.id);
export const audioFileForSpeech = (speech: SpeechEvent) =>
manifestById.get(speech.id)?.file ??
`audio/pizza-oven-project-01/lines/${speech.id}.wav`;
export const durationForSpeech = (
speech: SpeechEvent,
fps = PIZZA_OVEN_PROJECT_01_FPS
) => {
const entry = manifestById.get(speech.id);
if (entry && Number.isFinite(entry.durationSeconds)) {
return Math.max(1, Math.ceil(entry.durationSeconds * fps));
}
if (speech.durationSeconds && Number.isFinite(speech.durationSeconds)) {
return Math.max(1, Math.ceil(speech.durationSeconds * fps));
}
const estimatedSeconds = Math.max(1.2, speech.text.length * 0.11);
return Math.ceil(estimatedSeconds * fps);
};
export const durationForTimelineEvent = (
event: TimelineEvent,
fps = PIZZA_OVEN_PROJECT_01_FPS
) => durationForSpeech(event, fps);
export const pizzaOvenProject01AssetWorkflow =
defineVQScenarioAssetWorkflow({
voicevox: {
scriptPath: "src/data/pizza-oven-project-01/script.ts",
outputDir: "public/audio/pizza-oven-project-01/lines",
manifestPath: "src/data/pizza-oven-project-01/voicevox-manifest.json",
},
rhubarb: {
sourceManifestPath: "src/data/pizza-oven-project-01/voicevox-manifest.json",
manifestPath: "src/generated/lipsync/manifest.json",
outputDir: "src/generated/lipsync",
rawOutputDir: "public/lipsync/raw",
},
});
export const pizzaOvenProject01Scenario =
defineVQChronologicalScenario<TimelineEvent>({
timeline,
gapFrames: PIZZA_OVEN_PROJECT_01_GAP_FRAMES,
durationForEvent: durationForTimelineEvent,
assetWorkflow: pizzaOvenProject01AssetWorkflow,
});
export const totalPizzaOvenProject01DurationInFrames = (
fps = PIZZA_OVEN_PROJECT_01_FPS
) =>
totalVQChronologicalScenarioDurationInFrames(
pizzaOvenProject01Scenario,
fps
);