@ -249,6 +249,12 @@ export async function generateWithGeminiVideo(
config ,
config ,
} ;
} ;
// Validate image-to-video models have an image
if ( modelId . includes ( "image-to-video" ) && ( ! images || images . length === 0 ) ) {
console . error ( ` [API: ${ requestId } ] Image required for image-to-video model: ${ modelId } ` ) ;
return { success : false , error : "Image required for image-to-video model" } ;
}
// Add image for image-to-video models
// Add image for image-to-video models
if ( images && images . length > 0 && modelId . includes ( "image-to-video" ) ) {
if ( images && images . length > 0 && modelId . includes ( "image-to-video" ) ) {
const imageInput = images [ 0 ] ;
const imageInput = images [ 0 ] ;
@ -272,7 +278,10 @@ export async function generateWithGeminiVideo(
// Start video generation (async operation)
// Start video generation (async operation)
const startTime = Date . now ( ) ;
const startTime = Date . now ( ) ;
let operation = await ai . models . generateVideos ( requestArgs as unknown as Parameters < typeof ai.models.generateVideos > [ 0 ] ) ;
let operation ;
try {
operation = await ai . models . generateVideos ( requestArgs as unknown as Parameters < typeof ai.models.generateVideos > [ 0 ] ) ;
// Poll for completion (10s intervals, 5min timeout)
// Poll for completion (10s intervals, 5min timeout)
const POLL_INTERVAL = 10 _000 ;
const POLL_INTERVAL = 10 _000 ;
@ -289,6 +298,11 @@ export async function generateWithGeminiVideo(
await new Promise ( ( resolve ) = > setTimeout ( resolve , POLL_INTERVAL ) ) ;
await new Promise ( ( resolve ) = > setTimeout ( resolve , POLL_INTERVAL ) ) ;
operation = await ai . operations . getVideosOperation ( { operation } ) ;
operation = await ai . operations . getVideosOperation ( { operation } ) ;
}
}
} catch ( error ) {
const msg = error instanceof Error ? error.message : String ( error ) ;
console . error ( ` [API: ${ requestId } ] Veo generation failed: ${ msg } ` ) ;
return { success : false , error : ` Video generation failed: ${ msg } ` } ;
}
const duration = Date . now ( ) - startTime ;
const duration = Date . now ( ) - startTime ;
console . log ( ` [API: ${ requestId } ] Veo generation completed in ${ ( duration / 1000 ) . toFixed ( 1 ) } s ` ) ;
console . log ( ` [API: ${ requestId } ] Veo generation completed in ${ ( duration / 1000 ) . toFixed ( 1 ) } s ` ) ;
@ -310,7 +324,10 @@ export async function generateWithGeminiVideo(
const videoUrl = ` ${ videoUri } &key= ${ apiKey } ` ;
const videoUrl = ` ${ videoUri } &key= ${ apiKey } ` ;
console . log ( ` [API: ${ requestId } ] Fetching video from URI... ` ) ;
console . log ( ` [API: ${ requestId } ] Fetching video from URI... ` ) ;
const videoResponse = await fetch ( videoUrl ) ;
const controller = new AbortController ( ) ;
const fetchTimeout = setTimeout ( ( ) = > controller . abort ( ) , 60 _000 ) ;
try {
const videoResponse = await fetch ( videoUrl , { signal : controller.signal } ) ;
if ( ! videoResponse . ok ) {
if ( ! videoResponse . ok ) {
console . error ( ` [API: ${ requestId } ] Failed to fetch video: ${ videoResponse . status } ` ) ;
console . error ( ` [API: ${ requestId } ] Failed to fetch video: ${ videoResponse . status } ` ) ;
return { success : false , error : ` Failed to download generated video: ${ videoResponse . status } ` } ;
return { success : false , error : ` Failed to download generated video: ${ videoResponse . status } ` } ;
@ -329,4 +346,10 @@ export async function generateWithGeminiVideo(
success : true ,
success : true ,
outputs : [ { type : "video" , data : dataUrl } ] ,
outputs : [ { type : "video" , data : dataUrl } ] ,
} ;
} ;
} catch ( error ) {
console . error ( ` [API: ${ requestId } ] Failed to download video: ${ error } ` ) ;
return { success : false , error : "Failed to download generated video" } ;
} finally {
clearTimeout ( fetchTimeout ) ;
}
}
}