Newer
Older
remotion_docker_devcontainer / voicevox-remotion-template / src / avatar-animations.ts
export type AvatarAnimationContext = Readonly<{
  frame: number;
  fps: number;
  focused: boolean;
  hasMultipleCharacters: boolean;
}>;

export type AvatarAnimation = (context: AvatarAnimationContext) => number;

const gentleBobAmplitude = ({focused}: AvatarAnimationContext) =>
  focused ? 10 : 3.5;

export const idleAvatarAnimations = {
  none: () => 0,
  gentleBob: (context) =>
    Math.sin((context.frame / context.fps) * Math.PI * 2) *
    gentleBobAmplitude(context),
} satisfies Record<string, AvatarAnimation>;

export type IdleAvatarAnimationType = keyof typeof idleAvatarAnimations;

export const speakingAvatarAnimations = {
  none: () => 0,
  gentleBob: idleAvatarAnimations.gentleBob,
  quickHop: ({frame, fps}) => {
    const cycleFrames = Math.max(1, Math.round(fps * 0.25));
    const progress = (frame % cycleFrames) / cycleFrames;

    return -Math.sin(progress * Math.PI) * 7;
  },
} satisfies Record<string, AvatarAnimation>;

export type SpeakingAvatarAnimationType = keyof typeof speakingAvatarAnimations;