This commit is contained in:
arys
2026-03-03 19:23:58 +05:00
parent edeeae4a4b
commit 39ef9e8c14
@@ -26,7 +26,8 @@ public class GeminiVideoGenerationService {
private static final Logger logger = LoggerFactory.getLogger(GeminiVideoGenerationService.class);
private static final String VERTEX_API_TEMPLATE = "https://%s-aiplatform.googleapis.com/v1/projects/%s/locations/%s/publishers/google/models/%s:predictLongRunning";
// ИСПОЛЬЗУЕМ СТРОГО v1beta1 (иначе Google не понимает операции для новых моделей)
private static final String VERTEX_API_BASE = "https://%s-aiplatform.googleapis.com/v1beta1";
private static final String CREDENTIALS_FILE_PATH = "keys/google-key.json";
private final WebClient webClient;
@@ -43,7 +44,7 @@ public class GeminiVideoGenerationService {
public GeminiVideoGenerationService() {
HttpClient httpClient = HttpClient.create()
.resolver(DefaultAddressResolverGroup.INSTANCE)
.responseTimeout(Duration.ofMillis(600000)); // 10 минут
.responseTimeout(Duration.ofMillis(600000));
ExchangeStrategies strategies = ExchangeStrategies.builder()
.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(150 * 1024 * 1024))
@@ -57,7 +58,9 @@ public class GeminiVideoGenerationService {
public byte[] generateVideo(String prompt) {
try {
String endpointUrl = String.format(VERTEX_API_TEMPLATE, location, projectId, location, model);
// ШАГ 1: Запускаем задачу
String endpointUrl = String.format("%s/projects/%s/locations/%s/publishers/google/models/%s:predictLongRunning",
String.format(VERTEX_API_BASE, location), projectId, location, model);
Map<String, Object> requestBody = new HashMap<>();
List<Map<String, Object>> instances = new ArrayList<>();
@@ -70,9 +73,8 @@ public class GeminiVideoGenerationService {
parameters.put("aspectRatio", "9:16");
requestBody.put("parameters", parameters);
logger.info("VEO: Запускаем генерацию (Long Running Operation). Промпт: {}", prompt);
logger.info("VEO: Запускаем генерацию. Промпт: {}", prompt);
// ШАГ 1: Запускаем задачу
Map<String, Object> initResponse = webClient.post()
.uri(URI.create(endpointUrl))
.header("Authorization", "Bearer " + getAccessTokenFromResources())
@@ -87,31 +89,25 @@ public class GeminiVideoGenerationService {
return null;
}
// ШАГ 2: Берем сырой путь операции и собираем ссылку через v1beta1
String rawOperationName = (String) initResponse.get("name");
logger.info("VEO: Задача успешно принята Google. Сырой ID: {}", rawOperationName);
logger.info("VEO: Задача успешно принята Google. ID: {}", rawOperationName);
// =================================================================
// ШАГ 2: ФИКС БАГА GOOGLE CLOUD
// Вырезаем чистый ID операции и собираем каноничный Vertex URL
// =================================================================
String operationId = rawOperationName.substring(rawOperationName.lastIndexOf("/") + 1);
String cleanOperationPath = String.format("projects/%s/locations/%s/operations/%s", projectId, location, operationId);
String operationUrl = String.format("https://%s-aiplatform.googleapis.com/v1/%s", location, cleanOperationPath);
logger.info("VEO: Сформирован ПРАВИЛЬНЫЙ URL для проверки: {}", operationUrl);
String operationUrl = String.format("%s/%s", String.format(VERTEX_API_BASE, location), rawOperationName);
logger.info("VEO: URL для проверки (v1beta1): {}", operationUrl);
// ШАГ 3: Цикл опроса (Polling)
int attempts = 0;
int maxAttempts = 60; // Максимум 15 минут (60 попыток по 15 сек)
int maxAttempts = 60; // Ждем до 15 минут
while (attempts < maxAttempts) {
Thread.sleep(15000); // Ждем 15 секунд перед проверкой
Thread.sleep(15000);
attempts++;
logger.info("VEO: Проверка статуса видео... (попытка {}/{})", attempts, maxAttempts);
Map<String, Object> statusResponse = webClient.get()
.uri(URI.create(operationUrl))
.header("Authorization", "Bearer " + getAccessTokenFromResources()) // Обязательно обновляем токен
.header("Authorization", "Bearer " + getAccessTokenFromResources())
.retrieve()
.bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {})
.block(Duration.ofSeconds(30));
@@ -125,6 +121,7 @@ public class GeminiVideoGenerationService {
Boolean isDone = (Boolean) statusResponse.get("done");
if (Boolean.TRUE.equals(isDone)) {
logger.info("VEO: 🔥 ВИДЕО ГОТОВО! Скачиваем результат...");
@SuppressWarnings("unchecked")
Map<String, Object> responseObj = (Map<String, Object>) statusResponse.get("response");
return extractVideoFromResponse(responseObj);
}