fix(lipsync): 修复 lipsync_tts 跨容器 import 错误导致 API/Worker 启动崩溃
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 2m5s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 29s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 15s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 2m40s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m2s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m21s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m29s
AI Code Review / AI Code Review (pull_request) Successful in 6m40s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 8m40s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m55s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 25m25s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Has been cancelled
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 16s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 138h7m12s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 138h30m19s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 138h31m0s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Failing after 138h32m37s
CI/CD Pipeline / PR Build Web Image (pull_request) Failing after 138h30m17s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 138h30m14s
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Failing after 138h32m23s
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Failing after 138h32m24s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 138h32m32s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 138h32m32s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 138h32m32s
CI/CD Pipeline / Check push changed paths (pull_request) Failing after 138h32m33s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 138h6m59s
CI/CD Pipeline / Canary Release to Production (pull_request) Failing after 138h6m58s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 138h6m58s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 138h6m59s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 138h30m9s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 138h30m6s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 138h30m52s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 2m5s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 29s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 15s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 2m40s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 3m2s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m21s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 4m29s
AI Code Review / AI Code Review (pull_request) Successful in 6m40s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 8m40s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 10m55s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 25m25s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Has been cancelled
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 16s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 138h7m12s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 138h30m19s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 138h31m0s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Failing after 138h32m37s
CI/CD Pipeline / PR Build Web Image (pull_request) Failing after 138h30m17s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 138h30m14s
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Failing after 138h32m23s
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Failing after 138h32m24s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 138h32m32s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 138h32m32s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 138h32m32s
CI/CD Pipeline / Check push changed paths (pull_request) Failing after 138h32m33s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 138h6m59s
CI/CD Pipeline / Canary Release to Production (pull_request) Failing after 138h6m58s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 138h6m58s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 138h6m59s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 138h30m9s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 138h30m6s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 138h30m52s
lipsync_tts.py 原从 apps.worker.worker_app 导入 celery_app,而 API 镜像中没有 apps.worker 目录, 导致 API 容器导入 lipsync_service 时 ModuleNotFoundError,健康检查失败触发自动回滚。 修复: 1. celery_app 改为从 app.core.celery_app 导入(API 侧 Celery app,API/Worker 镜像均存在) 2. _sign_media_url 改为模块内独立函数,去掉对 LipsyncService.__new__ 反射调用的依赖 (Worker 镜像不复制 services 目录,反射导入会失败) 3. worker.Dockerfile 补充 apps/api/app/tasks/、mediakit_client.py 及必需的 __init__.py (Worker 进程需能 import lipsync_tts task 并注册 Celery 路由)
This commit is contained in:
@@ -14,11 +14,42 @@
|
||||
import io
|
||||
import logging
|
||||
from datetime import datetime, timezone
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from apps.worker.worker_app.celery_app import celery_app
|
||||
from app.core.celery_app import celery_app
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# MediaKit 预签名 URL 有效期(7天,秒),与 LipsyncService 保持一致
|
||||
_MEDIAKIT_URL_TTL_SECONDS = 7 * 24 * 3600
|
||||
|
||||
|
||||
def _sign_media_url(url: str) -> str:
|
||||
"""对自家 OSS 私有桶 URL 重签长有效期预签名(与 LipsyncService._sign_media_url 保持一致).
|
||||
|
||||
- 自家 OSS URL → 重签 7 天有效期
|
||||
- 外部临时 URL → 原样透传
|
||||
- 任何异常降级原样返回,不阻断主流程
|
||||
"""
|
||||
if not url:
|
||||
return url
|
||||
try:
|
||||
from packages.shared.storage import get_shared_storage_service
|
||||
|
||||
storage = get_shared_storage_service()
|
||||
public_base = getattr(storage, "public_url", "")
|
||||
if not isinstance(public_base, str) or not public_base:
|
||||
return url
|
||||
own_host = urlparse(public_base).netloc.lower()
|
||||
host = urlparse(url).netloc.lower()
|
||||
if not own_host or host != own_host:
|
||||
return url
|
||||
signed = storage.get_download_url(url, expires_seconds=_MEDIAKIT_URL_TTL_SECONDS)
|
||||
return signed or url
|
||||
except Exception as exc: # noqa: BLE001
|
||||
logger.warning("[lipsync_tts] URL 重签失败,原样返回: url_prefix=%s err=%s", url[:80], exc)
|
||||
return url
|
||||
|
||||
|
||||
@celery_app.task(
|
||||
bind=True,
|
||||
@@ -109,7 +140,13 @@ def tts_synthesize_and_submit(
|
||||
audio_data = safe_download_bytes(
|
||||
temp_url,
|
||||
purpose="lipsync_tts_audio",
|
||||
allowed_mime_types=("audio/mpeg", "audio/mp3", "audio/wav", "audio/mp4", "audio/x-m4a"),
|
||||
allowed_mime_types=(
|
||||
"audio/mpeg",
|
||||
"audio/mp3",
|
||||
"audio/wav",
|
||||
"audio/mp4",
|
||||
"audio/x-m4a",
|
||||
),
|
||||
timeout=60.0,
|
||||
)
|
||||
storage = get_shared_storage_service()
|
||||
@@ -118,17 +155,18 @@ def tts_synthesize_and_submit(
|
||||
logger.info("[lipsync_tts] TTS 音频已转存 OSS: job_id=%s key=%s", job_id, storage_key)
|
||||
job.audio_url = permanent_url
|
||||
except Exception as exc:
|
||||
logger.warning("[lipsync_tts] TTS 音频转存 OSS 失败,回退临时 URL: job_id=%s err=%s", job_id, exc)
|
||||
logger.warning(
|
||||
"[lipsync_tts] TTS 音频转存 OSS 失败,回退临时 URL: job_id=%s err=%s",
|
||||
job_id,
|
||||
exc,
|
||||
)
|
||||
job.audio_url = temp_url
|
||||
|
||||
db.commit()
|
||||
|
||||
# 3. 签名 URL 并提交到 MediaKit
|
||||
from app.services.lipsync_service import LipsyncService
|
||||
|
||||
temp_service = LipsyncService.__new__(LipsyncService)
|
||||
audio_url = temp_service._sign_media_url(job.audio_url)
|
||||
video_url = temp_service._sign_media_url(job.video_url)
|
||||
audio_url = _sign_media_url(job.audio_url)
|
||||
video_url = _sign_media_url(job.video_url)
|
||||
|
||||
client = get_mediakit_client()
|
||||
try:
|
||||
@@ -141,7 +179,11 @@ def tts_synthesize_and_submit(
|
||||
job.mediakit_task_id = mk_result["task_id"]
|
||||
job.status = "submitted"
|
||||
job.submitted_at = datetime.now(timezone.utc)
|
||||
logger.info("[lipsync_tts] 已提交 MediaKit: job_id=%s task_id=%s", job_id, mk_result["task_id"])
|
||||
logger.info(
|
||||
"[lipsync_tts] 已提交 MediaKit: job_id=%s task_id=%s",
|
||||
job_id,
|
||||
mk_result["task_id"],
|
||||
)
|
||||
except MediaKitError as exc:
|
||||
job.status = "failed"
|
||||
job.error_message = str(exc)
|
||||
|
||||
@@ -30,6 +30,13 @@ COPY migrations/ /app/migrations/
|
||||
COPY packages/ /app/packages/
|
||||
COPY apps/api/app/config.py /app/apps/api/app/config.py
|
||||
COPY apps/api/app/core/ /app/apps/api/app/core/
|
||||
# API 侧 Celery 任务(lipsync_tts 等)在 worker 进程中执行,需复制任务文件、依赖及 __init__.py
|
||||
RUN mkdir -p /app/apps && touch /app/apps/__init__.py
|
||||
COPY apps/api/__init__.py /app/apps/api/__init__.py
|
||||
COPY apps/api/app/__init__.py /app/apps/api/app/__init__.py
|
||||
COPY apps/api/app/services/__init__.py /app/apps/api/app/services/__init__.py
|
||||
COPY apps/api/app/services/mediakit_client.py /app/apps/api/app/services/mediakit_client.py
|
||||
COPY apps/api/app/tasks/ /app/apps/api/app/tasks/
|
||||
|
||||
# Worker 启动脚本
|
||||
COPY infra/docker/entrypoint-worker.sh /usr/local/bin/entrypoint-worker.sh
|
||||
|
||||
Reference in New Issue
Block a user