diff --git a/packages/shared/ai_client.py b/packages/shared/ai_client.py index fb2a75630..819aa61ba 100755 --- a/packages/shared/ai_client.py +++ b/packages/shared/ai_client.py @@ -297,18 +297,22 @@ class DoubaoClient: if image_url: if has_extra_refs: # omni_reference:首张图作为 reference_image,允许指定 ratio - content.append({ - "type": "image_url", - "image_url": {"url": image_url}, - "role": "reference_image", - }) + content.append( + { + "type": "image_url", + "image_url": {"url": image_url}, + "role": "reference_image", + } + ) else: # 纯首帧:不带 role,服务端识别为 first_frame(或显式 role=first_frame) - content.append({ - "type": "image_url", - "image_url": {"url": image_url}, - "role": "first_frame", - }) + content.append( + { + "type": "image_url", + "image_url": {"url": image_url}, + "role": "first_frame", + } + ) for u in ref_imgs: content.append({"type": "image_url", "image_url": {"url": u}, "role": "reference_image"}) for u in ref_audios: @@ -358,7 +362,7 @@ class DoubaoClient: except Exception as ee: last_err = ee if attempt < self.max_retries: - time.sleep(0.5 * (2 ** attempt)) + time.sleep(0.5 * (2**attempt)) continue return None, last_err, sc, body data = resp.json() @@ -369,8 +373,14 @@ class DoubaoClient: except Exception as e: last_err = e if attempt < self.max_retries: - wait = 0.5 * (2 ** attempt) - logger.warning("Seedance 创建任务失败,%.1fs 后重试 (%d/%d): %s", wait, attempt + 1, self.max_retries + 1, e) + wait = 0.5 * (2**attempt) + logger.warning( + "Seedance 创建任务失败,%.1fs 后重试 (%d/%d): %s", + wait, + attempt + 1, + self.max_retries + 1, + e, + ) time.sleep(wait) return None, last_err, 0, "" @@ -378,7 +388,16 @@ class DoubaoClient: task_id, last_err, sc, body = _do_create(create_payload) # ratio 兜底:HTTP 400 且 body 提到 ratio / adaptive → 回退 adaptive 再试一次 - if not task_id and sc == 400 and final_ratio != "adaptive" and ("ratio" in (body or "").lower() or "aspect" in (body or "").lower() or "adaptive" in (body or "").lower()): + if ( + not task_id + and sc == 400 + and final_ratio != "adaptive" + and ( + "ratio" in (body or "").lower() + or "aspect" in (body or "").lower() + or "adaptive" in (body or "").lower() + ) + ): logger.warning("Seedance 创建因 ratio 失败,回退 ratio=adaptive 重试") create_payload["ratio"] = "adaptive" task_id, last_err, sc2, body2 = _do_create(create_payload) @@ -388,7 +407,10 @@ class DoubaoClient: "Seedance 创建任务最终失败: model=%s base_url=%s err=%s body=%s 【排查】" "1) 方舟控制台已开通 doubao-seedance-2-5-260628;2) API Key 有该模型权限;" "3) DOUBAO_BASE_URL=https://ark.cn-beijing.volces.com/api/v3;4) 参考素材 URL 公网可访问。", - video_model, self.base_url, last_err, (body or "")[:500], + video_model, + self.base_url, + last_err, + (body or "")[:500], ) return None @@ -444,7 +466,11 @@ class DoubaoClient: if not video_url: logger.error( "Seedance 任务未成功: task_id=%s last_status=%s polls=%d err=%s (总等待 %.0fs)", - task_id, last_status, poll_count, last_err, total_timeout, + task_id, + last_status, + poll_count, + last_err, + total_timeout, ) return None @@ -454,7 +480,9 @@ class DoubaoClient: os.makedirs(out_dir, exist_ok=True) local_path = f"{out_dir}/seedance_{task_id}_{uuid.uuid4().hex[:8]}.mp4" download_timeout = 120.0 - logger.info("Seedance 开始下载: task_id=%s url=%s timeout=%.0fs", task_id, video_url[:120], download_timeout) + logger.info( + "Seedance 开始下载: task_id=%s url=%s timeout=%.0fs", task_id, video_url[:120], download_timeout + ) with httpx.stream("GET", video_url, timeout=download_timeout) as r: r.raise_for_status() downloaded = 0