feat(voices): TTS时长修复 + 提取视频配音 + AI配音标识 (#1656)
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 2s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 3s
CI/CD Pipeline / Check push changed paths (push) Successful in 4s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Build Staging API Image (push) Successful in 29s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 12s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 13s
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 16s
CI/CD Pipeline / PR Build Web Image (pull_request) Successful in 23s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m11s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 20s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 3s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 1m48s
AI Code Review / AI Code Review (pull_request) Failing after 2m6s
CI/CD Pipeline / Integration Tests (push) Successful in 2m12s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m9s
CI/CD Pipeline / Validate - Style (push) Failing after 3m5s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m5s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m30s
CI/CD Pipeline / Frontend Unit Tests (push) Failing after 4m35s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m10s
CI/CD Pipeline / Validate - Security (push) Successful in 5m43s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 4m0s
CI/CD Pipeline / Unit Tests (push) Successful in 7m31s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Failing after 308h1m6s
CI/CD Pipeline / CI Gate (push) Failing after 308h12m41s
CI/CD Pipeline / Build Production Worker Image (push) Failing after 308h12m41s
CI/CD Pipeline / Build Production API Image (push) Failing after 308h12m41s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Failing after 308h17m7s
CI/CD Pipeline / Deploy Production (pull_request) Failing after 308h18m57s
CI/CD Pipeline / Staging E2E Tests (pull_request) Failing after 308h19m0s
CI/CD Pipeline / ACR Image Cleanup (pull_request) Failing after 308h18m58s
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Failing after 308h19m0s
CI/CD Pipeline / Retag skipped Staging API Image (push) Failing after 308h19m1s
CI/CD Pipeline / Build Production Worker Image (pull_request) Failing after 308h19m2s
CI/CD Pipeline / Build Production API Image (pull_request) Failing after 308h19m3s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Failing after 308h19m3s
CI/CD Pipeline / Frontend Unit Tests (pull_request) Failing after 308h19m33s
CI/CD Pipeline / Integration Tests (pull_request) Failing after 308h19m33s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 308h19m33s
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Failing after 308h20m9s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Failing after 308h20m9s
CI/CD Pipeline / Validate - Security (pull_request) Failing after 308h20m10s
CI/CD Pipeline / Validate - Style (pull_request) Failing after 308h20m11s
CI/CD Pipeline / Frontend Lint (push) Failing after 308h20m13s
CI/CD Pipeline / Build Staging Worker Image (pull_request) Failing after 308h20m14s
CI/CD Pipeline / Build Staging API Image (pull_request) Failing after 308h20m15s
CI/CD Pipeline / PR Build Worker Image (push) Failing after 308h20m16s
CI/CD Pipeline / PR Build API Image (push) Failing after 308h20m16s
CI/CD Pipeline / Check push changed paths (pull_request) Failing after 308h20m16s
CI/CD Pipeline / Check if frontend-only change (push) Failing after 308h20m17s
CI/CD Pipeline / Deploy Production (push) Failing after 308h47m2s
CI/CD Pipeline / Build Production Web Image (push) Failing after 308h47m4s
CI/CD Pipeline / Staging API Integration Tests (pull_request) Failing after 308h53m22s
CI/CD Pipeline / Retag skipped Staging Web Image (push) Failing after 308h53m23s
CI/CD Pipeline / Build Production Web Image (pull_request) Failing after 308h53m25s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 308h53m56s
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Failing after 308h54m32s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Failing after 308h54m33s
CI/CD Pipeline / Build Staging Web Image (pull_request) Failing after 308h54m38s
CI/CD Pipeline / PR Build Web Image (push) Failing after 308h54m39s

Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
This commit was merged in pull request #1656.
This commit is contained in:
2026-09-03 19:04:35 +08:00
committed by auto-approve-bot
parent e6e4090f3c
commit 6d2d63da7e
8 changed files with 418 additions and 3 deletions
+22 -1
View File
@@ -2,7 +2,9 @@
from __future__ import annotations
import json
import logging
import subprocess
import tempfile
from pathlib import Path
from typing import Any, Optional
@@ -430,6 +432,8 @@ def save_tts_job_to_library(
storage_key = f"uploads/voice/tts/{job.id}.{audio_format}"
tmp_path: Path | None = None
audio_duration: float | None = None
file_size = 0
try:
with tempfile.NamedTemporaryFile(suffix=f".{audio_format}", delete=False) as tmp:
tmp_path = Path(tmp.name)
@@ -445,6 +449,23 @@ def save_tts_job_to_library(
)
file_size = tmp_path.stat().st_size
storage_service.upload_file(tmp_path, storage_key, content_type=content_type)
# 从音频文件提取时长(ffprobe),作为 job.duration 的兜底
try:
proc = subprocess.run(
[
"ffprobe", "-v", "quiet", "-print_format", "json",
"-show_format", str(tmp_path),
],
capture_output=True, text=True, timeout=10,
)
if proc.returncode == 0:
fmt = json.loads(proc.stdout).get("format", {})
dur = float(fmt.get("duration", 0))
if dur > 0:
audio_duration = dur
except Exception:
logger.warning("ffprobe 提取时长失败: job_id=%s", job.id, exc_info=True)
except HTTPException:
raise
except Exception as e:
@@ -482,7 +503,7 @@ def save_tts_job_to_library(
mime_type=content_type,
metadata=metadata_,
file_size=file_size,
duration=job.duration or None,
duration=job.duration or audio_duration or None,
status=AssetStatus.READY,
classification_status=ClassificationStatus.PENDING, # 音频不参与内容分类,保持 pending 与 ingest 链路一致
uploaded_by_user_id=user_id,