feat(conversation): TTS 投递与 WebSocket 管线;客户端播放门禁与会话页联动;COS 键与迁移脚本调整

This commit is contained in:
Kevin
2026-03-26 15:51:24 +08:00
parent c23931ec91
commit d990399112
22 changed files with 630 additions and 74 deletions

View File

@@ -6,6 +6,13 @@ from typing import Any
from urllib.parse import urlparse
from app.core.config import settings
from app.core.logging import get_logger
from app.ports.storage import ObjectStorage
logger = get_logger(__name__)
# 客户端再读 TTS / 拉取音频:预签名有效期(秒),与移动端会话长度匹配
TTS_PRESIGNED_EXPIRES_SEC = 86_400
def extract_cos_object_key_if_owned(url: str | None) -> str | None:
@@ -75,3 +82,40 @@ def collect_cos_keys_from_tts_url_list(urls: list[str] | None) -> set[str]:
if k:
keys.add(k)
return keys
def presign_tts_urls_for_playback(
urls: list[str],
storage: ObjectStorage | None,
*,
expires: int = TTS_PRESIGNED_EXPIRES_SEC,
) -> list[str]:
"""
将本环境 COS 直链替换为预签名下载 URL私有桶下匿名 GET 会 AccessDenied
目的与回忆录 `normalize_image_assets_for_api` 中对 `get_download_url` 的用法一致。
非本环境 URL 或无法解析 key 时原样返回。
"""
if not storage or not urls:
return list(urls)
out: list[str] = []
for u in urls:
if not isinstance(u, str):
continue
s = u.strip()
if not s:
continue
key = extract_cos_object_key_if_owned(s)
if key:
try:
out.append(storage.get_url(key, expires=expires))
except Exception as exc:
logger.warning(
"presign tts url failed, keeping original url: key={} err={}",
key,
exc,
)
out.append(s)
else:
out.append(s)
return out