110 lines
4.4 KiB
PHP
110 lines
4.4 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Core\Database;
|
|
use App\Core\Env;
|
|
|
|
class AiVideoGeneratorService
|
|
{
|
|
/**
|
|
* Step 1: Generate the Educational Script using Gemini
|
|
* Takes the complex Markdown and simplifies it into a lively script with examples.
|
|
*/
|
|
public static function generateLivelyScript(int $lessonId): ?array
|
|
{
|
|
$lesson = Database::selectOne(
|
|
"SELECT l.*, c.subject_id FROM lessons l JOIN courses c ON l.course_id = c.id WHERE l.id = ?",
|
|
[$lessonId]
|
|
);
|
|
|
|
if (!$lesson || empty($lesson['markdown_content'])) {
|
|
throw new \Exception("Lesson not found or has no markdown content.");
|
|
}
|
|
|
|
// Determine Language based on subject or content (assuming Subject ID 2 might be English)
|
|
$isEnglish = ($lesson['subject_id'] == 2) || (stripos($lesson['title'], 'english') !== false);
|
|
|
|
$prompt = self::buildPrompt($lesson['title'], $lesson['markdown_content'], $isEnglish);
|
|
|
|
// Call Gemini to get the script
|
|
return self::callGemini($prompt);
|
|
}
|
|
|
|
private static function buildPrompt(string $title, string $content, bool $isEnglish): string
|
|
{
|
|
if ($isEnglish) {
|
|
return "You are a world-class, enthusiastic English teacher.
|
|
Transform the following lesson content into a lively, highly engaging video script.
|
|
Use simple vocabulary, lots of practical examples, and a friendly tone.
|
|
Output as JSON: {\"narration_text\": \"...\", \"visual_cues\": \"...\"}
|
|
|
|
Lesson Title: {$title}
|
|
Content: {$content}";
|
|
} else {
|
|
return "أنت معلم خبير، مبدع ومحبوب جداً لدى الطلاب.
|
|
قم بتحويل محتوى الدرس التالي إلى (سكربت/سيناريو) مفعم بالحيوية والنشاط لتسجيله كفيديو تعليمي.
|
|
يجب أن يكون الشرح بسيطاً جداً، يستخدم أمثلة من الحياة الواقعية، وبلغة عربية فصحى مبسطة (أو لهجة قريبة للقلب).
|
|
|
|
أريد الإجابة بصيغة JSON فقط كالتالي:
|
|
{
|
|
\"narration_text\": \"النص الذي سيقرأه المعلم الذكي أو التعليق الصوتي\",
|
|
\"visual_cues\": \"وصف للمشاهد البصرية أو الرسوم التي يجب أن تظهر على الشاشة\"
|
|
}
|
|
|
|
عنوان الدرس: {$title}
|
|
المحتوى: {$content}";
|
|
}
|
|
}
|
|
|
|
private static function callGemini(string $prompt): ?array
|
|
{
|
|
$apiKey = Env::get('GEMINI_API_KEY');
|
|
if (!$apiKey) return null;
|
|
|
|
$model = Env::get('GEMINI_MODEL') ?: 'gemini-flash-lite-latest';
|
|
$url = "https://generativelanguage.googleapis.com/v1beta/models/{$model}:generateContent?key={$apiKey}";
|
|
|
|
$payload = [
|
|
'contents' => [['parts' => [['text' => $prompt]]]],
|
|
'generationConfig' => ['responseMimeType' => 'application/json', 'temperature' => 0.7]
|
|
];
|
|
|
|
$ch = curl_init($url);
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_POST => true,
|
|
CURLOPT_POSTFIELDS => json_encode($payload),
|
|
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_TIMEOUT => 60
|
|
]);
|
|
$res = curl_exec($ch);
|
|
curl_close($ch);
|
|
|
|
if (!$res) return null;
|
|
|
|
$json = json_decode($res, true);
|
|
$text = $json['candidates'][0]['content']['parts'][0]['text'] ?? '';
|
|
|
|
$text = preg_replace('/^```json\s*/i', '', $text);
|
|
$text = preg_replace('/```\s*$/i', '', $text);
|
|
|
|
return json_decode(trim($text), true);
|
|
}
|
|
|
|
/**
|
|
* Step 2: Call external AI Video/Avatar API (e.g., HeyGen, Synthesia)
|
|
* (Placeholder for future API integration)
|
|
*/
|
|
public static function triggerVideoGenerationApi(int $lessonId, string $scriptText): string
|
|
{
|
|
// TODO: Integrate with specific Video API (HeyGen, D-ID, Synthesia)
|
|
// 1. Send $scriptText to API
|
|
// 2. Receive Webhook or Poll for MP4 URL
|
|
// 3. Download MP4
|
|
// 4. Pass MP4 to our VideoService::transcodeToHls()
|
|
|
|
return "pending_api_integration";
|
|
}
|
|
}
|