package academy import ( "fmt" "log" ) // VideoGenerator orchestrates video generation with 3-tier fallback: // 1. HeyGen + ElevenLabs -> Avatar video with voice // 2. ElevenLabs only -> Audio podcast style // 3. No external services -> Text + Quiz only type VideoGenerator struct { elevenLabs *ElevenLabsClient heyGen *HeyGenClient } // NewVideoGenerator creates a new video generator func NewVideoGenerator() *VideoGenerator { return &VideoGenerator{ elevenLabs: NewElevenLabsClient(), heyGen: NewHeyGenClient(), } } // GenerationMode describes the available generation mode type GenerationMode string const ( ModeAvatarVideo GenerationMode = "avatar_video" // HeyGen + ElevenLabs ModeAudioOnly GenerationMode = "audio_only" // ElevenLabs only ModeTextOnly GenerationMode = "text_only" // No external services ) // GetAvailableMode returns the best available generation mode func (vg *VideoGenerator) GetAvailableMode() GenerationMode { if vg.heyGen.IsConfigured() && vg.elevenLabs.IsConfigured() { return ModeAvatarVideo } if vg.elevenLabs.IsConfigured() { return ModeAudioOnly } return ModeTextOnly } // GenerateAudio generates audio from text using ElevenLabs func (vg *VideoGenerator) GenerateAudio(text string) ([]byte, error) { if !vg.elevenLabs.IsConfigured() { return nil, fmt.Errorf("ElevenLabs not configured") } log.Printf("Generating audio for text (%d chars)...", len(text)) return vg.elevenLabs.TextToSpeech(text) } // GenerateVideo generates a video from audio using HeyGen func (vg *VideoGenerator) GenerateVideo(audioURL string) (string, error) { if !vg.heyGen.IsConfigured() { return "", fmt.Errorf("HeyGen not configured") } log.Printf("Creating HeyGen video with audio: %s", audioURL) resp, err := vg.heyGen.CreateVideo(audioURL) if err != nil { return "", err } return resp.Data.VideoID, nil } // CheckVideoStatus checks if a HeyGen video is ready func (vg *VideoGenerator) CheckVideoStatus(videoID string) (string, string, error) { if !vg.heyGen.IsConfigured() { return "", "", fmt.Errorf("HeyGen not configured") } status, err := vg.heyGen.GetVideoStatus(videoID) if err != nil { return "", "", err } return status.Data.Status, status.Data.VideoURL, nil } // GetStatus returns the configuration status func (vg *VideoGenerator) GetStatus() map[string]interface{} { return map[string]interface{}{ "mode": string(vg.GetAvailableMode()), "elevenLabsConfigured": vg.elevenLabs.IsConfigured(), "heyGenConfigured": vg.heyGen.IsConfigured(), } }