@@ -91,6 +91,18 @@ def _video_t_grid(n, origin):
9191 return float (origin ) + torch .cat ([torch .zeros (1 , dtype = torch .float64 ), spans [:- 1 ].cumsum (0 )])
9292
9393
94+ def _ref_t_span (blk ):
95+ # time-axis span a reference block occupies ahead of the target streams
96+ kind = blk ["kind" ]
97+ if kind == "image" :
98+ return 1.0
99+ if kind == "audio" :
100+ return float (blk ["ref_audio_t" ])
101+ if kind in ("video" , "video_audio" ):
102+ return max (float (blk ["ref_audio_t" ]), sum (_video_t_spans (blk ["latent_t" ])))
103+ return 0.0
104+
105+
94106def _audio_grid (cursor , t , w_low , w_high ):
95107 # channel-major stereo rows: t advances per latent frame, w pinned to the grid extremes per stereo channel, h stays 0
96108 g = torch .zeros (t * 2 , 3 , dtype = torch .float64 )
@@ -288,7 +300,7 @@ def forward(self, x, t_emb, video_seg, audio_seg):
288300class PackedLayout :
289301 """Static packed-sequence structure for one shape/conditioning signature."""
290302
291- def __init__ (self , text_len , latent_t , latent_h , latent_w , audio_t , keyframes = None , refs = None , frame_count = None ):
303+ def __init__ (self , text_len , latent_t , latent_h , latent_w , audio_t , keyframes = None , refs = None ):
292304 frame , w_grid = _frame_grid (latent_h , latent_w )
293305 frame_rows = frame .shape [0 ]
294306
@@ -299,29 +311,37 @@ def __init__(self, text_len, latent_t, latent_h, latent_w, audio_t, keyframes=No
299311
300312 img_pos , img_update = [], []
301313 audio_pos , audio_update = [], []
302- cursor = text_len
303314 row = text_len
304315
316+ target_audio_w = (float (w_grid [0 ]), float (w_grid [- 1 ]))
317+ # refs pack between text and the targets, so the target timeline starts after their spans
318+ cursor = float (text_len )
319+ for blk in refs or ():
320+ cursor += _ref_t_span (blk )
321+
305322 if keyframes :
306- # fl2va: keyframe cond rows right after text, sharing the target spatial grid
323+ # fl2va: keyframe cond rows right after text, sharing the target spatial grid;
324+ # anchors count from the target timeline origin, FRAME_RESCALE per pixel frame, 1.0 per audio latent frame
307325 for kf in keyframes :
308- pixel_index = kf ["resolved_frame_index" ]
309- if pixel_index == 0 :
310- cond_t = float (text_len )
311- elif frame_count is not None and pixel_index == frame_count - 1 :
312- cond_t = float (text_len ) + sum (_video_t_spans (latent_t )) - FRAME_RESCALE
313- else :
314- raise ValueError ("only first/last keyframe anchors are supported" )
315- g = torch .empty (frame_rows , 3 , dtype = torch .float64 )
316- g [:, 0 ] = cond_t
317- g [:, 1 :] = frame
318- segments .append (("cond" , frame_rows ))
319- pos .append (g )
320- img_pos .append (torch .arange (row , row + frame_rows ))
321- img_update .append (torch .zeros (frame_rows , dtype = torch .bool ))
322- row += frame_rows
326+ cond_t = cursor + FRAME_RESCALE * kf ["resolved_frame_index" ]
327+ video_latent = kf .get ("latent" )
328+ if video_latent is not None :
329+ vt = video_latent .shape [2 ]
330+ n = vt * frame_rows
331+ segments .append (("cond" , n ))
332+ pos .append (_video_grid (vt , frame , cond_t ))
333+ img_pos .append (torch .arange (row , row + n ))
334+ img_update .append (torch .zeros (n , dtype = torch .bool ))
335+ row += n
336+ audio_latent = kf .get ("audio_latent" )
337+ if audio_latent is not None :
338+ rt = audio_latent .shape [- 1 ]
339+ segments .append (("cond_audio" , rt * 2 ))
340+ pos .append (_audio_grid (cond_t , rt , * target_audio_w ))
341+ audio_pos .append (torch .arange (row , row + rt * 2 ))
342+ audio_update .append (torch .zeros (rt * 2 , dtype = torch .bool ))
343+ row += rt * 2
323344
324- target_audio_w = (float (w_grid [0 ]), float (w_grid [- 1 ]))
325345 if refs :
326346 cursor = float (text_len )
327347 for blk in refs :
@@ -389,7 +409,7 @@ def __init__(self, text_len, latent_t, latent_h, latent_w, audio_t, keyframes=No
389409 self .audio_update = torch .cat (audio_update )
390410 self .signature = (text_len , latent_t , latent_h , latent_w , audio_t )
391411 # contiguous segment table (start, stop, kind)
392- # kinds: text / cond / ref_img / ref_audio / audio / video
412+ # kinds: text / cond / cond_audio / ref_img / ref_audio / audio / video
393413 # the packed sequence is uniform per segment in (modality tag, timestep class),
394414 # except the text span (tag runs resolved at forward time from the presentation tags)
395415 seg_abs = []
@@ -529,8 +549,7 @@ def _forward(self, x, timestep, context, transformer_options={}, minimax_payload
529549 if layout is None or layout .signature != (text_len , latent_t , lat_h , lat_w , audio_t ):
530550 layout = PackedLayout (text_len , latent_t , lat_h , lat_w , audio_t ,
531551 keyframes = payload .get ("keyframes" ),
532- refs = payload .get ("refs" ),
533- frame_count = payload .get ("frame_count" ))
552+ refs = payload .get ("refs" ))
534553
535554 # model_base passes model_sampling.timestep(sigma) = sigma * 1000
536555 shift_v = float (transformer_options .get ("minimax_h3_sigma_shift_video" , self .sigma_shift_video ))
@@ -543,14 +562,14 @@ def _forward(self, x, timestep, context, transformer_options={}, minimax_payload
543562 vis_aug = float (payload .get ("visual_cond_noise_aug" , VISUAL_COND_TIMESTEP ))
544563 aud_aug = float (payload .get ("audio_cond_noise_aug" , AUDIO_COND_TIMESTEP ))
545564 has_vis_cond = any (k in ("cond" , "ref_img" ) for _ , _ , k in layout .segments )
546- has_aud_cond = any (k == " ref_audio" for _ , _ , k in layout .segments )
565+ has_aud_cond = any (k in ( "cond_audio" , " ref_audio") for _ , _ , k in layout .segments )
547566 seg_t = {"text" : t_v , "video" : t_v , "audio" : t_a ,
548567 "cond" : max (t_v , vis_aug ), "ref_img" : max (t_v , vis_aug ),
549- "ref_audio" : max (t_a , aud_aug )}
568+ "cond_audio" : max ( t_a , aud_aug ), " ref_audio" : max (t_a , aud_aug )}
550569 unique_t = sorted ({t_v , t_a } | ({seg_t ["cond" ]} if has_vis_cond else set ())
551570 | ({seg_t ["ref_audio" ]} if has_aud_cond else set ()))
552571 t_row = {t : i for i , t in enumerate (unique_t )}
553- seg_tag = {"text" : 1 , "video" : 0 , "audio" : 2 , "cond" : 0 , "ref_img" : 0 , "ref_audio" : 2 }
572+ seg_tag = {"text" : 1 , "video" : 0 , "audio" : 2 , "cond" : 0 , "ref_img" : 0 , "cond_audio" : 2 , " ref_audio" : 2 }
554573
555574 text_tags = payload .get ("text_token_tags" )
556575 mod_segments = []
0 commit comments