gemini = $gemini; } /** * 스크린샷 배열을 Gemini Vision으로 분석 * * @param array $imagePaths 스크린샷 파일 경로 배열 * @return array 분석 결과 배열 */ public function analyzeScreenshots(array $imagePaths): array { $results = []; foreach ($imagePaths as $index => $imagePath) { $screenNumber = $index + 1; Log::info("ScreenAnalysis: 스크린샷 {$screenNumber}/" . count($imagePaths) . " 분석 시작", [ 'path' => $imagePath, ]); $result = $this->analyzeSingleScreen($imagePath, $screenNumber, count($imagePaths)); if ($result) { $results[] = $result; } else { Log::warning("ScreenAnalysis: 스크린샷 {$screenNumber} 분석 실패, 기본값 사용"); $results[] = [ 'screen_number' => $screenNumber, 'title' => "화면 {$screenNumber}", 'narration' => "이 화면에서는 주요 기능을 확인할 수 있습니다.", 'ui_elements' => [], 'duration' => 8, ]; } } return $results; } /** * 단일 스크린샷 분석 */ private function analyzeSingleScreen(string $imagePath, int $screenNumber, int $totalScreens): ?array { if (! file_exists($imagePath)) { Log::error("ScreenAnalysis: 파일 없음 - {$imagePath}"); return null; } $imageData = base64_encode(file_get_contents($imagePath)); $mimeType = mime_content_type($imagePath) ?: 'image/png'; $prompt = << $prompt], [ 'inlineData' => [ 'mimeType' => $mimeType, 'data' => $imageData, ], ], ]; $result = $this->gemini->callGeminiWithParts($parts, 0.3, 2048); if (! $result) { return null; } $parsed = $this->gemini->parseJson($result); if (! $parsed || ! isset($parsed['screen_number'])) { Log::warning('ScreenAnalysis: JSON 파싱 실패 또는 형식 불일치', [ 'result' => substr($result, 0, 300), ]); return null; } // screen_number 강제 보정 $parsed['screen_number'] = $screenNumber; return $parsed; } }