File size: 2,295 Bytes
24dade7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# utils/helpers.py
import base64
from io import BytesIO
from PIL import Image
import imageio
import numpy as np
from typing import List

def encode_image_base64(image: Image.Image, format="PNG") -> str:
    """Encodes a PIL Image to a base64 string."""
    buffered = BytesIO()
    image.save(buffered, format=format)
    img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
    return img_str

def decode_base64_image(image_base64: str) -> Image.Image:
    """Decodes a base64 string to a PIL Image."""
    img_bytes = base64.b64decode(image_base64)
    img = Image.open(BytesIO(img_bytes))
    return img.convert("RGB") # Ensure RGB format

def encode_video_base64(video_frames: List[np.ndarray], fps: int, format="MP4") -> str:
    """Encodes a list of numpy array frames (H, W, C) to a base64 video string."""
    if not video_frames:
        raise ValueError("Cannot encode empty video frames list.")

    buffered = BytesIO()
    # Ensure frames are uint8
    frames_uint8 = [(frame * 255).astype(np.uint8) if frame.dtype != np.uint8 else frame for frame in video_frames]

    if format.upper() == "MP4":
        # imageio requires ffmpeg to be installed in the Space environment
        # Add 'imageio[ffmpeg]' to requirements.txt if needed, or ensure ffmpeg is available
        try:
            imageio.mimwrite(buffered, frames_uint8, format='mp4', fps=fps, output_params=['-vf', 'pad=ceil(iw/2)*2:ceil(ih/2)*2']) # Ensure dimensions are even for some codecs
            # quality=8 is a reasonable default, adjust if needed. Macro_block size needed for h264
        except Exception as e:
             print(f"WARNING: MP4 encoding failed ({e}). Check ffmpeg availability. Falling back to GIF.")
             # Fallback to GIF if MP4 fails (e.g., ffmpeg not found)
             imageio.mimwrite(buffered, frames_uint8, format='gif', duration=1000/fps) # duration is in ms
             format = "GIF"

    elif format.upper() == "GIF":
        imageio.mimwrite(buffered, frames_uint8, format='gif', duration=1000/fps) # duration is in ms
    else:
        raise ValueError(f"Unsupported video format: {format}")

    video_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
    return video_str, format.upper() # Return actual format used (might differ on fallback)