""" VoiceVerse AI — Utility helpers. Provides temp file management and error formatting used across the pipeline. """ import os import tempfile import logging logging.basicConfig( level=logging.INFO, format="%(asctime)s [%(levelname)s] %(name)s: %(message)s", ) logger = logging.getLogger("voiceverse") def get_temp_filepath(suffix: str = ".wav") -> str: """Return a path to a new temporary file that won't be auto-deleted.""" fd, path = tempfile.mkstemp(suffix=suffix) os.close(fd) return path def format_error(stage: str, error: Exception) -> str: """ Return a user-friendly error string. Hides raw tracebacks; logs the full error for debugging. """ logger.error("Error in %s: %s", stage, error, exc_info=True) friendly_messages = { "upload": "Could not read the uploaded file. Please try a different PDF or TXT file.", "rag": "Failed to process the document text. The file may be empty or corrupted.", "script": "Could not generate the audio script. Please check your HF_TOKEN and try again.", "tts": "Audio generation failed. The system will retry with a fallback voice.", } return friendly_messages.get(stage, f"An unexpected error occurred: {stage}") def validate_file(file_path: str) -> tuple[bool, str]: """ Validate an uploaded file. Returns (is_valid, message). """ if file_path is None: return False, "Please upload a PDF or TXT file first." if not os.path.exists(file_path): return False, "The uploaded file could not be found. Please try again." ext = os.path.splitext(file_path)[1].lower() if ext not in (".pdf", ".txt"): return False, f"Unsupported file format '{ext}'. Please upload a PDF or TXT file." size = os.path.getsize(file_path) if size == 0: return False, "The uploaded file is empty. Please upload a file with content." if size > 20 * 1024 * 1024: # 20 MB limit return False, "File is too large (>20 MB). Please upload a smaller document." return True, "File is valid."