From 9c95b787b370446a66a98a2172ddf9abb121f427 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Sun, 14 Jun 2026 15:35:34 +0800 Subject: [PATCH] Add API endpoints (status/submit/task) --- app/api/status/index.dspy | 13 ++++++++ app/api/submit/index.dspy | 66 +++++++++++++++++++++++++++++++++++++++ app/api/task/index.dspy | 17 ++++++++++ app/health.dspy | 22 ++----------- conf/config.json | 45 +++++++++++++++++++++----- 5 files changed, 136 insertions(+), 27 deletions(-) create mode 100644 app/api/status/index.dspy create mode 100644 app/api/submit/index.dspy create mode 100644 app/api/task/index.dspy diff --git a/app/api/status/index.dspy b/app/api/status/index.dspy new file mode 100644 index 0000000..9d03a0b --- /dev/null +++ b/app/api/status/index.dspy @@ -0,0 +1,13 @@ +# -*- coding:utf-8 -*- +# GET /api/status - KTV合成服务状态 + +import subprocess +import json + +result = { + 'service': 'ktv-video-synthesis', + 'components': ['ffmpeg', 'ass-subtitle', 'video-concat'], + 'gpu_required': False +} + +return json.dumps(result) diff --git a/app/api/submit/index.dspy b/app/api/submit/index.dspy new file mode 100644 index 0000000..4bb8fca --- /dev/null +++ b/app/api/submit/index.dspy @@ -0,0 +1,66 @@ +# -*- coding:utf-8 -*- +# POST /api/submit - 提交KTV视频合成任务 + +import json +import uuid +from ahserver.serverenv import ServerEnv + +method = request.method + +if method == 'POST': + # 必需参数 + video_clips = params_kw.get('video_clips', []) + audio_path = params_kw.get('audio_path', '') + subtitle_path = params_kw.get('subtitle_path', '') + + if not video_clips or not isinstance(video_clips, list): + return json.dumps({'error': 'video_clips (list) is required'}, ensure_ascii=False) + if not audio_path: + return json.dumps({'error': 'audio_path is required'}, ensure_ascii=False) + if not subtitle_path: + return json.dumps({'error': 'subtitle_path (ASS file) is required'}, ensure_ascii=False) + + task_id = params_kw.get('task_id', str(uuid.uuid4()).replace("-", "")[:12]) + output_format = params_kw.get('output_format', 'mp4') + resolution = params_kw.get('resolution', '1920x1080') + + payload = { + 'task_type': 'synthesize', + 'task_id': task_id, + 'video_clips': video_clips, + 'audio_path': audio_path, + 'subtitle_path': subtitle_path, + 'output_format': output_format, + 'resolution': resolution + } + + 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', + 'video_clips_count': len(video_clips), + 'audio_path': audio_path, + 'subtitle_path': subtitle_path, + 'message': 'task submitted', + 'check_url': f'/api/task?task_id={real_task_id}' + }, ensure_ascii=False) + +else: + return json.dumps({ + 'usage': 'POST with JSON body', + 'params': { + 'video_clips': 'list (required, server paths to video segments)', + 'audio_path': 'string (required, server path to audio file)', + 'subtitle_path': 'string (required, server path to ASS subtitle file)', + 'output_format': 'string (default mp4)', + 'resolution': 'string (default 1920x1080)', + 'task_id': 'string (optional, auto-generated)', + } + }, ensure_ascii=False) diff --git a/app/api/task/index.dspy b/app/api/task/index.dspy new file mode 100644 index 0000000..a1137df --- /dev/null +++ b/app/api/task/index.dspy @@ -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) diff --git a/app/health.dspy b/app/health.dspy index e6e6a82..b7028a1 100644 --- a/app/health.dspy +++ b/app/health.dspy @@ -1,19 +1,3 @@ -KTV Synth Service Health Check - -This service provides KTV/MTV video synthesis using FFmpeg. - -Status: OK -Service: ktv-synth-service -Port: 9084 -Queue: ktv_synth -Output Directory: /tmp/ktv-synth-outputs - -Supported Operations: -- synthesize: Create KTV (dual-track) and MTV (single-track) videos - -Features: -- Two-step FFmpeg synthesis -- ASS subtitle rendering -- Dual audio track support (accompaniment + original) -- Configurable video looping -- 1920x1080 output resolution +import json +result = {"status": "ok", "service": "$svc"} +print(json.dumps(result)) diff --git a/conf/config.json b/conf/config.json index cd2763e..36b63e4 100644 --- a/conf/config.json +++ b/conf/config.json @@ -1,9 +1,38 @@ { - "port": 9084, - "queue": "ktv_synth", - "filesroot": "/tmp/ktv-synth-outputs", - "redis_url": "redis://127.0.0.1:6379", - "worker_cnt": 1, - "stuck_seconds": 1800, - "max_age_hours": 24 -} + "password_key": "KTVSynthService2026Key", + "databases": {}, + "session_redis": { + "host": "127.0.0.1", + "port": 6379, + "db": 1 + }, + "website": { + "paths": [ + [ + "$[workdir]$/app", + "" + ] + ], + "host": "0.0.0.0", + "port": 9084, + "coding": "utf-8", + "indexes": [ + "index.html", + "index.dspy" + ], + "processors": [ + [ + ".dspy", + "dspy" + ] + ], + "startswiths": [ + { + "leading": "/idfile", + "registerfunction": "idfile" + } + ] + }, + "hot_reload": false, + "filesroot": "/tmp/ktv-synth-outputs" +} \ No newline at end of file