huggingFaceImage->generate($cleanPrompt, $this->resolveAspect($options), 1); $imageUrl = trim((string) ($images[0] ?? '')); $usesGeneratedFrame = true; } $video = $this->motionVideo->createFromImageUrl($imageUrl, $cleanPrompt, $options); return [ 'url' => $video['url'] ?? null, 'provider' => 'huggingface-motion', 'aspect' => $video['aspect'] ?? ($options['aspect_ratio'] ?? '16:9'), 'prompt' => $cleanPrompt, 'duration_seconds' => $video['duration_seconds'] ?? 8, 'source_image_url' => $imageUrl, 'applied_settings' => array_merge((array) ($video['applied_settings'] ?? []), [ 'video_provider' => 'huggingface', ]), 'notice' => $usesGeneratedFrame ? 'Start frame dibuat lewat Hugging Face, lalu dianimasikan dengan motion renderer lokal.' : 'Source frame dipakai langsung, lalu dirender ke video dengan pipeline Hugging Face/local motion.', 'async' => false, ]; } private function resolveAspect(array $options): string { return (($options['aspect_ratio'] ?? '16:9') === '9:16') ? 'portrait' : 'landscape'; } }