diff --git a/nodes/volcengine_doubao_seedance.py b/nodes/volcengine_doubao_seedance.py index e5f6926..c1497f2 100644 --- a/nodes/volcengine_doubao_seedance.py +++ b/nodes/volcengine_doubao_seedance.py @@ -88,22 +88,44 @@ class VolcengineDoubaoSeedance: def image_to_base64(self, image_tensor): """将ComfyUI图片张量转换为Base64""" + print(f"=== DEBUG: 图片转换开始 ===") + print(f"输入张量形状: {image_tensor.shape}") + print(f"输入张量数据类型: {image_tensor.dtype}") + print(f"输入张量值范围: {image_tensor.min().item()} ~ {image_tensor.max().item()}") + # image_tensor shape: [1, H, W, 3] if image_tensor.dim() == 4: image_tensor = image_tensor.squeeze(0) # 移除batch维度 + print(f"移除batch维度后形状: {image_tensor.shape}") # 转换为numpy数组并确保数据类型正确 image_np = image_tensor.cpu().numpy() + print(f"转换为numpy后数据类型: {image_np.dtype}") + if image_np.dtype != np.uint8: image_np = (image_np * 255).astype(np.uint8) + print(f"转换为uint8后值范围: {image_np.min()} ~ {image_np.max()}") # 转换为PIL图像 pil_image = Image.fromarray(image_np) + print(f"PIL图像尺寸: {pil_image.size}") + print(f"PIL图像模式: {pil_image.mode}") # 转换为Base64 buffer = io.BytesIO() pil_image.save(buffer, format='PNG') + buffer_size = len(buffer.getvalue()) + print(f"PNG缓冲区大小: {buffer_size} bytes") + image_base64 = base64.b64encode(buffer.getvalue()).decode('utf-8') + base64_length = len(image_base64) + print(f"Base64编码长度: {base64_length}") + + # 检查图片大小是否超过限制(30MB) + if buffer_size > 30 * 1024 * 1024: + print(f"警告:图片大小 {buffer_size / 1024 / 1024:.2f}MB 可能超过API限制(30MB)") + + print(f"=== DEBUG: 图片转换完成 ===") return f"data:image/png;base64,{image_base64}" @@ -155,19 +177,48 @@ class VolcengineDoubaoSeedance: "content": content_list } + # 输出详细的请求信息用于调试 + print(f"=== DEBUG: 创建任务请求信息 ===") + print(f"请求URL: {self.base_url}") + print(f"请求Headers: {headers}") + print(f"请求Payload: {json.dumps(payload, indent=2, ensure_ascii=False)}") + print(f"================================") + try: response = requests.post(self.base_url, headers=headers, json=payload, timeout=30) + + # 输出详细的响应信息用于调试 + print(f"=== DEBUG: 响应信息 ===") + print(f"响应状态码: {response.status_code}") + print(f"响应Headers: {dict(response.headers)}") + + try: + response_json = response.json() + print(f"响应内容: {json.dumps(response_json, indent=2, ensure_ascii=False)}") + except: + print(f"响应内容(原始文本): {response.text}") + print(f"=====================") + response.raise_for_status() result = response.json() if "id" in result: + print(f"任务创建成功,任务ID: {result['id']}") return result["id"] else: - print(f"创建任务失败: {result}") + print(f"创建任务失败,响应中没有任务ID: {result}") return None + except requests.exceptions.HTTPError as e: + print(f"HTTP错误: {e}") + try: + error_detail = response.json() + print(f"错误详情: {json.dumps(error_detail, indent=2, ensure_ascii=False)}") + except: + print(f"错误详情(原始文本): {response.text}") + return None except Exception as e: - print(f"创建任务时发生错误: {str(e)}") + print(f"创建任务时发生其他错误: {str(e)}") return None def query_task(self, ark_api_key, task_id, max_retries=60, retry_interval=10): @@ -181,10 +232,19 @@ class VolcengineDoubaoSeedance: for attempt in range(max_retries): try: + print(f"查询任务URL: {query_url}") response = requests.get(query_url, headers=headers, timeout=30) + + # 输出查询响应的debug信息 + print(f"=== DEBUG: 查询任务响应 (尝试 {attempt + 1}) ===") + print(f"响应状态码: {response.status_code}") + response.raise_for_status() result = response.json() + print(f"查询响应内容: {json.dumps(result, indent=2, ensure_ascii=False)}") + print(f"=====================================") + status = result.get("status") print(f"查询任务 {task_id} 状态: {status} (尝试 {attempt + 1}/{max_retries})") @@ -197,12 +257,14 @@ class VolcengineDoubaoSeedance: return {"status": "success", "video_url": video_url, "result": result} else: print("任务成功但未找到视频URL") + print(f"完整响应内容: {json.dumps(result, indent=2, ensure_ascii=False)}") return {"status": "error", "message": "未找到视频URL"} elif status == "failed": error_info = result.get("error", {}) error_message = error_info.get("message", "任务失败") print(f"任务失败: {error_message}") + print(f"错误详情: {json.dumps(error_info, indent=2, ensure_ascii=False)}") return {"status": "error", "message": error_message} elif status == "cancelled": @@ -216,11 +278,24 @@ class VolcengineDoubaoSeedance: else: print(f"未知状态: {status}") + print(f"完整响应: {json.dumps(result, indent=2, ensure_ascii=False)}") time.sleep(retry_interval) continue + except requests.exceptions.HTTPError as e: + print(f"查询任务HTTP错误: {e}") + try: + error_detail = response.json() + print(f"查询错误详情: {json.dumps(error_detail, indent=2, ensure_ascii=False)}") + except: + print(f"查询错误详情(原始文本): {response.text}") + if attempt < max_retries - 1: + time.sleep(retry_interval) + continue + else: + return {"status": "error", "message": f"查询任务失败: {str(e)}"} except Exception as e: - print(f"查询任务时发生错误: {str(e)}") + print(f"查询任务时发生其他错误: {str(e)}") if attempt < max_retries - 1: time.sleep(retry_interval) continue @@ -295,8 +370,12 @@ class VolcengineDoubaoSeedance: if first_frame is not None or last_frame is not None: if first_frame is not None and last_frame is not None: print("检测到首尾帧图片,使用首尾帧图生视频模式") + print(f"首帧图片形状: {first_frame.shape}") + print(f"尾帧图片形状: {last_frame.shape}") + # 处理首帧图片 first_frame_base64 = self.image_to_base64(first_frame) + print(f"首帧图片Base64长度: {len(first_frame_base64)}") first_frame_content = { "type": "image_url", "image_url": { @@ -308,6 +387,7 @@ class VolcengineDoubaoSeedance: # 处理尾帧图片 last_frame_base64 = self.image_to_base64(last_frame) + print(f"尾帧图片Base64长度: {len(last_frame_base64)}") last_frame_content = { "type": "image_url", "image_url": { @@ -319,7 +399,10 @@ class VolcengineDoubaoSeedance: elif first_frame is not None: print("检测到首帧图片,使用图生视频模式") + print(f"首帧图片形状: {first_frame.shape}") + first_frame_base64 = self.image_to_base64(first_frame) + print(f"首帧图片Base64长度: {len(first_frame_base64)}") first_frame_content = { "type": "image_url", "image_url": { @@ -331,7 +414,10 @@ class VolcengineDoubaoSeedance: elif last_frame is not None: print("检测到尾帧图片,使用图生视频模式") + print(f"尾帧图片形状: {last_frame.shape}") + last_frame_base64 = self.image_to_base64(last_frame) + print(f"尾帧图片Base64长度: {len(last_frame_base64)}") last_frame_content = { "type": "image_url", "image_url": {