01e057c939
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Has been cancelled
CI/CD Pipeline / Staging E2E Tests (push) Has been cancelled
CI/CD Pipeline / Staging API Integration Tests (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / ACR Image Cleanup (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Failing after 1300h27m31s
CI/CD Pipeline / Build Production Worker Image (push) Failing after 1300h41m33s
CI/CD Pipeline / PR Build Worker Image (push) Failing after 1300h41m51s
CI/CD Pipeline / Build Production Web Image (push) Failing after 1300h41m35s
CI/CD Pipeline / PR Build Web Image (push) Failing after 1300h41m53s
CI/CD Pipeline / Check if frontend-only change (push) Failing after 1300h42m58s
CI/CD Pipeline / Validate - Code Quality (push) Failing after 1m25s
CI/CD Pipeline / Validate - Type Check (mypy) (push) Successful in 58s
CI/CD Pipeline / Validate - Migration (alembic) (push) Successful in 52s
CI/CD Pipeline / Unit Tests (push) Successful in 4m19s
CI/CD Pipeline / Integration Tests (push) Successful in 3m11s
CI/CD Pipeline / Frontend Lint (push) Successful in 35s
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 49s
CI/CD Pipeline / Build Production API Image (push) Failing after 1301h14m3s
CI/CD Pipeline / PR Build API Image (push) Failing after 1301h14m21s
CI/CD Pipeline / Build Staging API Image (push) Failing after 14m16s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 1m52s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 6m41s
134 lines
4.0 KiB
Python
Executable File
134 lines
4.0 KiB
Python
Executable File
"""BGM 管理路由.
|
||
|
||
端点:
|
||
- GET /bgm 获取 BGM 配置
|
||
- PUT /bgm 更新 BGM 配置
|
||
- GET /bgm/presets 预设 BGM 列表
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import logging
|
||
from typing import Any
|
||
|
||
from app.auth import AuthenticatedUser, get_current_user
|
||
from app.services.edit_plan_service import EditPlanService
|
||
from app.services.edit_template_service import EditTemplateService
|
||
from fastapi import APIRouter, Depends, HTTPException, Query, status
|
||
|
||
from .dependencies import get_draft_plan_id, get_editor_services
|
||
from .schemas import BGMConfigUpdateRequest
|
||
|
||
logger = logging.getLogger(__name__)
|
||
router = APIRouter(tags=["Template Editor"])
|
||
|
||
|
||
@router.get("/bgm", response_model=dict[str, Any])
|
||
def get_editor_bgm(
|
||
template_id: str,
|
||
plan_id: str = Depends(get_draft_plan_id),
|
||
services: tuple[EditTemplateService, EditPlanService] = Depends(get_editor_services),
|
||
_: AuthenticatedUser = Depends(get_current_user),
|
||
):
|
||
"""获取草稿的 BGM 配置"""
|
||
_, plan_svc = services
|
||
plan = plan_svc.get_plan_or_raise(plan_id)
|
||
config = plan.config or {}
|
||
return {
|
||
"plan_id": plan.id,
|
||
"bgm": config.get("bgm", {}),
|
||
}
|
||
|
||
|
||
@router.put("/bgm", response_model=dict[str, Any])
|
||
def update_editor_bgm(
|
||
template_id: str,
|
||
body: BGMConfigUpdateRequest,
|
||
plan_id: str = Depends(get_draft_plan_id),
|
||
services: tuple[EditTemplateService, EditPlanService] = Depends(get_editor_services),
|
||
current_user: AuthenticatedUser = Depends(get_current_user),
|
||
):
|
||
"""更新草稿的 BGM 配置"""
|
||
_, plan_svc = services
|
||
plan = plan_svc.get_plan_or_raise(plan_id)
|
||
|
||
config = dict(plan.config) if plan.config else {}
|
||
current_bgm = dict(config.get("bgm", {}))
|
||
update_data = body.model_dump(exclude_none=True)
|
||
current_bgm.update(update_data)
|
||
|
||
if current_bgm.get("enabled"):
|
||
has_source = any(
|
||
current_bgm.get(key)
|
||
for key in ("asset_id", "preset_id", "audio_url")
|
||
if current_bgm.get(key)
|
||
)
|
||
if not has_source:
|
||
raise HTTPException(
|
||
status_code=status.HTTP_400_BAD_REQUEST,
|
||
detail="启用 BGM 时需要指定素材来源(asset_id / preset_id / audio_url)",
|
||
)
|
||
|
||
config["bgm"] = current_bgm
|
||
updated_plan = plan_svc.update_plan_config(plan_id, config)
|
||
|
||
logger.info(
|
||
"模板编辑器更新BGM: template_id=%s plan_id=%s enabled=%s by user=%s",
|
||
template_id,
|
||
plan_id,
|
||
current_bgm.get("enabled", False),
|
||
current_user.user.id,
|
||
)
|
||
|
||
return {
|
||
"plan_id": updated_plan.id,
|
||
"bgm": current_bgm,
|
||
}
|
||
|
||
|
||
@router.get("/bgm/presets", response_model=dict[str, Any])
|
||
def list_editor_bgm_presets(
|
||
style: str | None = Query(default=None, description="按风格筛选"),
|
||
keyword: str | None = Query(default=None, description="关键词搜索"),
|
||
skip: int = Query(default=0, ge=0, description="分页偏移"),
|
||
limit: int = Query(default=50, ge=1, le=200, description="每页数量"),
|
||
_: AuthenticatedUser = Depends(get_current_user),
|
||
):
|
||
"""获取预设 BGM 列表"""
|
||
from packages.domain.preset_bgm import (
|
||
BGM_STYLES,
|
||
PRESET_BGM_LIBRARY,
|
||
list_preset_bgm_by_style,
|
||
search_preset_bgm,
|
||
)
|
||
|
||
bgm_list = PRESET_BGM_LIBRARY
|
||
if keyword:
|
||
bgm_list = search_preset_bgm(keyword)
|
||
elif style:
|
||
bgm_list = list_preset_bgm_by_style(style)
|
||
|
||
total = len(bgm_list)
|
||
paged = bgm_list[skip : skip + limit]
|
||
|
||
return {
|
||
"total": total,
|
||
"skip": skip,
|
||
"limit": limit,
|
||
"styles": BGM_STYLES,
|
||
"items": [
|
||
{
|
||
"id": bgm.id,
|
||
"name": bgm.name,
|
||
"style": bgm.style,
|
||
"style_label": BGM_STYLES.get(bgm.style, bgm.style),
|
||
"duration": bgm.duration,
|
||
"artist": bgm.artist,
|
||
"description": bgm.description,
|
||
"tags": bgm.tags,
|
||
"audio_url": bgm.audio_url,
|
||
}
|
||
for bgm in paged
|
||
],
|
||
}
|