Compare commits

..

5 Commits

Author SHA1 Message Date
xiaoxia 50e833eeeb fix(web): Google Fonts 延迟到 window.load 后注入,彻底排除E2E load事件阻塞 (#2301)
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 1s
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 6s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 1m4s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Successful in 40s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m34s
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 44s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m5s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m12s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m4s
CI/CD Pipeline / Build Staging API Image (push) Successful in 3m50s
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Integration Tests (push) Successful in 4m18s
CI/CD Pipeline / Validate - Style (push) Successful in 5m23s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m35s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 6m1s
AI Code Review / AI Code Review (pull_request) Successful in 6m49s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m36s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m8s
CI/CD Pipeline / Staging E2E Tests (push) Successful in 3m14s
CI/CD Pipeline / Validate - Security (push) Successful in 13m3s
CI/CD Pipeline / Unit Tests (push) Successful in 18m18s
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
2026-10-14 22:56:14 +08:00
xiaoxia 79624587c4 fix(web): Google Fonts 非阻塞加载修复 E2E page.goto 超时 (#2300)
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 1s
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
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 / Frontend Lint (push) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 4s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 1m41s
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m32s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m8s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 28s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 33s
CI/CD Pipeline / Build Staging Web Image (push) Successful in 2m30s
CI/CD Pipeline / CI Gate (pull_request) Successful in 4s
CI/CD Pipeline / Retag skipped Staging Web Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m21s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m41s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m21s
CI/CD Pipeline / Integration Tests (push) Successful in 5m18s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 5m57s
CI/CD Pipeline / Validate - Style (push) Successful in 6m0s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 2m19s
AI Code Review / AI Code Review (pull_request) Successful in 7m4s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 4m19s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 4m51s
CI/CD Pipeline / Unit Tests (push) Successful in 12m39s
CI/CD Pipeline / Validate - Security (push) Successful in 15m38s
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
2026-10-14 21:39:29 +08:00
xiaoxia ee871ac4aa Merge pull request 'fix(ditto): blend_frames 默认值 12→6,与 GPU 端 clamp 最优值对齐' (#2299) from fix/ditto-blend-frames-default into develop
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
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 2s
CI/CD Pipeline / Check push changed paths (push) Successful in 3s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 3s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 47s
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 16s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 55s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 20s
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (push) Successful in 17s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 3m6s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 3m8s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m24s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 5m2s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m50s
CI/CD Pipeline / Integration Tests (push) Successful in 5m35s
CI/CD Pipeline / Validate - Style (push) Successful in 6m3s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 6m10s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m15s
AI Code Review / AI Code Review (pull_request) Successful in 6m50s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 5m6s
CI/CD Pipeline / Build Production Worker Image (push) Has been cancelled
CI/CD Pipeline / Deploy Production (push) Has been cancelled
CI/CD Pipeline / Unit Tests (push) Has been cancelled
CI/CD Pipeline / Build Production API Image (push) Has been cancelled
CI/CD Pipeline / Build Production Web Image (push) Has been cancelled
CI/CD Pipeline / Production Browser E2E (push) Has been cancelled
CI/CD Pipeline / Canary Release to Production (push) Has been cancelled
CI/CD Pipeline / CI Gate (push) Has been cancelled
CI/CD Pipeline / Validate - Security (push) Has been cancelled
2026-10-14 21:26:46 +08:00
xiaoxia 50c8618b87 fix(viral-script): 加固_safe_format防花括号炸format+默认模板回落ERROR+markdown时间分块 (#2298)
CI/CD Pipeline / Check if frontend-only change (push) Has been skipped
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (push) Successful in 1s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check push changed paths (push) Successful in 5s
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 3s
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 4s
CI/CD Pipeline / Frontend Lint (push) Has been skipped
CI/CD Pipeline / PR Build API Image (push) Has been skipped
CI/CD Pipeline / PR Build Web Image (push) Has been skipped
CI/CD Pipeline / PR Build Worker Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (push) Successful in 2m22s
CI/CD Pipeline / Build Staging Web Image (push) Has been skipped
CI/CD Pipeline / Build Staging API Image (push) Successful in 36s
CI/CD Pipeline / Validate - Style (pull_request) Has been skipped
CI/CD Pipeline / Validate - Security (pull_request) Has been skipped
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Has been skipped
CI/CD Pipeline / Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 27s
CI/CD Pipeline / Build Staging Worker Image (push) Successful in 1m14s
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (push) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (push) Successful in 5m31s
CI/CD Pipeline / Retag skipped Staging Web Image (push) Successful in 45s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m32s
CI/CD Pipeline / CI Gate (pull_request) Successful in 1s
CI/CD Pipeline / Validate - Python (mypy + alembic) (push) Successful in 6m24s
CI/CD Pipeline / Validate - Style (push) Successful in 6m29s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m58s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Has been skipped
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 2m33s
AI Code Review / AI Code Review (pull_request) Successful in 6m29s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (push) Successful in 1m48s
CI/CD Pipeline / ACR Image Cleanup (push) Successful in 1m46s
CI/CD Pipeline / Staging API Integration Tests (push) Successful in 3m20s
CI/CD Pipeline / Unit Tests (push) Successful in 13m20s
CI/CD Pipeline / Validate - Security (push) Successful in 15m44s
CI/CD Pipeline / Build Production API Image (push) Has been skipped
CI/CD Pipeline / Build Production Worker Image (push) Has been skipped
CI/CD Pipeline / CI Gate (push) Has been skipped
CI/CD Pipeline / Build Production Web Image (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Canary Release to Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Failing after 3m8s
Co-authored-by: xiaoxia <dev@xiaoxiajianji.com>
Co-committed-by: xiaoxia <dev@xiaoxiajianji.com>
2026-10-14 20:41:34 +08:00
Agent 712464f030 fix(ditto): blend_frames 默认值 12→6,与 GPU 端 clamp 最优值对齐
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
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 2s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 53s
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 1m15s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m53s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m59s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 5m11s
CI/CD Pipeline / Validate - Style (pull_request) Successful in 6m27s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 6m36s
AI Code Review / AI Code Review (pull_request) Successful in 6m47s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 9m51s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 15m37s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Failing after 2s
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 9m11s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 28s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 4m22s
GPU 端三层表情优化(眨眼+情绪头动+眼球微动+呼吸感+非唇动态混合+低表情检测)
已完成,blend_frames=6 时表情切换最灵敏;GPU 端仍保留 max(6,min(8,...)) clamp
兜底,本改动仅让 SaaS 端默认值与 GPU 最优值对齐。

注意:staging DB 当前 ditto_blend_frames=10(DB 优先于 env 默认),本 PR 合入后
需通过后台配置将 DB 值改为 6 才会在 staging 实际生效;生产未开 Ditto 无影响。
范围校验 6-30 不变。
2026-10-14 20:39:09 +08:00
5 changed files with 197 additions and 34 deletions
+47 -21
View File
@@ -4,31 +4,57 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- 标题字体(#2001 / #font-selection 修复):完全非阻塞加载中文字体
- 使用 preload + 动态 rel 切换的"无阻塞字体加载"模式:
浏览器以 preload 低优先级拉取 CSS,不会阻塞 render/DOMContentLoaded/load 任一事件
- onload 后切换 rel=stylesheet 字体才生效,首屏用系统字体兜底(Noto Sans SC → PingFang SC → Microsoft YaHei → sans-serif)
- 解决境内访问 Google Fonts 挂起时首屏白屏 + Playwright load 事件超时(E2E 也受益) -->
<link
rel="preload"
as="style"
href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;700;900&family=Noto+Serif+SC:wght@400;700;900&family=ZCOOL+KuaiLe&family=ZCOOL+XiaoWei&family=ZCOOL+QingKe+HuangYou&family=Ma+Shan+Zheng&family=Long+Cang&family=Liu+Jian+Mao+Cao&family=Zhi+Mang+Xing&display=swap"
/>
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;700;900&family=Noto+Serif+SC:wght@400;700;900&family=ZCOOL+KuaiLe&family=ZCOOL+XiaoWei&family=ZCOOL+QingKe+HuangYou&family=Ma+Shan+Zheng&family=Long+Cang&family=Liu+Jian+Mao+Cao&family=Zhi+Mang+Xing&display=swap"
media="print"
onload="this.media='all'; this.onload=null"
/>
<noscript
><link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;700;900&family=Noto+Serif+SC:wght@400;700;900&family=ZCOOL+KuaiLe&family=ZCOOL+XiaoWei&family=ZCOOL+QingKe+HuangYou&family=Ma+Shan+Zheng&family=Long+Cang&family=Liu+Jian+Mao+Cao&family=Zhi+Mang+Xing&display=swap"
/></noscript>
<!-- 标题字体(#2001 / #font-selection 修复):Google Fonts 中文字体完全延迟加载
关键设计:所有 Google Fonts 子资源(CSS + 字体文件)必须在 window load 之后才发起请求。
- 原因:fonts.googleapis.com/gstatic.com 在境内访问间歇性挂起,若在关键路径内
(<link rel=stylesheet>/preload/preconnect 等任何会被计入文档子资源完成的形式),
会拖死 window.load 事件,导致 Playwright page.goto 默认 waitUntil:'load' 90s 超时,
同时真实用户首屏也可能因等字体而白屏。
- 实现:head 里完全不出现 Google 域的 <link>,首屏用系统字体兜底
(font-family fallback 链:Noto Sans SC → PingFang SC → Microsoft YaHei → sans-serif);
页面 load 后通过 requestIdleCallback 动态注入 <link rel=stylesheet>,字体异步加载生效。
- noscript 降级:JS 禁用时仍然阻塞加载(可接受,这类用户极少)。
- 参考:运维 2026-10-14 E2E 失败根因分析,#2300 preload/media=print 方案不治本,
preload 与 media=print 样式表仍计入子资源完成,会阻塞 load 事件。 -->
<title>小虾 SaaS - 自动化视频剪辑平台</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
<!-- Google Fonts 延迟注入:必须在 main.tsx 之后,用独立 <script>(非 module)在页面解析
完成时注册 load 回调;window.load 触发后再 requestIdleCallback 插 <link>,
确保字体请求不进入首屏关键路径,也不阻塞 Playwright load 等待 -->
<script>
(function () {
var FONT_HREF =
"https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;700;900&family=Noto+Serif+SC:wght@400;700;900&family=ZCOOL+KuaiLe&family=ZCOOL+XiaoWei&family=ZCOOL+QingKe+HuangYou&family=Ma+Shan+Zheng&family=Long+Cang&family=Liu+Jian+Mao+Cao&family=Zhi+Mang+Xing&display=swap";
function inject() {
if (document.getElementById("__gfonts_link")) return;
var l = document.createElement("link");
l.id = "__gfonts_link";
l.rel = "stylesheet";
l.href = FONT_HREF;
l.setAttribute("data-lazy", "1");
document.head.appendChild(l);
}
function schedule() {
if ("requestIdleCallback" in window) {
requestIdleCallback(inject, { timeout: 2000 });
} else {
setTimeout(inject, 500);
}
}
if (document.readyState === "complete") {
schedule();
} else {
window.addEventListener("load", schedule, { once: true });
}
})();
</script>
<noscript
><link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;700;900&family=Noto+Serif+SC:wght@400;700;900&family=ZCOOL+KuaiLe&family=ZCOOL+XiaoWei&family=ZCOOL+QingKe+HuangYou&family=Ma+Shan+Zheng&family=Long+Cang&family=Liu+Jian+Mao+Cao&family=Zhi+Mang+Xing&display=swap"
/></noscript>
</body>
</html>
+22 -1
View File
@@ -1248,7 +1248,7 @@ def _parse_script_markdown(
ratio: str,
default_theme: str,
) -> dict | None:
"""中文 markdown 兜底解析(格式C):按"镜头1/镜头一/第1镜"等分割。"""
"""中文 markdown 兜底解析(格式C/D):按"镜头1/镜头一/第1镜"或"0-4秒/4-8秒"时间范围分割。"""
# 提取 theme
theme = default_theme
theme_match = _MD_FIELD_RE["theme"].search(raw)
@@ -1421,6 +1421,27 @@ def _step_script_generation(
dur = max(5, min(30, int(getattr(job, "duration", 15) or 15)))
template = get_template("storyboard")
# P0 观测:模板来自代码默认(DB 加载失败)时打 ERROR,避免静默回落
# 判定方式:system_prompt 与 DEFAULT_TEMPLATES storyboard 完全一致
try:
from packages.application.viral_video.prompts import DEFAULT_TEMPLATES as _DEF_T
_def_story = next((t for t in _DEF_T if t["prompt_type"] == "storyboard"), None)
if (
template is not None
and _def_story is not None
and template.system_prompt == _def_story["system_prompt"]
and (template.example_output or "") == (_def_story.get("example_output") or "")
):
logger.error(
"[爆款视频] storyboard 模板使用代码默认 v%s/%s(DB 加载失败或无激活模板),"
"检查 DB 连接与 is_active——本次生成质量无保障,job_id=%s",
template.version,
template.name,
job.id,
)
except Exception: # noqa: BLE001
pass
marketing_purpose = getattr(job, "marketing_purpose", "") or "未指定"
theme_hint = _determine_theme(image_analysis, marketing_purpose)
@@ -166,17 +166,63 @@ def invalidate() -> None:
_warned.clear()
class _SafeDict(dict):
def __missing__(self, key: str) -> str:
return "{" + key + "}"
def _safe_format(text: str, kwargs: dict) -> str:
try:
return text.format_map(_SafeDict(kwargs))
except Exception as e: # noqa: BLE001
_warn_once("safe_format", "format", e)
return text
"""安全格式化模板:任何占位符异常(缺key/属性访问失败/格式符非法/JSON花括号样例)
都原样保留,不抛异常、不静默回落默认模板,只打一条warning告警。
不用 str.format_map(_SafeDict):_SafeDict 只能防 KeyError,无法防 AttributeError
(如 {duration.1格式写全6项参数} 访问 str.1格式... 会抛 AttributeError),
也无法防非法 format_spec(如 JSON 样例 {"key":"val"} 里冒号被当格式符)。
"""
import string as _string
out: list[str] = []
i, n = 0, len(text)
errors: list[str] = []
while i < n:
c = text[i]
if c == "{":
if i + 1 < n and text[i + 1] == "{":
out.append("{")
i += 2
continue
j = i + 1
depth = 1
while j < n and depth > 0:
if text[j] == "{":
depth += 1
elif text[j] == "}":
depth -= 1
j += 1
if depth == 0:
inner = text[i + 1 : j - 1]
try:
val = _string.Formatter().vformat("{" + inner + "}", (), kwargs)
out.append(val)
except Exception as e: # noqa: BLE001
# 非法占位符原样保留,避免模板里的样例JSON/说明文本炸format
errors.append(f"{inner!r}: {type(e).__name__}")
out.append(text[i:j])
i = j
continue
if c == "}":
if i + 1 < n and text[i + 1] == "}":
out.append("}")
i += 2
continue
out.append(c)
i += 1
if errors:
# 模板里花括号炸format是配置bug(如v5事故里{duration.1格式写全6项参数}),
# 提升到 ERROR 级别,避免被warning海淹没
logger.error(
"[viral][prompt] 模板格式化有%d个占位符无法渲染(示例:%s),"
"已原样保留——请检查system/user_prompt_template中花括号是否为样例文本而非变量",
len(errors),
errors[0],
)
_warn_once("safe_format", "format", f"{len(errors)}个占位符异常(首条{errors[0]})")
return "".join(out)
def render_system_prompt(template: PromptTemplate, **kwargs) -> str:
+2 -2
View File
@@ -202,9 +202,9 @@ class SharedSettings(BaseSettings):
default=120,
validation_alias=AliasChoices("DITTO_REQUEST_TIMEOUT", "ditto_request_timeout"),
)
# Ditto 句间过渡帧数(平滑表情/口型切换)
# Ditto 句间过渡帧数(平滑表情/口型切换);默认 6 与 GPU 端 clamp 最优值对齐(表情切换更灵敏)
ditto_blend_frames: int = Field(
default=12,
default=6,
validation_alias=AliasChoices("DITTO_BLEND_FRAMES", "ditto_blend_frames"),
)
+70
View File
@@ -1449,3 +1449,73 @@ class TestMarkdownTimeRangeSplit:
assert result is not None
assert len(result["shots"]) == 2
assert "你好" in result["voiceover_script"]
class TestSafeFormatHardening:
"""_safe_format 必须能扛住模板里任意花括号样例,不抛异常、不返回半截内容"""
def test_missing_key_preserves_placeholder(self):
from packages.application.viral_video.prompt_loader import _safe_format
out = _safe_format("时长{duration}秒,{missing}保留", {"duration": "20"})
assert out == "时长20秒,{missing}保留"
def test_attribute_access_on_string_preserves_placeholder(self):
"""复现v5事故:{duration.1格式写全6项参数}访问str的非法属性不应抛异常"""
from packages.application.viral_video.prompt_loader import _safe_format
out = _safe_format(
"总时长:{duration.1格式写全6项参数,第二个镜头起末尾加转场}秒",
{"duration": "20"},
)
assert "总时长:{duration.1格式写全6项参数,第二个镜头起末尾加转场}秒" == out
def test_json_braces_in_example_preserved(self):
"""模板里给LLM示例JSON时,{"key":"val"}不应被当format_spec解析"""
from packages.application.viral_video.prompt_loader import _safe_format
out = _safe_format(
'输出JSON示例:{"key": "value", "n": 1},时长{duration}秒',
{"duration": "20"},
)
assert '{"key": "value", "n": 1}' in out
assert "时长20秒" in out
def test_chinese_example_braces_preserved(self):
"""中文花括号示例如{示例}原样保留"""
from packages.application.viral_video.prompt_loader import _safe_format
out = _safe_format("规则:不要输出{示例}这类占位符,时长{duration}", {"duration": "20"})
assert "{示例}" in out
assert "时长20" in out
def test_escaped_braces_unescaped(self):
"""{{escaped}} 正常输出 {escaped}"""
from packages.application.viral_video.prompt_loader import _safe_format
out = _safe_format("这是{{escaped}},时长{duration}", {"duration": "20"})
assert out == "这是{escaped},时长20"
def test_legitimate_attribute_access_works(self):
"""合法对象属性访问仍正常工作"""
from packages.application.viral_video.prompt_loader import _safe_format
class Obj:
brand = "御众堂"
out = _safe_format("品牌:{obj.brand}", {"obj": Obj()})
assert out == "品牌:御众堂"
def test_invalid_format_spec_preserves_placeholder(self):
"""{val:invalid} 这种坏格式符原样保留"""
from packages.application.viral_video.prompt_loader import _safe_format
out = _safe_format("坏格式{val:invalid_chinese}结束", {"val": "x"})
assert "{val:invalid_chinese}" in out
def test_normal_format_spec_still_works(self):
"""合法格式符 {n:>3} 仍正常工作"""
from packages.application.viral_video.prompt_loader import _safe_format
out = _safe_format("数字{n:>3}结束", {"n": 5})
assert "5" in out