video
fastvideo.eval.io.video.load_video
load_video(source: str | torch.Tensor | list, **kwargs) -> torch.Tensor
Load a video as a (T, C, H, W) float32 tensor in [0, 1].
Supported source types:
- str / Path – path to
.mp4/.avi/.giffile, or a directory of frame images (sorted alphabetically). - torch.Tensor – returned as-is after shape validation.
- list[PIL.Image] – stacked into a tensor.
Source
def load_video(source: str | torch.Tensor | list, **kwargs) -> torch.Tensor:
"""Load a video as a ``(T, C, H, W)`` float32 tensor in ``[0, 1]``.
Supported *source* types:
* **str / Path** – path to ``.mp4`` / ``.avi`` / ``.gif`` file, or a
directory of frame images (sorted alphabetically).
* **torch.Tensor** – returned as-is after shape validation.
* **list[PIL.Image]** – stacked into a tensor.
"""
if isinstance(source, torch.Tensor):
if source.ndim != 4:
raise ValueError(f"Expected video tensor with 4 dims (T,C,H,W), got {source.ndim}")
return source.float()
if isinstance(source, list):
frames = [_pil_to_tensor(img) for img in source]
return torch.stack(frames)
path = Path(source)
if path.is_dir():
return _load_frame_dir(path)
return _load_video_file(str(path))</code></pre></details>
fastvideo.eval.io.video.extract_frames
extract_frames(video: torch.Tensor, n_frames: int | None = None) -> torch.Tensor
Uniformly sample n_frames from a (T, C, H, W) video tensor.
Source
def extract_frames(video: torch.Tensor, n_frames: int | None = None) -> torch.Tensor:
"""Uniformly sample *n_frames* from a ``(T, C, H, W)`` video tensor."""
if n_frames is None or n_frames >= video.shape[0]:
return video
indices = torch.linspace(0, video.shape[0] - 1, n_frames).long()
return video[indices]
fastvideo.eval.io.video.probe_video_fps
probe_video_fps(source: str | Path) -> float | None
Read a path-backed video's native frame rate without decoding frames.
Source
def probe_video_fps(source: str | Path) -> float | None:
"""Read a path-backed video's native frame rate without decoding frames."""
try:
import av
with av.open(str(source)) as container:
if not container.streams.video:
return None
stream = container.streams.video[0]
rate = stream.average_rate or stream.guessed_rate
if rate is not None and float(rate) > 0:
return float(rate)
except (ImportError, OSError, ValueError):
pass
try:
from decord import VideoReader, cpu
rate = float(VideoReader(str(source), ctx=cpu(0)).get_avg_fps())
return rate if rate > 0 else None
except (ImportError, OSError, RuntimeError, ValueError):
return None</code></pre></details>