fix
This commit is contained in:
@@ -42,10 +42,10 @@ public class GeminiVideoGenerationService {
|
|||||||
public GeminiVideoGenerationService() {
|
public GeminiVideoGenerationService() {
|
||||||
HttpClient httpClient = HttpClient.create()
|
HttpClient httpClient = HttpClient.create()
|
||||||
.resolver(DefaultAddressResolverGroup.INSTANCE)
|
.resolver(DefaultAddressResolverGroup.INSTANCE)
|
||||||
.responseTimeout(Duration.ofMillis(600000));
|
.responseTimeout(Duration.ofMillis(600000)); // 10 минут таймаут
|
||||||
|
|
||||||
ExchangeStrategies strategies = ExchangeStrategies.builder()
|
ExchangeStrategies strategies = ExchangeStrategies.builder()
|
||||||
.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(150 * 1024 * 1024))
|
.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(150 * 1024 * 1024)) // 150 MB под видео
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
this.webClient = WebClient.builder()
|
this.webClient = WebClient.builder()
|
||||||
@@ -54,19 +54,52 @@ public class GeminiVideoGenerationService {
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] generateVideo(String prompt) {
|
// НОВЫЙ МЕТОД: Полная диагностика перед запуском
|
||||||
|
private boolean runPreflightCheck() {
|
||||||
|
logger.info("=== СТАРТ ДИАГНОСТИКИ VEO ===");
|
||||||
|
|
||||||
|
// Шаг 1. Проверяем переменные окружения
|
||||||
if (projectId == null || projectId.trim().isEmpty()) {
|
if (projectId == null || projectId.trim().isEmpty()) {
|
||||||
logger.error("VEO: Project ID is missing!");
|
logger.error("[ПРОВАЛ] Project ID не задан в application.properties!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
logger.info("[ОК] Project ID: {}", projectId);
|
||||||
|
logger.info("[ОК] Location: {}", location);
|
||||||
|
logger.info("[ОК] Model: {}", model);
|
||||||
|
|
||||||
|
// Шаг 2. Проверяем файл ключа
|
||||||
|
ClassPathResource resource = new ClassPathResource(CREDENTIALS_FILE_PATH);
|
||||||
|
if (!resource.exists()) {
|
||||||
|
logger.error("[ПРОВАЛ] Файл ключа не найден по пути: src/main/resources/{}", CREDENTIALS_FILE_PATH);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
logger.info("[ОК] Файл ключа найден.");
|
||||||
|
|
||||||
|
// Шаг 3. Проверяем генерацию токена
|
||||||
|
String token = getAccessTokenFromResources();
|
||||||
|
if (token == null || token.isEmpty()) {
|
||||||
|
logger.error("[ПРОВАЛ] Не удалось сгенерировать Access Token. Проверьте содержимое ключа и права аккаунта!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
logger.info("[ОК] Access Token успешно сгенерирован (длина: {})", token.length());
|
||||||
|
|
||||||
|
// Шаг 4. Проверяем URL
|
||||||
|
String endpointUrl = String.format(VERTEX_API_TEMPLATE, location, projectId, location, model);
|
||||||
|
logger.info("[ОК] Endpoint URL сформирован: {}", endpointUrl);
|
||||||
|
|
||||||
|
logger.info("=== ДИАГНОСТИКА УСПЕШНО ЗАВЕРШЕНА ===");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] generateVideo(String prompt) {
|
||||||
|
// Запускаем проверку перед каждой генерацией
|
||||||
|
if (!runPreflightCheck()) {
|
||||||
|
logger.error("VEO: Генерация отменена из-за провала базовых проверок.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
String accessToken = getAccessTokenFromResources();
|
String accessToken = getAccessTokenFromResources();
|
||||||
if (accessToken == null) {
|
|
||||||
logger.error("VEO: Failed to load Google Credentials!");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
String endpointUrl = String.format(VERTEX_API_TEMPLATE, location, projectId, location, model);
|
String endpointUrl = String.format(VERTEX_API_TEMPLATE, location, projectId, location, model);
|
||||||
|
|
||||||
Map<String, Object> requestBody = new HashMap<>();
|
Map<String, Object> requestBody = new HashMap<>();
|
||||||
@@ -80,7 +113,8 @@ public class GeminiVideoGenerationService {
|
|||||||
parameters.put("aspectRatio", "9:16");
|
parameters.put("aspectRatio", "9:16");
|
||||||
requestBody.put("parameters", parameters);
|
requestBody.put("parameters", parameters);
|
||||||
|
|
||||||
logger.info("VEO: Requesting video generation. Prompt: {}", prompt);
|
// Логируем сам запрос, чтобы проверить его формат
|
||||||
|
logger.info("VEO: Отправка JSON запроса в Google: {}", requestBody);
|
||||||
|
|
||||||
Map<String, Object> response = webClient.post()
|
Map<String, Object> response = webClient.post()
|
||||||
.uri(URI.create(endpointUrl))
|
.uri(URI.create(endpointUrl))
|
||||||
@@ -96,17 +130,22 @@ public class GeminiVideoGenerationService {
|
|||||||
|
|
||||||
byte[] videoBytes = extractVideoFromResponse(response);
|
byte[] videoBytes = extractVideoFromResponse(response);
|
||||||
if (videoBytes != null) {
|
if (videoBytes != null) {
|
||||||
logger.info("VEO: Successfully generated video! Size: {} bytes", videoBytes.length);
|
logger.info("VEO: Успех! Видео сгенерировано. Размер: {} байт", videoBytes.length);
|
||||||
} else {
|
} else {
|
||||||
logger.error("VEO: Failed to extract video bytes from Google response.");
|
logger.error("VEO: Видео не найдено в ответе. Ответ от Google: {}", response);
|
||||||
}
|
}
|
||||||
return videoBytes;
|
return videoBytes;
|
||||||
|
|
||||||
} catch (WebClientResponseException e) {
|
} catch (WebClientResponseException e) {
|
||||||
logger.error("VEO API Error! Status: {}, Body: {}", e.getStatusCode(), e.getResponseBodyAsString());
|
// САМОЕ ВАЖНОЕ: Расшифровка ответа от Google
|
||||||
|
logger.error("==================================================");
|
||||||
|
logger.error("VEO API ERROR CRASH!");
|
||||||
|
logger.error("HTTP Status Code: {}", e.getStatusCode());
|
||||||
|
logger.error("Error Body from Google: {}", e.getResponseBodyAsString());
|
||||||
|
logger.error("==================================================");
|
||||||
return null;
|
return null;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("VEO API Fatal Error: {}", e.getMessage());
|
logger.error("VEO API Неизвестная ошибка: {}", e.getMessage(), e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,6 +161,7 @@ public class GeminiVideoGenerationService {
|
|||||||
return credentials.getAccessToken().getTokenValue();
|
return credentials.getAccessToken().getTokenValue();
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
logger.error("Ошибка при чтении файла ключа: {}", e.getMessage());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,12 +173,21 @@ public class GeminiVideoGenerationService {
|
|||||||
List<Map<String, Object>> predictions = (List<Map<String, Object>>) response.get("predictions");
|
List<Map<String, Object>> predictions = (List<Map<String, Object>>) response.get("predictions");
|
||||||
if (predictions != null && !predictions.isEmpty()) {
|
if (predictions != null && !predictions.isEmpty()) {
|
||||||
Map<String, Object> firstPrediction = predictions.get(0);
|
Map<String, Object> firstPrediction = predictions.get(0);
|
||||||
|
|
||||||
|
// Проверяем разные варианты ключей, в которых Google может вернуть видео
|
||||||
String base64Video = (String) firstPrediction.get("bytesBase64Encoded");
|
String base64Video = (String) firstPrediction.get("bytesBase64Encoded");
|
||||||
|
if (base64Video == null) {
|
||||||
|
base64Video = (String) firstPrediction.get("b64");
|
||||||
|
}
|
||||||
|
|
||||||
if (base64Video != null) {
|
if (base64Video != null) {
|
||||||
return java.util.Base64.getDecoder().decode(base64Video);
|
return java.util.Base64.getDecoder().decode(base64Video);
|
||||||
|
} else {
|
||||||
|
logger.warn("VEO: Ключ с Base64 видео не найден в 'predictions'. Доступные ключи: {}", firstPrediction.keySet());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
logger.error("VEO: Ошибка парсинга ответа: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user