|
|
|
import sys
|
|
from PIL import Image
|
|
from decord import VideoReader, cpu
|
|
from typing import List
|
|
|
|
|
|
from src.logger import logging
|
|
from src.exception import CustomExceptionHandling
|
|
|
|
|
|
|
|
MAX_NUM_FRAMES = 64
|
|
|
|
|
|
def encode_video(video_path: str) -> List[Image.Image]:
|
|
"""
|
|
Encodes a video file into a list of frames.
|
|
|
|
Args:
|
|
video_path (str): The path to the video file.
|
|
|
|
Returns:
|
|
list: A list of frames, where each frame is represented as an Image object.
|
|
"""
|
|
|
|
def uniform_sample(l: List, n: int) -> List:
|
|
"""
|
|
Uniformly samples elements from a list.
|
|
|
|
Args:
|
|
- l (list): The input list.
|
|
- n (int): The number of elements to sample.
|
|
|
|
Returns:
|
|
list: A list of sampled elements.
|
|
"""
|
|
gap = len(l) / n
|
|
idxs = [int(i * gap + gap / 2) for i in range(n)]
|
|
return [l[i] for i in idxs]
|
|
|
|
try:
|
|
|
|
vr = VideoReader(video_path, ctx=cpu(0))
|
|
sample_fps = round(vr.get_avg_fps() / 1)
|
|
frame_idx = [i for i in range(0, len(vr), sample_fps)]
|
|
|
|
|
|
if len(frame_idx) > MAX_NUM_FRAMES:
|
|
frame_idx = uniform_sample(frame_idx, MAX_NUM_FRAMES)
|
|
|
|
|
|
frames = vr.get_batch(frame_idx).asnumpy()
|
|
frames = [Image.fromarray(v.astype("uint8")) for v in frames]
|
|
|
|
|
|
logging.info("Video encoded successfully.")
|
|
|
|
|
|
return frames
|
|
|
|
|
|
except Exception as e:
|
|
|
|
raise CustomExceptionHandling(e, sys) from e
|
|
|