Multiverse-AI-Studio / backend /utils /file_manager.py
3v324v23's picture
feat: initial release of Multiverse AI Studio
4aed5f4
Raw
History Blame Contribute Delete
3.53 kB
# file_manager.py placeholder
"""
WHAT: A utility module for handling local file system operations (I/O) for generated media.
WHY: AI models generate raw objects in memory (PIL Images, byte strings, numpy arrays).
To send these to a web frontend, we must serialize them into standard file formats
(.png, .wav, .mp4) on disk, and provide static URLs pointing to those files.
HOW: It reads the OUTPUT_DIR from config, ensures directories exist for each specific job_id,
and writes binary or image data to disk. It returns a relative URL path (e.g., /assets/...)
that FastAPI will be configured to serve statically.
"""
import os
from PIL import Image
# Import the configured base output directory from our config file
# Note: Ensure that Python's execution path allows this import, typically running from the backend root.
from ..config import OUTPUT_DIR
def ensure_output_dir(job_id: str) -> str:
"""
WHAT: Creates a dedicated folder for a specific job on the local file system.
WHY: We want to organize files by job_id so assets from different requests don't overwrite each other.
HOW: Uses os.makedirs with exist_ok=True to safely create the directory path without throwing errors
if it already exists. Returns the absolute or relative path to the newly created folder.
"""
job_dir = os.path.join(OUTPUT_DIR, job_id)
os.makedirs(job_dir, exist_ok=True)
return job_dir
def save_image(pil_image: Image.Image, job_id: str, asset_name: str) -> str:
"""
WHAT: Saves a PIL (Python Imaging Library) Image object to disk as a PNG.
WHY: The Image Generator and Depth Estimator outputs in-memory PIL objects. They must be saved.
We use `asset_name` because we need to save both the base image ("image") and depth map ("depth").
HOW: Calls ensure_output_dir(), saves the file, and returns the relative static URL.
"""
job_dir = ensure_output_dir(job_id)
filename = f"{asset_name}.png"
filepath = os.path.join(job_dir, filename)
# Save the PIL image object directly to the file system
pil_image.save(filepath, format="PNG")
# Return the relative URL path that FastAPI will use to serve this file.
# Assuming main.py will mount OUTPUT_DIR at the route "/assets"
return f"/assets/{job_id}/{filename}"
def save_audio(audio_bytes: bytes, job_id: str) -> str:
"""
WHAT: Saves raw audio byte data to disk as a WAV file.
WHY: The Audio Generator outputs raw audio data that must be serialized for frontend playback
and eventually muxed into the final video.
HOW: Writes the bytes to disk in binary mode ("wb").
"""
job_dir = ensure_output_dir(job_id)
filename = "audio.wav"
filepath = os.path.join(job_dir, filename)
# Write raw bytes to file
with open(filepath, "wb") as f:
f.write(audio_bytes)
return f"/assets/{job_id}/{filename}"
def save_video(video_bytes: bytes, job_id: str) -> str:
"""
WHAT: Saves raw video byte data to disk as an MP4 file.
WHY: The Video Generator outputs the final culmination of our pipeline. This MP4 is the
end product delivered to the user.
HOW: Writes the bytes to disk in binary mode ("wb").
"""
job_dir = ensure_output_dir(job_id)
filename = "video.mp4"
filepath = os.path.join(job_dir, filename)
# Write raw bytes to file
with open(filepath, "wb") as f:
f.write(video_bytes)
return f"/assets/{job_id}/{filename}"