( apiKey: string, model: string, prompt: string, duration: number, aspectRatio: string, resolution: string, requestId: string, logger: ReturnType<typeof createLogger> )
| 487 | } |
| 488 | |
| 489 | async function generateWithVeo( |
| 490 | apiKey: string, |
| 491 | model: string, |
| 492 | prompt: string, |
| 493 | duration: number, |
| 494 | aspectRatio: string, |
| 495 | resolution: string, |
| 496 | requestId: string, |
| 497 | logger: ReturnType<typeof createLogger> |
| 498 | ): Promise<{ buffer: Buffer; width: number; height: number; jobId: string; duration: number }> { |
| 499 | logger.info(`[${requestId}] Starting Google Veo generation`) |
| 500 | |
| 501 | const dimensions = getVideoDimensions(aspectRatio, resolution) |
| 502 | |
| 503 | const modelNameMap: Record<string, string> = { |
| 504 | 'veo-3': 'veo-3.0-generate-001', |
| 505 | 'veo-3-fast': 'veo-3.0-fast-generate-001', // Fixed: was incorrectly mapped to 3.1 |
| 506 | 'veo-3.1': 'veo-3.1-generate-preview', |
| 507 | } |
| 508 | const modelName = modelNameMap[model] || 'veo-3.1-generate-preview' |
| 509 | |
| 510 | const createPayload = { |
| 511 | instances: [ |
| 512 | { |
| 513 | prompt, |
| 514 | }, |
| 515 | ], |
| 516 | parameters: { |
| 517 | aspectRatio: aspectRatio, // Keep as "16:9", don't convert |
| 518 | resolution: resolution, |
| 519 | durationSeconds: duration, // Keep as number |
| 520 | }, |
| 521 | } |
| 522 | |
| 523 | const createResponse = await fetch( |
| 524 | `https://generativelanguage.googleapis.com/v1beta/models/${modelName}:predictLongRunning`, |
| 525 | { |
| 526 | method: 'POST', |
| 527 | headers: { |
| 528 | 'Content-Type': 'application/json', |
| 529 | 'x-goog-api-key': apiKey, |
| 530 | }, |
| 531 | body: JSON.stringify(createPayload), |
| 532 | } |
| 533 | ) |
| 534 | |
| 535 | if (!createResponse.ok) { |
| 536 | const error = await readVideoErrorText(createResponse, 'Veo create error response') |
| 537 | throw new Error(`Veo API error: ${createResponse.status} - ${error}`) |
| 538 | } |
| 539 | |
| 540 | const createData = await readVideoJson<{ name: string }>(createResponse, 'Veo create response') |
| 541 | const operationName = createData.name |
| 542 | |
| 543 | logger.info(`[${requestId}] Veo operation created: ${operationName}`) |
| 544 | |
| 545 | const pollIntervalMs = 5000 |
| 546 | const maxAttempts = Math.ceil(getMaxExecutionTimeout() / pollIntervalMs) |
no test coverage detected