TTS / app /api /routes.py
github-actions[bot]
Auto-deploy from GitHub: 6cd5884f5f59c8acb069f7a2a8f8ce8558f018b5
6203f3a
from fastapi import APIRouter, UploadFile, File, Form, HTTPException
from fastapi.responses import FileResponse, JSONResponse
import os
import uuid
import aiofiles
from app.core.config import settings
from custom_logger import logger_config as logger
from app.db import crud
from app.services.worker import start_worker, is_worker_running
router = APIRouter()
@router.get("/")
async def index():
return FileResponse('index.html')
@router.post("/api/tasks/upload")
async def create_task(
text: str = Form(None),
file: UploadFile = File(None),
voice: str = Form("4"),
speed: float = Form(1.0),
hide_from_ui: str = Form("")
):
task_text = ""
if text:
task_text = text
elif file:
try:
content = await file.read()
task_text = content.decode('utf-8')
except Exception as e:
logger.error(f"Error reading uploaded file: {e}")
raise HTTPException(status_code=400, detail="Could not read file content")
if not task_text.strip():
raise HTTPException(status_code=400, detail="No text provided")
task_id = str(uuid.uuid4())
filename = file.filename if file else f"{task_text[:20]}..."
hide_from_ui_val = 1 if hide_from_ui.lower() in ['true', '1'] else 0
await crud.insert_task(task_id, filename, task_text, voice, speed, 'not_started', hide_from_ui_val)
await start_worker()
return JSONResponse(status_code=201, content={
'id': task_id,
'filename': filename,
'status': 'not_started',
'message': 'Task created successfully'
})
@router.get("/api/tasks")
async def get_tasks():
rows, queue_ids, processing_count, avg_time = await crud.get_all_tasks()
tasks = []
for row in rows:
queue_position = None
estimated_start_seconds = None
if row['status'] == 'not_started' and row['id'] in queue_ids:
queue_position = queue_ids.index(row['id']) + 1
tasks_ahead = queue_position - 1 + processing_count
estimated_start_seconds = round(tasks_ahead * avg_time)
tasks.append({
'id': row['id'],
'filename': row['filename'],
'status': row['status'],
'result': "HIDDEN_IN_LIST_VIEW",
'created_at': row['created_at'],
'processed_at': row['processed_at'],
'progress': row['progress'] or 0,
'progress_text': row['progress_text'],
'queue_position': queue_position,
'estimated_start_seconds': estimated_start_seconds
})
return tasks
@router.get("/api/tasks/{task_id}")
async def get_task(task_id: str):
result = await crud.get_task_by_id(task_id)
if not result:
raise HTTPException(status_code=404, detail="Task not found")
row, queue_position, estimated_start_seconds = result
return {
'id': row['id'],
'filename': row['filename'],
'text': row['text'],
'status': row['status'],
'result': row['text'], # result maps to text for detail view
'output_file': row['output_file'],
'created_at': row['created_at'],
'processed_at': row['processed_at'],
'progress': row['progress'] or 0,
'progress_text': row['progress_text'],
'queue_position': queue_position,
'estimated_start_seconds': estimated_start_seconds
}
@router.get("/api/download/{task_id}")
async def download_task(task_id: str):
result = await crud.get_task_by_id(task_id)
if not result or not result[0]['output_file']:
raise HTTPException(status_code=404, detail="Audio file not found")
row = result[0]
filepath = os.path.join(settings.UPLOAD_FOLDER, row['output_file'])
if not os.path.exists(filepath):
raise HTTPException(status_code=404, detail="File missing on server")
return FileResponse(filepath, media_type="audio/wav", filename=f"tts_{task_id}.wav")
@router.get("/health")
async def health():
return {
'status': 'healthy',
'service': 'tts-runner',
'worker_running': is_worker_running()
}