mstar.model.qwen3_5.video#

Qwen3.5 video input: frame sampling, timestamps and the prompt layout.

Mirrors transformers’ Qwen3VLProcessor / Qwen3VLVideoProcessor, which Qwen3.5 checkpoints name. A video renders as its chat-template triple with the pad replaced, per temporal group of temporal_patch_size frames, by <{t:.1f} seconds><|vision_start|><|video_pad|>*n<|vision_end|>; the outer sentinels stay. Only the pads are vision tokens: timestamps and every sentinel take text positions, and each group is placed in MRoPE like a one-frame image.

Kept free of engine imports so the parts that must match transformers can be tested without Triton.

Functions

expand_video_pads(text, pad, start, end, ...)

Replace the nth pad in text with the nth video's groups.

expand_video_parts(parts, groups)

parts with each video as text, group, text, ..., group, text.

ffmpeg_unavailable()

Why torchcodec can't decode video in this process, or None if it can.

group_owners(groups)

The video each group (numbered across all videos) belongs to.

group_timestamps(frames_indices, fps, ...)

Seconds per temporal group: the mean of its first and last frame's time.

sample_video(path, video_processor)

Decode the frames the checkpoint's video processor would sample.

Classes

ProcessedVideo(pixel_values, grid, timestamps)

One video as the vision walk takes it.

SampledVideo(frames, metadata)

What load_video hands process_prompt: the sampled frames only.

class mstar.model.qwen3_5.video.ProcessedVideo(pixel_values, grid, timestamps)[source]#

Bases: NamedTuple

One video as the vision walk takes it.

Parameters:
grid: Tensor#

Alias for field number 1

pixel_values: Tensor#

Alias for field number 0

timestamps: list[float]#

Alias for field number 2

class mstar.model.qwen3_5.video.SampledVideo(frames, metadata)[source]#

Bases: NamedTuple

What load_video hands process_prompt: the sampled frames only.

Parameters:
frames: Tensor#

Alias for field number 0

metadata: dict#

Alias for field number 1

mstar.model.qwen3_5.video.expand_video_pads(text, pad, start, end, timestamps)[source]#

Replace the nth pad in text with the nth video’s groups.

One pad per group: find_media_spans reads each group back as a span and the vision walk inserts its embeddings, as for an image.

Parameters:
Return type:

str

mstar.model.qwen3_5.video.expand_video_parts(parts, groups)[source]#

parts with each video as text, group, text, …, group, text.

The prefill plan’s view of expand_video_pads: the text around each group is the outer sentinel and the timestamps, so a video always has text on both sides, and prefill_plan merges it with the user’s text next to it. Video parts are renumbered per group, as find_media_spans numbers spans. A video with no entry in groups expands to nothing.

Parameters:
Return type:

list[PromptPart]

mstar.model.qwen3_5.video.ffmpeg_unavailable()[source]#

Why torchcodec can’t decode video in this process, or None if it can.

Return type:

str | None

mstar.model.qwen3_5.video.group_owners(groups)[source]#

The video each group (numbered across all videos) belongs to.

Parameters:

groups (Sequence[int])

Return type:

list[int]

mstar.model.qwen3_5.video.group_timestamps(frames_indices, fps, temporal_patch_size)[source]#

Seconds per temporal group: the mean of its first and last frame’s time.

Qwen3VLProcessor._calculate_timestamps, including its padding of an uneven tail with the last index (the patchifier repeats the last frame the same way) and its 24 fps fallback.

Parameters:
Return type:

list[float]

mstar.model.qwen3_5.video.sample_video(path, video_processor)[source]#

Decode the frames the checkpoint’s video processor would sample.

The same call transformers makes for a video path: torchcodec on the host (seek_mode="exact"), indices from the processor’s own sample_frames (fps per second, clamped to [min_frames, max_frames]), and only those frames decoded. Not on the GPU: NVDEC’s colour conversion need not match FFmpeg’s, and there is no fallback decoder for the same reason.

Parameters:

path (str)

Return type:

SampledVideo