Discussions

Ask a Question

DIFFICULTIES TO GET GENERATED VIDEOS URL BACK IN ORDER TO DISPLAY THEM ON MY WEB APP

'Annie_expressive4_public', 'teaching' => 'Annie_expressive4_public', 'project_management'=> 'Annie_expressive4_public', 'pharmacy' => 'Annie_expressive4_public', 'agro' => 'Annie_expressive4_public', ]; $VOICE_ID = '0b41c487c6da4f5ba5782bbe462958e8'; // === UTILS === function logMessage($msg) { $logFile = __DIR__ . '/logs/avatar_gen.log'; if (!is_dir(dirname($logFile))) mkdir(dirname($logFile), 0755, true); $timestamp = date('Y-m-d H:i:s'); error_log("[$timestamp] [AvatarGen] $msg\n", 3, $logFile); echo "[$timestamp] $msg\n"; } function heyGenRequest($method, $url, $payload = null) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 60); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json', 'Accept: application/json', 'X-Api-Key: ' . HEYGEN_API_KEY ]); if ($method === 'POST' && $payload) { curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload)); } $response = curl_exec($ch); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); $error = curl_error($ch); curl_close($ch); if ($error) { throw new Exception("cURL error: $error"); } // 🔍 Debug temporaire if ($http_code !== 200) { logMessage("DEBUG HTTP $http_code - URL: $url"); logMessage("DEBUG Response: " . substr($response, 0, 200)); } return [$http_code, json_decode($response, true)]; } // === ÉTAPE 1 : Lancer la génération === function generateVideo($text, $user_group) { global $AVATAR_MAP, $VOICE_ID; $avatar_id = $AVATAR_MAP[$user_group] ?? $AVATAR_MAP['default']; $payload = [ "video_inputs" => [[ "character" => [ "type" => "avatar", "avatar_id" => $avatar_id, "scale" => 1 ], "voice" => [ "type" => "text", "input_text" => $text, "voice_id" => $VOICE_ID ], "background" => ["type" => "color", "value" => "#f8fafc"] ]], "dimension" => ["width" => 1920, "height" => 1080], "test" => false, "caption" => false ]; for ($attempt = 1; $attempt <= MAX_RETRIES; $attempt++) { try { [$code, $data] = heyGenRequest('POST', HEYGEN_API_URL, $payload); if ($code === 200 && !empty($data['data']['video_id'])) { return $data['data']['video_id']; } else { $msg = "HeyGen error (attempt $attempt): HTTP $code - " . ($data['message'] ?? json_encode($data)); logMessage($msg); if ($attempt < MAX_RETRIES) sleep(RETRY_DELAY_SEC); } } catch (Exception $e) { logMessage("Exception (attempt $attempt): " . $e->getMessage()); if ($attempt < MAX_RETRIES) sleep(RETRY_DELAY_SEC); } } throw new Exception("Échec après " . MAX_RETRIES . " tentatives."); } // === ÉTAPE 2 : Attendre la fin de la génération === function waitForVideoCompletion($video_id) { $elapsed = 0; $check_interval = 5; $max_checks = MAX_WAIT_SEC / $check_interval; logMessage("⏳ Attente de la complétion de la vidéo (max " . MAX_WAIT_SEC . " sec)..."); logMessage("🔍 Video ID: $video_id"); // Délai initial plus long (HeyGen met du temps à indexer) sleep(25); for ($check = 1; $check <= $max_checks; $check++) { try { // ✅ CORRECTION DÉFINITIVE : POST avec video_id dans le body JSON (API v1) $payload = ['video_id' => $video_id]; [$code, $data] = heyGenRequest('POST', HEYGEN_STATUS_URL, $payload); if ($code === 200 && !empty($data['data'])) { $status = $data['data']['status'] ?? 'unknown'; logMessage("CallCheck #$check (elapsed: {$elapsed}s) - Statut: $status"); if ($status === 'completed') { $video_url = $data['data']['video_url'] ?? null; if ($video_url) { logMessage("✅ URL CDN trouvée : $video_url"); return $video_url; } // Recherche alternative dans assets $assets = $data['data']['assets'] ?? []; foreach ($assets as $asset) { if (isset($asset['type']) && $asset['type'] === 'video' && isset($asset['url'])) { $video_url = $asset['url']; logMessage("✅ URL trouvée dans assets : $video_url"); return $video_url; } } throw new Exception("Vidéo complétée mais URL non trouvée"); } elseif ($status === 'failed') { $reason = $data['data']['reason'] ?? 'Unknown'; throw new Exception("Échec HeyGen : $reason"); } } else { $error_msg = $data['message'] ?? json_encode($data); logMessage("⚠️ CheckCall #$check - HTTP $code - $error_msg"); } sleep($check_interval); $elapsed += $check_interval; } catch (Exception $e) { logMessage("⚠️ CheckCall #$check erreur: " . $e->getMessage()); sleep($check_interval); $elapsed += $check_interval; } } throw new Exception("Timeout après " . MAX_WAIT_SEC . " secondes"); } // === ÉTAPE 3 : Mettre à jour la base === function updateMediaUrl($conn, $content_date, $user_group, $video_url) { logMessage("💾 Mise à jour de la base de données..."); $stmt = $conn->prepare(" UPDATE daily_content SET media_url = :url, media_type = 'video' WHERE content_date = :date AND user_group = :group "); $stmt->execute([ ':url' => $video_url, ':date' => $content_date, ':group' => $user_group ]); $rows = $stmt->rowCount(); logMessage("✅ Base mise à jour : $rows ligne(s) modifiée(s) - $user_group / $content_date → $video_url"); // Vérification $verify = $conn->prepare(" SELECT media_url, media_type FROM daily_content WHERE content_date = :date AND user_group = :group "); $verify->execute([':date' => $content_date, ':group' => $user_group]); $result = $verify->fetch(PDO::FETCH_ASSOC); if ($result && !empty($result['media_url'])) { logMessage("🔍 Vérification BDD : OK → " . substr($result['media_url'], 0, 60) . "..."); } else { logMessage("⚠️ Vérification BDD : ÉCHOUÉE"); } } // === SCRIPT PRINCIPAL === try { logMessage("╔════════════════════════════════════════════════════════════╗"); logMessage("║ DÉMARRAGE GÉNÉRATION VIDÉO HEYGEN v2 ║"); logMessage("╚════════════════════════════════════════════════════════════╝"); $stmt = $conn->prepare(" SELECT id, content_date, user_group, reading_text FROM daily_content WHERE content_date = :today AND (media_url IS NULL OR media_url = '' OR media_type != 'video') AND reading_text IS NOT NULL AND TRIM(reading_text) != '' "); $stmt->execute([':today' => date('Y-m-d')]); $contents = $stmt->fetchAll(PDO::FETCH_ASSOC); if (empty($contents)) { logMessage("ℹ️ Aucun contenu à traiter aujourd'hui."); exit(0); } logMessage("📋 " . count($contents) . " contenu(s) trouvé(s) à traiter"); foreach ($contents as $row) { $text = trim($row['reading_text']); $user_group = $row['user_group']; $content_date = $row['content_date']; $content_id = $row['id']; if (empty($text)) continue; logMessage("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"); logMessage("🎬 Traitement : $user_group / $content_date (ID: $content_id)"); logMessage("📝 Texte (premiers 50 caractères): " . substr($text, 0, 50) . "..."); try { $video_id = generateVideo($text, $user_group); logMessage("⏳ Job HeyGen lancé : $video_id"); logMessage("🌐 Suivre sur : https://app.heygen.com/videos/$video_id"); $video_url = waitForVideoCompletion($video_id); if (empty($video_url)) { throw new Exception("URL de vidéo vide"); } updateMediaUrl($conn, $content_date, $user_group, $video_url); logMessage("✅ VIDÉO GÉNÉRÉE ET STOCKÉE !"); logMessage("🎬 URL publique : $video_url"); } catch (Exception $e) { logMessage("❌ ÉCHEC pour $user_group : " . $e->getMessage()); } } logMessage("╔════════════════════════════════════════════════════════════╗"); logMessage("║ GÉNÉRATION TERMINÉE ║"); logMessage("╚════════════════════════════════════════════════════════════╝"); logMessage("💡 Rechargez enregistrement.php pour voir la vidéo !"); } catch (Exception $e) { logMessage("🔥 ERREUR CRITIQUE : " . $e->getMessage()); exit(1); } ?>

Requests

  • Let Video Agent API to retrieve CC (subtitles) or allow for burning it into video
  • Let Video Agent API to give another prompt to edit the video
  • Allow to edit the plan with Video Agent API.

Personal Avatars, Voices, Through Video Agent API

Right now when I send a prompt to the video agent API it replies it can't access personal avatars, voices, templates, etc... Do you have any info about when that's going to be available? That would be a game-changer and I'd consider upgrading to the paid plan to be able to use that.

api use Similarity/Stability/Exaggeration possible?

When we use heygen manually we can configure Similarity/Stability/Exaggeration for a good voice and speed. Currently i am testing your api with the 100$ package and would like to use the configuration for my video/voice as same like i use it manually. I can not find in the documentation the confiration snippets. There are or you have another idea how i can adapt the same configruation of other videos to videos created by api?

Request Product Placement API access

Product Placement is currently a platform-only feature available through the HeyGen desktop app (Apps > Product Placement). It's not available via API at this time. Would be a great feature to add to my automation setup and hope this feature is something that can come to the API service in the near future. Thanks

Add our logo intro to all videos?

I saw the Api and I am not sure how to add custom api call which is not available in pabbly connect?
We have a 5 second intro video with our logo.
We just need to add this intro to all of our videos? 

PDF/PPTX (Document) Upload Support via HeyGen API

Hi HeyGen Support Team,

I wish using API I could send another prompt to edit video created via video agent

I wish using API I could send another prompt to edit video created via video agent

Dynamic Voice Speed Control in Template API

Dear HeyGen Support Team,

Eleven Labs V3 en API para voces clonadas