Add verify_delivery HTTP service with 4 QA checks

- QA1: Timeline validation (monotonic, no overlap)
- QA2: Lyrics accuracy (ASS vs original)
- QA3: MTV original audio verification
- QA4: KTV dual-track validation (accompaniment + original)

Service runs on port 9085 with longtasks queue
This commit is contained in:
yumoqing 2026-06-14 16:21:19 +08:00
parent 9ff3f19e88
commit 20df29e524
8 changed files with 89 additions and 52 deletions

View File

@ -1,30 +0,0 @@
# -*- coding: utf-8 -*-
import json
mtv_path = params.get("mtv_path", "")
ktv_path = params.get("ktv_path", "")
ass_path = params.get("ass_path", "")
lyrics_path = params.get("lyrics_path", "")
calibrated_path = params.get("calibrated_path", "")
original_duration = params.get("original_duration", 0)
if not any([mtv_path, ktv_path]):
result = {"error": "至少需要提供mtv_path或ktv_path"}
return json.dumps(result, ensure_ascii=False)
payload = {
"mtv_path": mtv_path,
"ktv_path": ktv_path,
"ass_path": ass_path,
"lyrics_path": lyrics_path,
"calibrated_path": calibrated_path,
"original_duration": original_duration
}
task_id = longtasks.submit_task(payload)
result = {
"status": "submitted",
"task_id": task_id,
"message": "质检任务已提交,请用 /api/task?task_id=" + str(task_id) + " 查询结果"
}
return json.dumps(result, ensure_ascii=False, indent=2)

60
app/api/submit/index.dspy Normal file
View File

@ -0,0 +1,60 @@
# -*- coding:utf-8 -*-
# POST /api/submit - 提交KTV交付质检任务
import json
import uuid
from ahserver.serverenv import ServerEnv
method = request.method
if method == "POST":
mtv_path = params_kw.get("mtv_path", "")
ktv_path = params_kw.get("ktv_path", "")
ass_path = params_kw.get("ass_path", "")
lyrics_path = params_kw.get("lyrics_path", "")
calibrated_path = params_kw.get("calibrated_path", "")
original_duration = params_kw.get("original_duration", 0)
if not any([mtv_path, ktv_path]):
return json.dumps({"error": "至少需要提供mtv_path或ktv_path"}, ensure_ascii=False)
task_id = params_kw.get("task_id", str(uuid.uuid4()).replace("-", "")[:12])
payload = {
"task_type": "verify",
"task_id": task_id,
"mtv_path": mtv_path,
"ktv_path": ktv_path,
"ass_path": ass_path,
"lyrics_path": lyrics_path,
"calibrated_path": calibrated_path,
"original_duration": float(original_duration) if original_duration else 0
}
env = ServerEnv()
longtasks = env.longtasks
if longtasks is None:
return json.dumps({"error": "service not ready"}, ensure_ascii=False)
result = await longtasks.submit_task(payload)
real_task_id = result.get("task_id", str(result)) if isinstance(result, dict) else str(result)
return json.dumps({
"task_id": real_task_id,
"status": "queued",
"message": "质检任务已提交",
"check_url": f"/api/task?task_id={real_task_id}"
}, ensure_ascii=False)
else:
return json.dumps({
"usage": "POST with JSON body",
"params": {
"mtv_path": "string (optional, MTV视频路径)",
"ktv_path": "string (optional, KTV视频路径)",
"ass_path": "string (optional, ASS字幕路径)",
"lyrics_path": "string (optional, 原始歌词路径)",
"calibrated_path": "string (optional, calibrated.json路径)",
"original_duration": "float (optional, 原曲时长秒)",
"task_id": "string (optional, auto-generated)"
}
}, ensure_ascii=False)

View File

@ -1,17 +0,0 @@
# -*- coding: utf-8 -*-
import json
task_id = params.get("task_id", "")
if not task_id:
result = {"error": "缺少 task_id 参数"}
return json.dumps(result, ensure_ascii=False)
status = longtasks.get_status(task_id)
result = longtasks.get_result(task_id)
output = {
"task_id": task_id,
"status": status,
"result": result
}
return json.dumps(output, ensure_ascii=False, indent=2)

17
app/api/task/index.dspy Normal file
View File

@ -0,0 +1,17 @@
# -*- coding:utf-8 -*-
# GET /api/task?task_id=xxx - 查询任务状态
import json
from ahserver.serverenv import ServerEnv
task_id = params_kw.get("task_id", "")
if not task_id:
return json.dumps({"error": "task_id is required"}, ensure_ascii=False)
env = ServerEnv()
longtasks = env.longtasks
if longtasks is None:
return json.dumps({"error": "service not ready"}, ensure_ascii=False)
status = await longtasks.get_status(task_id)
return json.dumps(status)

View File

@ -1,9 +1,16 @@
{
"password_key": "VerifyDeliveryService2026Key",
"databases": {},
"session_redis": {"host": "127.0.0.1", "port": 6379, "db": 1},
"website": {
"processors": [[".dspy", "dspy"]],
"port": 9085,
"paths": [["$[workdir]$/app", ""]],
"host": "0.0.0.0",
"static_paths": [],
"index_pages": ["index.dspy"]
}
"port": 9085,
"coding": "utf-8",
"indexes": ["index.html", "index.dspy"],
"processors": [[".dspy", "dspy"]],
"startswiths": [{"leading": "/idfile", "registerfunction": "idfile"}]
},
"hot_reload": false,
"filesroot": "/tmp/verify-delivery-outputs"
}

0
start.sh Normal file → Executable file
View File

0
stop.sh Normal file → Executable file
View File