添加项目目录结构

This commit is contained in:
xie236393
2025-02-26 21:42:39 +08:00
parent 78223aaa1a
commit 3d2b47209b
9 changed files with 640 additions and 0 deletions
View File
+30
View File
@@ -0,0 +1,30 @@
# GitHub 仓库设置指南
## 自动设置(推荐)
1. 双击运行 `setup_github.bat`
2. 按照向导提示操作即可
## 手动设置
如果自动设置失败,您可以:
1. 访问 https://github.com/settings/tokens/new
2. 创建新的访问令牌:
- 名称:WanAPI
- 有效期:永不过期
- 权限:勾选 repo
3. 复制生成的token
4. 编辑 config.json:
```json
{
"GITHUB_TOKEN": "你的token",
"GITHUB_REPO": "你的用户名/仓库名",
"GITHUB_BRANCH": "main"
}
```
## 常见问题
1. Token无效
- 检查是否正确复制
- 确保有 repo 权限
2. 仓库创建失败
- 检查仓库名是否已存在
- 确保token权限正确
View File
+10
View File
@@ -0,0 +1,10 @@
# 避免在顶层导入,改为按需导入
def get_image_processor():
from .image_processor import tensor_to_pil, validate_image_url
return tensor_to_pil, validate_image_url
def get_github_client():
from .github_client import GitHubUploader
return GitHubUploader
print("✅ utils模块已加载")
+91
View File
@@ -0,0 +1,91 @@
import os
import time
import base64
import requests
from pathlib import Path
class GitHubUploader:
def __init__(self, repo, branch, token):
self.repo = repo
self.branch = branch
self.headers = {
"Authorization": f"token {token}",
"Accept": "application/vnd.github.v3+json"
}
def _validate_permissions(self):
"""验证Token权限"""
try:
# 验证Token
auth_check = requests.get(
"https://api.github.com/user",
headers=self.headers,
timeout=5
)
if auth_check.status_code != 200:
print(f"❌ Token验证失败: {auth_check.json().get('message')}")
return False
# 验证仓库访问权限
repo_check = requests.get(
f"https://api.github.com/repos/{self.repo}",
headers=self.headers
)
if repo_check.status_code != 200:
print(f"❌ 仓库访问失败: {repo_check.json().get('message')}")
return False
return True
except Exception as e:
print(f"❌ 权限验证失败: {str(e)}")
return False
def upload(self, file_path):
"""上传文件到GitHub"""
if not self._validate_permissions():
return None
try:
# 读取文件内容
with open(file_path, 'rb') as f:
content = base64.b64encode(f.read()).decode('utf-8')
# 生成文件名
filename = f"wanx_{int(time.time())}.jpg"
# 上传到GitHub
response = requests.put(
f"https://api.github.com/repos/{self.repo}/contents/images/{filename}",
headers=self.headers,
json={
"message": "Auto-upload from ComfyUI",
"content": content,
"branch": self.branch
},
timeout=10
)
# 处理响应
if response.status_code == 201:
# 返回原始 GitHub URL 而不是 CDN URL
return f"https://raw.githubusercontent.com/{self.repo}/{self.branch}/images/{filename}"
elif response.status_code == 403:
error_msg = response.json().get('message', '')
if 'resource is not accessible' in error_msg:
print("""❌ 权限不足,请检查:
1. Token是否具有repo权限
2. 仓库是否设置为私有
3. Token是否已过期""")
return None
print(f"❌ 上传失败: {response.status_code} - {response.text}")
return None
except Exception as e:
print(f"❌ 上传失败: {str(e)}")
import traceback
print(f"🔍 详细错误:\n{traceback.format_exc()}")
return None
+37
View File
@@ -0,0 +1,37 @@
import torch
import numpy as np
from PIL import Image
import traceback
def tensor_to_pil(tensor):
"""将图像张量转换为PIL图像(兼容4D/3D张量)"""
try:
# 转换为CPU张量
image = tensor.cpu().detach()
# 处理不同维度
if len(image.shape) == 4:
image = image[0] # 取批次中第一张
if len(image.shape) == 3 and image.shape[0] in [1, 3, 4]:
image = image.permute(1, 2, 0) # CHW -> HWC
# 转换为numpy数组
image = (image * 255).clamp(0, 255).byte().numpy()
# 处理通道数
if image.shape[-1] == 1:
image = np.concatenate([image]*3, axis=-1)
elif image.shape[-1] == 4:
image = image[..., :3] # 移除Alpha通道
return Image.fromarray(image)
except Exception as e:
print(f"❌ 图像处理失败: {traceback.format_exc()}")
return None
def validate_image_url(url):
"""验证图片URL格式"""
if not url.startswith(("http://", "https://")):
raise ValueError("图片URL必须以http/https开头")
if "cdn.jsdelivr.net" not in url and "aliyuncs.com" not in url:
print("⚠️ 警告:非受信图片源,可能影响生成稳定性")
+7
View File
@@ -0,0 +1,7 @@
✅ utils模块已加载
# 在ComfyUI的Python控制台中测试
from Comfyui_wan_api.utils import image_processor, github_client
print("图像处理器模块:", dir(image_processor))
print("GitHub客户端:", dir(github_client))
图像处理器模块: ['tensor_to_pil', 'validate_image_url']
GitHub客户端: ['GitHubUploader']
View File
+465
View File
@@ -0,0 +1,465 @@
{
"last_node_id": 7,
"last_link_id": 6,
"nodes": [
{
"id": 3,
"type": "easy showAnything",
"pos": [
-1191.599365234375,
2210.471435546875
],
"size": [
210,
76
],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{
"name": "anything",
"type": "*",
"link": 2,
"shape": 7,
"label": "输入任何"
}
],
"outputs": [
{
"name": "output",
"type": "*",
"links": [
4
],
"slot_index": 0
}
],
"properties": {
"Node name for S&R": "easy showAnything"
},
"widgets_values": [
"https://raw.githubusercontent.com/penposs/image/main/images/wanx_1740562663.jpg"
]
},
{
"id": 5,
"type": "WanAPIImageToVideo",
"pos": [
-877.1105346679688,
2040.0242919921875
],
"size": [
400,
226
],
"flags": {},
"order": 3,
"mode": 0,
"inputs": [
{
"name": "image_url",
"type": "STRING",
"link": 4,
"widget": {
"name": "image_url"
},
"label": "image_url"
}
],
"outputs": [
{
"name": "video_url",
"type": "STRING",
"links": [
5,
6
],
"slot_index": 0,
"label": "video_url"
}
],
"properties": {
"Node name for S&R": "WanAPIImageToVideo"
},
"widgets_values": [
"",
"wanx2.1-i2v-plus",
5,
"",
"动漫风格,镜头环绕,女人跳起挥剑,剑光闪耀,黑雾傀儡碎裂成无数碎片,碎片缓缓飘落,闪闪发光,头发衣服飘动。",
896448203,
"randomize",
"False"
]
},
{
"id": 6,
"type": "ShowText|pysssss",
"pos": [
-851.0746459960938,
2318.310302734375
],
"size": [
315,
476
],
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{
"name": "text",
"type": "STRING",
"link": 5,
"widget": {
"name": "text"
},
"label": "文本"
}
],
"outputs": [
{
"name": "STRING",
"type": "STRING",
"links": null,
"shape": 6,
"label": "字符串"
}
],
"properties": {
"Node name for S&R": "ShowText|pysssss"
},
"widgets_values": [
"",
"https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/51/20250226/72e40b15/a8624ac4-cdf8-433b-9803-d273f99638f1.mp4?Expires=1740648892&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=qkCtiHjGJXSoHrHqmtV%2FRqCHziE%3D"
]
},
{
"id": 7,
"type": "VHS_LoadVideoPath",
"pos": [
-441.0176086425781,
2044.71484375
],
"size": [
231.8896484375,
238
],
"flags": {},
"order": 5,
"mode": 0,
"inputs": [
{
"name": "meta_batch",
"type": "VHS_BatchManager",
"link": null,
"shape": 7,
"label": "批次管理"
},
{
"name": "vae",
"type": "VAE",
"link": null,
"shape": 7,
"label": "vae"
},
{
"name": "video",
"type": "STRING",
"link": 6,
"widget": {
"name": "video"
},
"label": "视频"
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
3
],
"slot_index": 0,
"label": "图像"
},
{
"name": "frame_count",
"type": "INT",
"links": [],
"slot_index": 1,
"label": "帧计数"
},
{
"name": "audio",
"type": "AUDIO",
"links": null,
"label": "音频"
},
{
"name": "video_info",
"type": "VHS_VIDEOINFO",
"links": [],
"slot_index": 3,
"label": "视频信息"
}
],
"properties": {
"Node name for S&R": "VHS_LoadVideoPath"
},
"widgets_values": {
"video": "https://p1.a.kwimgs.com/bs2/upload-ylab-stunt/special-effect/output/HB1_PROD_ai_web_46554461/-2878350957757294165/output.mp4",
"force_rate": 0,
"force_size": "Disabled",
"custom_width": 512,
"custom_height": 512,
"frame_load_cap": 0,
"skip_first_frames": 0,
"select_every_nth": 1,
"videopreview": {
"hidden": false,
"paused": false,
"params": {
"frame_load_cap": 0,
"skip_first_frames": 0,
"force_rate": 0,
"filename": "https://p1.a.kwimgs.com/bs2/upload-ylab-stunt/special-effect/output/HB1_PROD_ai_web_46554461/-2878350957757294165/output.mp4",
"type": "path",
"format": "video/mp4",
"select_every_nth": 1
},
"muted": false
}
}
},
{
"id": 4,
"type": "VHS_VideoCombine",
"pos": [
-143.3603057861328,
2037.040771484375
],
"size": [
247.27825927734375,
657.9598999023438
],
"flags": {},
"order": 6,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 3,
"label": "图像"
},
{
"name": "audio",
"type": "AUDIO",
"link": null,
"shape": 7,
"label": "音频"
},
{
"name": "meta_batch",
"type": "VHS_BatchManager",
"link": null,
"shape": 7,
"label": "批次管理"
},
{
"name": "vae",
"type": "VAE",
"link": null,
"shape": 7,
"label": "vae"
}
],
"outputs": [
{
"name": "Filenames",
"type": "VHS_FILENAMES",
"links": [],
"slot_index": 0,
"label": "文件名"
}
],
"properties": {
"Node name for S&R": "VHS_VideoCombine"
},
"widgets_values": {
"frame_rate": 30,
"loop_count": 0,
"filename_prefix": "wan/test",
"format": "video/h264-mp4",
"pix_fmt": "yuv420p",
"crf": 19,
"save_metadata": true,
"pingpong": false,
"save_output": true,
"videopreview": {
"hidden": false,
"paused": false,
"params": {
"filename": "test_00002.mp4",
"subfolder": "wan",
"type": "output",
"format": "video/h264-mp4",
"frame_rate": 30,
"workflow": "test_00002.png",
"fullpath": "I:\\ComfyUI_windows_portable\\ComfyUI\\output\\wan\\test_00002.mp4"
},
"muted": false
}
}
},
{
"id": 1,
"type": "LoadImage",
"pos": [
-1545.814208984375,
1985.2684326171875
],
"size": [
315,
314
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
1
],
"slot_index": 0,
"label": "图像"
},
{
"name": "MASK",
"type": "MASK",
"links": null,
"label": "遮罩"
}
],
"properties": {
"Node name for S&R": "LoadImage"
},
"widgets_values": [
"46.jpg",
"image"
]
},
{
"id": 2,
"type": "WanAPIImageUploader",
"pos": [
-1187.8138427734375,
1991.5435791015625
],
"size": [
231.67236328125,
130
],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 1,
"label": "images"
}
],
"outputs": [
{
"name": "STRING",
"type": "STRING",
"links": [
2
],
"slot_index": 0,
"label": "STRING"
}
],
"properties": {
"Node name for S&R": "WanAPIImageUploader"
},
"widgets_values": [
"GitHub",
"",
"main",
""
]
}
],
"links": [
[
1,
1,
0,
2,
0,
"IMAGE"
],
[
2,
2,
0,
3,
0,
"*"
],
[
3,
7,
0,
4,
0,
"IMAGE"
],
[
4,
3,
0,
5,
0,
"STRING"
],
[
5,
5,
0,
6,
0,
"STRING"
],
[
6,
5,
0,
7,
2,
"STRING"
]
],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 1,
"offset": [
1584.863449468461,
-1739.5341228629436
]
},
"groupNodes": {},
"ue_links": []
},
"version": 0.4
}