Update Saqel Platform: 2026-09-08 23:48:05

This commit is contained in:
Hamza-Ayed
2026-09-08 23:48:05 +03:00
parent be60f34148
commit ef639e804d
@@ -115,23 +115,67 @@ class AiVideoAnalyzerService
'contents' => [[
'parts' => [
['text' => $prompt],
['inline_data' => ['mime_type' => 'image/jpeg', 'data' => base64_encode((string)file_get_contents($frame))],],
['inlineData' => [
'mimeType' => 'image/jpeg',
'data' => base64_encode((string)file_get_contents($frame)),
]],
],
]],
'generationConfig' => ['responseMimeType' => 'application/json', 'temperature' => 0.1],
];
$geminiModel = getenv('GEMINI_MODEL') ?: 'gemini-1.5-flash';
$ch = curl_init('https://generativelanguage.googleapis.com/v1beta/models/' . rawurlencode($geminiModel) . ':generateContent?key=' . rawurlencode($key));
curl_setopt_array($ch, [CURLOPT_POST=>true,CURLOPT_POSTFIELDS=>json_encode($payload),CURLOPT_HTTPHEADER=>['Content-Type: application/json'],CURLOPT_RETURNTRANSFER=>true,CURLOPT_TIMEOUT=>30]);
$body = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch);
$text = json_decode((string)$body, true)['candidates'][0]['content']['parts'][0]['text'] ?? '';
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($ch);
$curlErr = curl_error($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($body === false || !empty($curlErr)) {
error_log("AiVideoAnalyzerService cURL error: " . $curlErr);
throw new \RuntimeException("تعذر الاتصال بخدمة التحليل: {$curlErr}");
}
if ($code !== 200) {
error_log("AiVideoAnalyzerService Gemini HTTP {$code}: " . $body);
$errJson = json_decode((string)$body, true);
$errMsg = $errJson['error']['message'] ?? "رمز الاستجابة {$code}";
throw new \RuntimeException("استجابة Gemini: {$errMsg}");
}
$rawText = json_decode((string)$body, true)['candidates'][0]['content']['parts'][0]['text'] ?? '';
$text = trim($rawText);
if (str_starts_with($text, '```json')) {
$text = trim(substr($text, 7));
if (str_ends_with($text, '```')) {
$text = trim(substr($text, 0, -3));
}
} elseif (str_starts_with($text, '```')) {
$text = trim(substr($text, 3));
if (str_ends_with($text, '```')) {
$text = trim(substr($text, 0, -3));
}
}
$report = json_decode($text, true);
if ($code !== 200 || !is_array($report) || !in_array($report['decision'] ?? '', ['approved','needs_manual_review','rejected'], true)) throw new \RuntimeException('استجابة Gemini غير صالحة');
if (!is_array($report) || !in_array($report['decision'] ?? '', ['approved','needs_manual_review','rejected'], true)) {
error_log("AiVideoAnalyzerService invalid report format: " . $text);
throw new \RuntimeException('تنسيق تقرير الجودة غير صالح');
}
$report['duration_seconds'] = $duration;
if (($report['visual_clarity_score'] ?? 0) < 85 || ($report['pedagogical_readiness_score'] ?? 0) < 85) $report['decision'] = 'needs_manual_review';
if (($report['visual_clarity_score'] ?? 0) < 85 || ($report['pedagogical_readiness_score'] ?? 0) < 85) {
$report['decision'] = 'needs_manual_review';
}
return $report;
} catch (\Throwable $e) {
return ['decision' => 'needs_manual_review', 'reason' => 'تعذر إكمال تحليل Gemini؛ لم يتم رفع الفيديو'];
error_log("AiVideoAnalyzerService audit exception: " . $e->getMessage());
return ['decision' => 'needs_manual_review', 'reason' => 'تعذر إكمال تحليل Gemini: ' . $e->getMessage(), 'duration_seconds' => $duration];
} finally { @unlink($frame); }
}
/**
@@ -285,7 +329,8 @@ class AiVideoAnalyzerService
\"approval_status\": \"approved_official\"
}";
$url = "https://generativelanguage.googleapis.com/v1beta/models/gemini-flash-lite-latest:generateContent?key=" . $geminiKey;
$geminiModel = getenv('GEMINI_MODEL') ?: 'gemini-1.5-flash';
$url = "https://generativelanguage.googleapis.com/v1beta/models/" . rawurlencode($geminiModel) . ":generateContent?key=" . $geminiKey;
$payload = [
'contents' => [['parts' => [['text' => $prompt]]]],
'generationConfig' => ['responseMimeType' => 'application/json', 'temperature' => 0.2]
@@ -400,7 +445,8 @@ class AiVideoAnalyzerService
}
قاعدة صارمة: السؤال عند أي دقيقة يسأل فقط عما تم شرحه قبل ذلك التوقيت، وممنوع نهائياً الاستعانة بأي معلومة خارج المنهاج.";
$url = "https://generativelanguage.googleapis.com/v1beta/models/gemini-flash-lite-latest:generateContent?key=" . $geminiKey;
$geminiModel = getenv('GEMINI_MODEL') ?: 'gemini-1.5-flash';
$url = "https://generativelanguage.googleapis.com/v1beta/models/" . rawurlencode($geminiModel) . ":generateContent?key=" . $geminiKey;
$payload = [
'contents' => [
['parts' => [['text' => $prompt]]]