From 1d92f2f4fa2ffcdde42dc0a17971c3b0c287358c Mon Sep 17 00:00:00 2001 From: dsyoon Date: Fri, 30 Jan 2026 20:51:18 +0900 Subject: [PATCH] Store mp3 size in database Persist file size at creation and backfill missing sizes on list responses so the UI can display sizes reliably. --- server/db.py | 25 +++++++++++++++++++++++-- server/main.py | 44 +++++++++++++++++++++++++++++++------------- 2 files changed, 54 insertions(+), 15 deletions(-) diff --git a/server/db.py b/server/db.py index bbbb78a..18bdcc0 100644 --- a/server/db.py +++ b/server/db.py @@ -29,10 +29,17 @@ def init_db(): id SERIAL PRIMARY KEY, text TEXT NOT NULL, filename TEXT, + size_bytes BIGINT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); """ ) + cur.execute( + """ + ALTER TABLE tts_items + ADD COLUMN IF NOT EXISTS size_bytes BIGINT; + """ + ) cur.execute( """ CREATE INDEX IF NOT EXISTS tts_items_created_at_idx @@ -72,12 +79,26 @@ def update_filename(tts_id: int, filename: str) -> None: conn.commit() +def update_size_bytes(tts_id: int, size_bytes: int) -> None: + with get_conn() as conn: + with conn.cursor() as cur: + cur.execute( + """ + UPDATE tts_items + SET size_bytes = %s + WHERE id = %s; + """, + (size_bytes, tts_id), + ) + conn.commit() + + def list_items() -> List[Dict[str, Any]]: with get_conn() as conn: with conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) as cur: cur.execute( """ - SELECT id, created_at, filename + SELECT id, created_at, filename, size_bytes FROM tts_items ORDER BY created_at DESC; """ @@ -91,7 +112,7 @@ def get_item(tts_id: int) -> Optional[Dict[str, Any]]: with conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) as cur: cur.execute( """ - SELECT id, text, filename, created_at + SELECT id, text, filename, size_bytes, created_at FROM tts_items WHERE id = %s; """, diff --git a/server/main.py b/server/main.py index 8d723a1..55c91a0 100644 --- a/server/main.py +++ b/server/main.py @@ -15,6 +15,7 @@ from .db import ( init_db, create_item, update_filename, + update_size_bytes, list_items, get_item, delete_items, @@ -72,13 +73,19 @@ def format_size(bytes_size: int) -> str: return f"{bytes_size / (1024 * 1024):.1f}MB" -def get_file_size_display(filename: str | None) -> str | None: +def get_file_size_display(size_bytes: int | None) -> str | None: + if size_bytes is None: + return None + return format_size(size_bytes) + + +def get_file_size_bytes(filename: str | None) -> int | None: if not filename: return None file_path = RESOURCES_DIR / filename if not file_path.exists(): return None - return format_size(file_path.stat().st_size) + return file_path.stat().st_size @app.on_event("startup") @@ -95,16 +102,24 @@ def index(request: Request): @app.get("/api/tts") def api_list_tts(): rows = list_items() - return [ - { - "id": row["id"], - "created_at": row["created_at"].isoformat(), - "display_time": format_display_time(row["created_at"]), - "filename": row["filename"], - "size_display": get_file_size_display(row["filename"]), - } - for row in rows - ] + payload = [] + for row in rows: + size_bytes = row.get("size_bytes") + if size_bytes is None and row.get("filename"): + computed = get_file_size_bytes(row["filename"]) + if computed is not None: + update_size_bytes(row["id"], computed) + size_bytes = computed + payload.append( + { + "id": row["id"], + "created_at": row["created_at"].isoformat(), + "display_time": format_display_time(row["created_at"]), + "filename": row["filename"], + "size_display": get_file_size_display(size_bytes), + } + ) + return payload @app.post("/api/tts") @@ -128,14 +143,17 @@ def api_create_tts(payload: TtsCreateRequest): delete_item_by_id(tts_id) raise HTTPException(status_code=500, detail=str(exc)) from exc + size_bytes = get_file_size_bytes(filename) update_filename(tts_id, filename) + if size_bytes is not None: + update_size_bytes(tts_id, size_bytes) return { "id": tts_id, "created_at": created_at.isoformat(), "display_time": format_display_time(created_at), "filename": filename, - "size_display": get_file_size_display(filename), + "size_display": get_file_size_display(size_bytes), }