(
vae,
latents,
num_frames,
decode_chunk_size=8)
| 12 | logger = logging.getLogger(__name__) |
| 13 | |
| 14 | def decode_latents( |
| 15 | vae, |
| 16 | latents, |
| 17 | num_frames, |
| 18 | decode_chunk_size=8): |
| 19 | # [batch, frames, channels, height, width] -> [batch*frames, channels, height, width] |
| 20 | latents = latents.flatten(0, 1) |
| 21 | |
| 22 | latents = 1 / vae.config.scaling_factor * latents |
| 23 | |
| 24 | forward_vae_fn = vae._orig_mod.forward if is_compiled_module(vae) else vae.forward |
| 25 | accepts_num_frames = "num_frames" in set(inspect.signature(forward_vae_fn).parameters.keys()) |
| 26 | |
| 27 | # decode decode_chunk_size frames at a time to avoid OOM |
| 28 | frames = [] |
| 29 | for i in range(0, latents.shape[0], decode_chunk_size): |
| 30 | num_frames_in = latents[i: i + decode_chunk_size].shape[0] |
| 31 | decode_kwargs = {} |
| 32 | if accepts_num_frames: |
| 33 | # we only pass num_frames_in if it's expected |
| 34 | decode_kwargs["num_frames"] = num_frames_in |
| 35 | |
| 36 | frame = vae.decode(latents[i: i + decode_chunk_size], **decode_kwargs).sample |
| 37 | frames.append(frame.cpu()) |
| 38 | frames = torch.cat(frames, dim=0) |
| 39 | |
| 40 | # [batch*frames, channels, height, width] -> [batch, channels, frames, height, width] |
| 41 | frames = frames.reshape(-1, num_frames, *frames.shape[1:]).permute(0, 2, 1, 3, 4) |
| 42 | |
| 43 | # we always cast to float32 as this does not cause significant overhead and is compatible with bfloat16 |
| 44 | frames = frames.float() |
| 45 | return frames |
| 46 | |
| 47 | def tensor2vid(video, processor, output_type="np"): |
| 48 | batch_size, channels, num_frames, height, width = video.shape |
no test coverage detected