1313# limitations under the License.
1414
1515import json
16- import time
16+ import asyncio
1717import traceback
1818from typing import Dict , cast
1919
4141)
4242
4343
44- async def generate (prompt , first_frame_image = None , last_frame_image = None ):
44+ async def generate (
45+ prompt , first_frame_image = None , last_frame_image = None , generate_audio = None
46+ ):
4547 try :
48+ if generate_audio is False :
49+ generate_audio = None
50+ model_name = getenv ("MODEL_VIDEO_NAME" , DEFAULT_VIDEO_MODEL_NAME )
51+
52+ if model_name .startswith ("doubao-seedance-1-0" ) and generate_audio :
53+ logger .warning (
54+ "The `doubao-seedance-1-0` series models do not support enabling the audio field. "
55+ "Please upgrade to the doubao-seedance-1-5 series of you want to generate video with audio."
56+ )
57+ generate_audio = None
4658 if first_frame_image is None :
4759 response = client .content_generation .tasks .create (
4860 model = getenv ("MODEL_VIDEO_NAME" , DEFAULT_VIDEO_MODEL_NAME ),
4961 content = [
5062 {"type" : "text" , "text" : prompt },
5163 ],
64+ generate_audio = generate_audio ,
5265 extra_headers = {
5366 "veadk-source" : "veadk" ,
5467 "veadk-version" : VERSION ,
@@ -112,7 +125,10 @@ async def generate(prompt, first_frame_image=None, last_frame_image=None):
112125
113126
114127async def video_generate (
115- params : list , tool_context : ToolContext , batch_size : int = 10
128+ params : list ,
129+ tool_context : ToolContext ,
130+ batch_size : int = 10 ,
131+ max_wait_seconds : int = 1200 ,
116132) -> Dict :
117133 """
118134 Generate videos in **batch** from text prompts, optionally guided by a first/last frame,
@@ -126,6 +142,10 @@ async def video_generate(
126142 A list of video generation requests. Each item supports the fields below.
127143 batch_size (int):
128144 The number of videos to generate in a batch. Defaults to 10.
145+ max_wait_seconds (int):
146+ Maximum time in seconds to wait for all video tasks in each batch.
147+ Default is 20 minutes (1200 seconds). When the timeout is reached,
148+ unfinished tasks will be marked as timeout errors.
129149
130150 Required per item:
131151 - video_name (str):
@@ -148,6 +168,12 @@ async def video_generate(
148168 URL or Base64 string (data URL) for the **last frame** (role = `last_frame`).
149169 Use when you want the clip to end on a specific image.
150170
171+ - generate_audio (bool | None):
172+ Boolean value, used to determine whether the generated video should have sound.
173+ If this field is not configured (None) or its value is `False`, no sound will be generated.
174+ If it is configured as `True`, sound can be generated.
175+ If you want to describe the sound content in detail, you can do so in the `prompt` field.
176+
151177 Notes on first/last frame:
152178 * When both frames are provided, **match width/height** to avoid cropping; if they differ,
153179 the tail frame may be auto-cropped to fit.
@@ -222,6 +248,7 @@ async def video_generate(
222248 """
223249 success_list = []
224250 error_list = []
251+ timeout_tasks = []
225252 logger .debug (f"Using model: { getenv ('MODEL_VIDEO_NAME' , DEFAULT_VIDEO_MODEL_NAME )} " )
226253 logger .debug (f"video_generate params: { params } " )
227254
@@ -243,22 +270,32 @@ async def video_generate(
243270 prompt = item ["prompt" ]
244271 first_frame = item .get ("first_frame" , None )
245272 last_frame = item .get ("last_frame" , None )
273+ generate_audio = item .get ("generate_audio" , None )
246274 try :
247275 if not first_frame :
248276 logger .debug (
249277 f"video_generate task_{ idx } text generation: prompt={ prompt } "
250278 )
251- response = await generate (prompt )
279+ response = await generate (prompt , generate_audio = generate_audio )
252280 elif not last_frame :
253281 logger .debug (
254282 f"video_generate task_{ idx } first frame generation: prompt={ prompt } , first_frame={ first_frame } "
255283 )
256- response = await generate (prompt , first_frame )
284+ response = await generate (
285+ prompt ,
286+ first_frame_image = first_frame ,
287+ generate_audio = generate_audio ,
288+ )
257289 else :
258290 logger .debug (
259291 f"video_generate task_{ idx } first and last frame generation: prompt={ prompt } , first_frame={ first_frame } , last_frame={ last_frame } "
260292 )
261- response = await generate (prompt , first_frame , last_frame )
293+ response = await generate (
294+ prompt ,
295+ first_frame_image = first_frame ,
296+ last_frame_image = last_frame ,
297+ generate_audio = generate_audio ,
298+ )
262299 logger .debug (
263300 f"batch_{ start_idx // batch_size } video_generate task_{ idx } response: { response } "
264301 )
@@ -270,6 +307,10 @@ async def video_generate(
270307
271308 logger .debug ("begin query video_generate task status..." )
272309
310+ sleep_interval = 10
311+ max_sleep_times = max_wait_seconds // sleep_interval
312+ sleep_times = 0
313+
273314 while True :
274315 task_list = list (task_dict .keys ())
275316 if len (task_list ) == 0 :
@@ -303,7 +344,23 @@ async def video_generate(
303344 logger .debug (
304345 f"{ task_dict [task_id ]} video_generate current status: { status } , Retrying after 10 seconds..."
305346 )
306- time .sleep (10 )
347+ if sleep_times >= max_sleep_times :
348+ logger .error (
349+ f"video_generate polling timed out after { max_wait_seconds } seconds; remaining tasks: { task_dict } "
350+ )
351+ for task_id , video_name in task_dict .items ():
352+ timeout_tasks .append (
353+ {
354+ "task_id" : task_id ,
355+ "video_name" : video_name ,
356+ }
357+ )
358+ error_list .append (video_name )
359+ task_dict .clear ()
360+ break
361+
362+ await asyncio .sleep (sleep_interval )
363+ sleep_times += 1
307364
308365 add_span_attributes (
309366 span ,
@@ -324,6 +381,7 @@ async def video_generate(
324381 "status" : "error" ,
325382 "success_list" : success_list ,
326383 "error_list" : error_list ,
384+ "timeout_tasks" : timeout_tasks ,
327385 }
328386 else :
329387 logger .debug (
@@ -333,6 +391,7 @@ async def video_generate(
333391 "status" : "success" ,
334392 "success_list" : success_list ,
335393 "error_list" : error_list ,
394+ "timeout_tasks" : timeout_tasks ,
336395 }
337396
338397
0 commit comments