Files
audio2text/app/controllers/task_router.py
zikai 00e2a95fb7 Initial commit: audio2text 双语字幕生成服务
- 音频/视频转双语(英/中)SRT 字幕,Docker 容器化,CPU 开发/GPU 生产同一份代码
- faster-whisper ASR(词级时间戳) + 断句时间戳重算 + NLLB 翻译(模型不共驻)
- 分片上传(断点续传) + SQLite 持久化 + 主页/历史/日志页面
- 历史页文件名搜索;缓存定时清理(默认保留7天,可配置)
- 双 Dockerfile(cpu/gpu) + setup/start/stop 脚本
2026-07-06 06:54:19 +00:00

89 lines
2.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""任务路由:列表 / 状态 / 下载字幕。"""
from __future__ import annotations
from pathlib import Path
from fastapi import APIRouter, Depends, HTTPException, Query
from fastapi.responses import FileResponse
from sqlalchemy.orm import Session
from ..config import get_settings
from ..database import get_db
from ..models.task import Task
from ..schemas.task import TaskListResponse, TaskResponse
router = APIRouter(prefix="/api/tasks", tags=["task"])
def _to_resp(task: Task) -> TaskResponse:
return TaskResponse(
id=task.id,
filename=task.filename,
status=task.status,
progress=task.progress,
error=task.error,
created_at=task.created_at,
updated_at=task.updated_at,
)
@router.get("", response_model=TaskListResponse, summary="任务列表")
def list_tasks(
limit: int = Query(100, ge=1, le=500),
offset: int = Query(0, ge=0),
q: str = Query("", description="按文件名模糊搜索(大小写不敏感,匹配子串)"),
db: Session = Depends(get_db),
) -> TaskListResponse:
q_base = db.query(Task).order_by(Task.id.desc())
if q.strip():
# SQLite 的 LIKE 默认大小写不敏感ASCIIilike 等价于 LIKE
like = f"%{q.strip()}%"
q_base = q_base.filter(Task.filename.ilike(like))
total = q_base.count()
tasks = q_base.offset(offset).limit(limit).all()
return TaskListResponse(tasks=[_to_resp(t) for t in tasks], total=total)
@router.get("/{task_id}", response_model=TaskResponse, summary="任务状态")
def get_task(task_id: int, db: Session = Depends(get_db)) -> TaskResponse:
task = db.get(Task, task_id)
if task is None:
raise HTTPException(404, f"任务不存在:{task_id}")
return _to_resp(task)
@router.get("/{task_id}/subtitle", summary="下载字幕")
def download_subtitle(
task_id: int,
type: str = Query("bilingual", pattern="^(bilingual|en|zh)$"),
db: Session = Depends(get_db),
) -> FileResponse:
task = db.get(Task, task_id)
if task is None:
raise HTTPException(404, f"任务不存在:{task_id}")
if task.status != "done":
raise HTTPException(409, f"任务尚未完成(当前状态:{task.status}")
rel = {
"bilingual": task.bilingual_srt_path,
"en": task.en_srt_path,
"zh": task.zh_srt_path,
}[type]
if not rel:
raise HTTPException(404, f"该类型字幕不存在:{type}")
s = get_settings()
path = s.output_dir() / rel
if not path.is_file():
raise HTTPException(404, f"字幕文件丢失:{path}")
base = Path(task.filename).stem
suffix = "" if type == "bilingual" else f".{type}"
download_name = f"{base}{suffix}.srt"
return FileResponse(
path=path,
media_type="application/x-subrip",
filename=download_name,
)