auto-save 2026-05-14 10:45 (+1, ~5)

This commit is contained in:
2026-05-14 10:45:48 +08:00
parent 1014114df8
commit d0abed6740
6 changed files with 317 additions and 15 deletions

View File

@@ -561,7 +561,36 @@ async def lifespan(_: FastAPI):
for p in JOBS_DIR.iterdir():
if p.is_dir() and (p / "state.json").exists():
try:
JOBS[p.name] = Job.model_validate_json((p / "state.json").read_text())
job = Job.model_validate_json((p / "state.json").read_text())
source_exists = (p / "source.mp4").exists()
if job.status in {"created", "downloading"}:
if source_exists:
update(job, status="downloaded", progress=25, message="服务重启 · 视频已恢复,可重新解析")
else:
update(job, status="failed", message="服务重启 · 下载任务已中断,请重新提交")
elif job.status == "splitting":
update(
job,
status="frames_extracted" if job.frames else "downloaded",
progress=70 if job.frames else 25,
message="服务重启 · 上次抽帧已中断,可重新抽帧",
)
elif job.status == "transcribing":
audio_script = job.audio_script
if audio_script.status == "rewriting":
audio_script = audio_script.model_copy(update={
"status": "failed",
"error": "服务重启 · 上次音频改写/配音已中断,可重新处理",
"created_at": audio_script.created_at or time.time(),
})
update(
job,
status="frames_extracted",
progress=70,
audio_script=audio_script,
message="服务重启 · 上次音频处理已中断,可重新处理",
)
JOBS[p.name] = job
except Exception:
pass
yield
@@ -1122,7 +1151,7 @@ def ffprobe_meta(mp4: Path) -> dict:
return json.loads(out)
async def pipeline_download(job_id: str) -> None:
def pipeline_download(job_id: str) -> None:
"""阶段 1仅下载或上传跳过落 source.mp4停在 downloaded 等用户点解析。"""
job = JOBS[job_id]
d = job_dir(job_id)
@@ -1159,7 +1188,7 @@ async def pipeline_download(job_id: str) -> None:
update(job, status="failed", error=str(e), message="下载失败")
async def pipeline_analyze(
def pipeline_analyze(
job_id: str,
frame_count: int = KEYFRAME_COUNT,
target: FrameExtractTarget = "transparent_human",
@@ -1311,7 +1340,7 @@ async def pipeline_analyze(
update(job, status="failed", error=str(e), message="解析失败")
async def analyze_queue_worker() -> None:
def analyze_queue_worker() -> None:
global ANALYZE_WORKER_RUNNING
ANALYZE_WORKER_RUNNING = True
try:
@@ -1319,7 +1348,7 @@ async def analyze_queue_worker() -> None:
job_id, frames, target, mode, quality = ANALYZE_QUEUE.pop(0)
if job_id not in JOBS:
continue
await pipeline_analyze(job_id, frames, target, mode, quality)
pipeline_analyze(job_id, frames, target, mode, quality)
if ANALYZE_QUEUE:
for pos, (queued_job_id, *_rest) in enumerate(ANALYZE_QUEUE, start=1):
queued_job = JOBS.get(queued_job_id)
@@ -1984,6 +2013,14 @@ def get_video(job_id: str):
return FileResponse(p, media_type="video/mp4")
@app.get("/jobs/{job_id}/audio.wav")
def get_source_audio(job_id: str):
p = job_dir(job_id) / "audio.wav"
if not p.exists():
raise HTTPException(404, "audio not found")
return FileResponse(p, media_type="audio/wav")
@app.get("/jobs/{job_id}/audio-script.mp3")
def get_audio_script(job_id: str):
p = job_dir(job_id) / "audio_script.mp3"