( apiKey: string, model: string, prompt: string, duration: number, aspectRatio: string, resolution: string, visualReference: UserFile | undefined, requestId: string, logger: ReturnType<typeof createLogger> )
| 359 | }) |
| 360 | |
| 361 | async function generateWithRunway( |
| 362 | apiKey: string, |
| 363 | model: string, |
| 364 | prompt: string, |
| 365 | duration: number, |
| 366 | aspectRatio: string, |
| 367 | resolution: string, |
| 368 | visualReference: UserFile | undefined, |
| 369 | requestId: string, |
| 370 | logger: ReturnType<typeof createLogger> |
| 371 | ): Promise<{ buffer: Buffer; width: number; height: number; jobId: string; duration: number }> { |
| 372 | logger.info(`[${requestId}] Starting Runway Gen-4 generation`) |
| 373 | |
| 374 | const dimensions = getVideoDimensions(aspectRatio, resolution) |
| 375 | |
| 376 | // Convert aspect ratio to resolution format for 2024-11-06 API version |
| 377 | const ratioMap: { [key: string]: string } = { |
| 378 | '16:9': '1280:720', // Landscape (720p) |
| 379 | '9:16': '720:1280', // Portrait (720p) |
| 380 | '1:1': '960:960', // Square |
| 381 | } |
| 382 | const runwayRatio = ratioMap[aspectRatio] || '1280:720' |
| 383 | |
| 384 | const createPayload: any = { |
| 385 | promptText: prompt, |
| 386 | duration, |
| 387 | ratio: runwayRatio, // Use resolution-based ratio for 2024-11-06 API |
| 388 | model: 'gen4_turbo', // Only gen4_turbo supports image-to-video // Use underscore |
| 389 | } |
| 390 | |
| 391 | if (visualReference) { |
| 392 | if (visualReference.size > MAX_VIDEO_REFERENCE_IMAGE_BYTES) { |
| 393 | throw new PayloadSizeLimitError({ |
| 394 | label: 'video visual reference', |
| 395 | maxBytes: MAX_VIDEO_REFERENCE_IMAGE_BYTES, |
| 396 | observedBytes: visualReference.size, |
| 397 | }) |
| 398 | } |
| 399 | const refBuffer = await downloadFileFromStorage(visualReference, requestId, logger, { |
| 400 | maxBytes: MAX_VIDEO_REFERENCE_IMAGE_BYTES, |
| 401 | }) |
| 402 | assertKnownSizeWithinLimit( |
| 403 | refBuffer.length, |
| 404 | MAX_VIDEO_REFERENCE_IMAGE_BYTES, |
| 405 | 'video visual reference' |
| 406 | ) |
| 407 | const refBase64 = refBuffer.toString('base64') |
| 408 | createPayload.promptImage = `data:${visualReference.type};base64,${refBase64}` // Use promptImage |
| 409 | } |
| 410 | |
| 411 | const createResponse = await fetch('https://api.dev.runwayml.com/v1/image_to_video', { |
| 412 | method: 'POST', |
| 413 | headers: { |
| 414 | Authorization: `Bearer ${apiKey}`, |
| 415 | 'Content-Type': 'application/json', |
| 416 | 'X-Runway-Version': '2024-11-06', |
| 417 | }, |
| 418 | body: JSON.stringify(createPayload), |
no test coverage detected