VideoChat3-4B-Stage2 / videochat3_utils.py
lmwang's picture
Upload stage2 ckpt
397ee8a verified
Raw
History Blame Contribute Delete
2.9 kB
from dataclasses import dataclass, fields
from typing import Optional, Mapping
@dataclass
class VideoChat3VideoMetadata(Mapping):
total_num_frames: int
fps: Optional[float] = None
width: Optional[int] = None
height: Optional[int] = None
duration: Optional[float] = None
video_backend: Optional[str] = None
frames_indices: Optional[list[int]] = None
video_start_time: float = 0.0 # The start time of the video, in seconds
clip_start_time: Optional[float] = None # The start time of the video clip to be extracted, in seconds
clip_end_time: Optional[float] = None # The end time of the video clip to be extracted, in seconds
def __post_init__(self):
if self.fps is not None and self.duration is not None:
expected_frames = self.fps * self.duration
if abs(expected_frames - self.total_num_frames) > 1e-6:
raise ValueError(f"fps * duration must be equal to total_num_frames, but got {expected_frames} != {self.total_num_frames}")
if self.video_start_time < 0 or (self.duration is not None and self.video_start_time >= self.duration):
raise ValueError(f"video_start_time must be greater than or equal to 0 and less than duration, but got {self.video_start_time}")
if (self.clip_start_time is None) != (self.clip_end_time is None):
raise ValueError("clip_start_time and clip_end_time must both be None or both be not None.")
if self.clip_start_time is not None and self.clip_end_time is not None and self.clip_end_time <= self.clip_start_time:
raise ValueError(f"clip_end_time must be greater than clip_start_time, but got {self.clip_end_time} <= {self.clip_start_time}")
if self.clip_start_time is not None and self.clip_start_time < 0:
raise ValueError(f"clip_start_time must be greater than 0, but got {self.clip_start_time}")
if self.clip_end_time is not None and (self.clip_end_time < 0 or self.clip_end_time > self.duration):
raise ValueError(f"clip_end_time must be greater than 0 and less than duration, but got {self.clip_end_time}")
def __iter__(self):
return (f.name for f in fields(self))
def __len__(self):
return len(fields(self))
def __getitem__(self, item):
return getattr(self, item)
def __setitem__(self, key, value):
return setattr(self, key, value)
@property
def timestamps(self) -> float:
"Timestamps of the sampled frames in seconds."
if self.fps is None:
raise ValueError("Cannot infer video `timestamps` when `fps` is None.")
return [self.video_start_time + frame_idx / self.fps for frame_idx in self.frames_indices]
def update(self, dictionary):
for key, value in dictionary.items():
if hasattr(self, key):
setattr(self, key, value)