Store mp3 size in database

Persist file size at creation and backfill missing sizes on list responses so the UI can display sizes reliably.
This commit is contained in:
dsyoon
2026-01-30 20:51:18 +09:00
parent 7ee89d0629
commit 1d92f2f4fa
2 changed files with 54 additions and 15 deletions

View File

@@ -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;
""",

View File

@@ -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 [
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(row["filename"]),
"size_display": get_file_size_display(size_bytes),
}
for row in rows
]
)
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),
}