完善fastapi接口
This commit is contained in:
229
api/routers/resources.py
Normal file
229
api/routers/resources.py
Normal file
@@ -0,0 +1,229 @@
|
||||
"""
|
||||
Resource discovery endpoints
|
||||
|
||||
Provides endpoints to discover available workflows, templates, and BGM.
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from loguru import logger
|
||||
|
||||
from api.dependencies import PixelleVideoDep
|
||||
from api.schemas.resources import (
|
||||
WorkflowInfo,
|
||||
WorkflowListResponse,
|
||||
TemplateInfo,
|
||||
TemplateListResponse,
|
||||
BGMInfo,
|
||||
BGMListResponse,
|
||||
)
|
||||
from pixelle_video.utils.os_util import list_resource_files, get_root_path, get_data_path
|
||||
from pixelle_video.utils.template_util import get_all_templates_with_info
|
||||
|
||||
router = APIRouter(prefix="/resources", tags=["Resources"])
|
||||
|
||||
|
||||
@router.get("/workflows/tts", response_model=WorkflowListResponse)
|
||||
async def list_tts_workflows(pixelle_video: PixelleVideoDep):
|
||||
"""
|
||||
List available TTS workflows
|
||||
|
||||
Returns list of TTS workflows from both RunningHub and self-hosted sources.
|
||||
|
||||
Example response:
|
||||
```json
|
||||
{
|
||||
"workflows": [
|
||||
{
|
||||
"name": "tts_edge.json",
|
||||
"display_name": "tts_edge.json - Runninghub",
|
||||
"source": "runninghub",
|
||||
"path": "workflows/runninghub/tts_edge.json",
|
||||
"key": "runninghub/tts_edge.json",
|
||||
"workflow_id": "123456"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
"""
|
||||
try:
|
||||
# Get all workflows from TTS service
|
||||
all_workflows = pixelle_video.tts.list_workflows()
|
||||
|
||||
# Filter to TTS workflows only (filename starts with "tts_")
|
||||
tts_workflows = [
|
||||
WorkflowInfo(**wf)
|
||||
for wf in all_workflows
|
||||
if wf["name"].startswith("tts_")
|
||||
]
|
||||
|
||||
return WorkflowListResponse(workflows=tts_workflows)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"List TTS workflows error: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@router.get("/workflows/image", response_model=WorkflowListResponse)
|
||||
async def list_image_workflows(pixelle_video: PixelleVideoDep):
|
||||
"""
|
||||
List available image generation workflows
|
||||
|
||||
Returns list of image workflows from both RunningHub and self-hosted sources.
|
||||
|
||||
Example response:
|
||||
```json
|
||||
{
|
||||
"workflows": [
|
||||
{
|
||||
"name": "image_flux.json",
|
||||
"display_name": "image_flux.json - Runninghub",
|
||||
"source": "runninghub",
|
||||
"path": "workflows/runninghub/image_flux.json",
|
||||
"key": "runninghub/image_flux.json",
|
||||
"workflow_id": "123456"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
"""
|
||||
try:
|
||||
# Get all workflows from image service
|
||||
all_workflows = pixelle_video.image.list_workflows()
|
||||
|
||||
# Filter to image workflows only (filename starts with "image_")
|
||||
image_workflows = [
|
||||
WorkflowInfo(**wf)
|
||||
for wf in all_workflows
|
||||
if wf["name"].startswith("image_")
|
||||
]
|
||||
|
||||
return WorkflowListResponse(workflows=image_workflows)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"List image workflows error: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@router.get("/templates", response_model=TemplateListResponse)
|
||||
async def list_templates():
|
||||
"""
|
||||
List available video templates
|
||||
|
||||
Returns list of HTML templates grouped by size (portrait, landscape, square).
|
||||
Templates are merged from both default (templates/) and custom (data/templates/) directories.
|
||||
|
||||
Example response:
|
||||
```json
|
||||
{
|
||||
"templates": [
|
||||
{
|
||||
"name": "default.html",
|
||||
"display_name": "default.html",
|
||||
"size": "1080x1920",
|
||||
"width": 1080,
|
||||
"height": 1920,
|
||||
"orientation": "portrait",
|
||||
"path": "templates/1080x1920/default.html",
|
||||
"key": "1080x1920/default.html"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
"""
|
||||
try:
|
||||
# Get all templates with info
|
||||
all_templates = get_all_templates_with_info()
|
||||
|
||||
# Convert to API response format
|
||||
templates = []
|
||||
for t in all_templates:
|
||||
templates.append(TemplateInfo(
|
||||
name=t.display_info.name,
|
||||
display_name=t.display_info.name,
|
||||
size=t.display_info.size,
|
||||
width=t.display_info.width,
|
||||
height=t.display_info.height,
|
||||
orientation=t.display_info.orientation,
|
||||
path=t.template_path,
|
||||
key=t.template_path
|
||||
))
|
||||
|
||||
return TemplateListResponse(templates=templates)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"List templates error: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
|
||||
@router.get("/bgm", response_model=BGMListResponse)
|
||||
async def list_bgm():
|
||||
"""
|
||||
List available background music files
|
||||
|
||||
Returns list of BGM files merged from both default (bgm/) and custom (data/bgm/) directories.
|
||||
Custom files take precedence over default files with the same name.
|
||||
|
||||
Supported formats: mp3, wav, flac, m4a, aac, ogg
|
||||
|
||||
Example response:
|
||||
```json
|
||||
{
|
||||
"bgm_files": [
|
||||
{
|
||||
"name": "default.mp3",
|
||||
"path": "bgm/default.mp3",
|
||||
"source": "default"
|
||||
},
|
||||
{
|
||||
"name": "happy.mp3",
|
||||
"path": "data/bgm/happy.mp3",
|
||||
"source": "custom"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
"""
|
||||
try:
|
||||
# Supported audio extensions
|
||||
audio_extensions = ('.mp3', '.wav', '.flac', '.m4a', '.aac', '.ogg')
|
||||
|
||||
# Collect BGM files from both locations
|
||||
bgm_files_dict = {} # {filename: {"path": str, "source": str}}
|
||||
|
||||
# Scan default bgm/ directory
|
||||
default_bgm_dir = Path(get_root_path("bgm"))
|
||||
if default_bgm_dir.exists() and default_bgm_dir.is_dir():
|
||||
for item in default_bgm_dir.iterdir():
|
||||
if item.is_file() and item.suffix.lower() in audio_extensions:
|
||||
bgm_files_dict[item.name] = {
|
||||
"path": f"bgm/{item.name}",
|
||||
"source": "default"
|
||||
}
|
||||
|
||||
# Scan custom data/bgm/ directory (overrides default)
|
||||
custom_bgm_dir = Path(get_data_path("bgm"))
|
||||
if custom_bgm_dir.exists() and custom_bgm_dir.is_dir():
|
||||
for item in custom_bgm_dir.iterdir():
|
||||
if item.is_file() and item.suffix.lower() in audio_extensions:
|
||||
bgm_files_dict[item.name] = {
|
||||
"path": f"data/bgm/{item.name}",
|
||||
"source": "custom"
|
||||
}
|
||||
|
||||
# Convert to response format
|
||||
bgm_files = [
|
||||
BGMInfo(
|
||||
name=name,
|
||||
path=info["path"],
|
||||
source=info["source"]
|
||||
)
|
||||
for name, info in sorted(bgm_files_dict.items())
|
||||
]
|
||||
|
||||
return BGMListResponse(bgm_files=bgm_files)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"List BGM error: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
Reference in New Issue
Block a user