import {getStandeeSet, type AvatarDefinition} from "../../standee-sets";
import type {VQStillEvent} from "../../lib/VQRemotionLib";
export type VoicevoxVoice = Readonly<{
speakerName: string;
styleName: string;
}>;
export type CharacterDefinition = Readonly<{
displayName: string;
voicevox: VoicevoxVoice;
avatar: AvatarDefinition;
}>;
export const characters = {
sayo: {
displayName: "小夜",
voicevox: {
speakerName: "小夜/SAYO",
styleName: "ノーマル",
},
avatar: {
...getStandeeSet("sayo_ohnegus_ai"),
accentColor: "#6b5f83",
speakingAnimationType: "rhubarbLipSync",
idleAnimationType: "none",
},
},
} as const satisfies Record<string, CharacterDefinition>;
export type CharacterId = keyof typeof characters;
export type SpeechOptions = Readonly<{
subtitle?: string;
voicevox?: Partial<VoicevoxVoice>;
durationSeconds?: number;
}>;
export type SpeechEvent = Readonly<{
type: "say";
id: string;
character: CharacterId;
text: string;
subtitle?: string;
voicevox?: Partial<VoicevoxVoice>;
durationSeconds?: number;
}>;
export type StillEvent = VQStillEvent;
export type TimelineEvent = SpeechEvent | StillEvent;
export const say = (
id: string,
character: CharacterId,
text: string,
options: SpeechOptions = {}
): SpeechEvent => ({
type: "say",
id,
character,
text,
...options,
});
export const still = (
id: string,
imagePath: string,
options: Omit<StillEvent, "type" | "id" | "imagePath"> = {}
): StillEvent => ({
type: "still",
id,
imagePath,
...options,
});
export const timeline = [
say("pizza-oven-project-01-sayo-001", "sayo", "こんにちは。小夜です。"),
say("pizza-oven-project-01-sayo-002", "sayo", "ピザって美味しいじゃないですか。"),
say("pizza-oven-project-01-sayo-003", "sayo", "だから、作る事にしたんですよね。"),
still(
"pizza-oven-project-01-oven-still-001",
"image/still/blender-oven-still01.png",
{
durationSeconds: 1.5,
fit: "cover",
}
),
say("pizza-oven-project-01-sayo-004", "sayo", "ピザ窯を。", {
durationSeconds: 3,
}),
say("pizza-oven-project-01-sayo-005", "sayo", "まずはblender上で、耐熱レンガの寸法を元に積み方を設計することにしました。"),
] satisfies TimelineEvent[];
export const isSpeechEvent = (
event: TimelineEvent
): event is SpeechEvent => event.type === "say";
export const script = timeline.filter(isSpeechEvent);