不用翻墙、不用 Hugging Face、不用 Google。同样的 diffusers 代码,权重改从魔搭社区(ModelScope)下载——国内直连、速度快。文生图用可图 Kolors,图生视频用通义万相 Wan 2.2 或 CogVideoX,提示词支持中文。No VPN, no Hugging Face, no Google. The same diffusers code — you just download the weights from ModelScope (魔搭), China's domestic model hub, instead. Text-to-image with Kolors, image-to-video with Wan 2.2 or CogVideoX, Chinese prompts supported.
在中国大陆,huggingface.co 和 Google 托管的权重通常无法直连。但模型本身没有国界——同样的 .safetensors 权重在 魔搭社区 ModelScope(阿里达摩院运营,相当于国内版 Hugging Face)上一份不少地重新托管,而且可图、混元、通义万相、CogVideoX 这些国产模型本来就首发在魔搭。你写的 diffusers 代码一行都不用改,只是把“从哪里下载权重”从 Hugging Face 换成魔搭:In mainland China, huggingface.co and Google-hosted weights are usually unreachable. But the models themselves have no borders — the same .safetensors weights are re-hosted on ModelScope (魔搭), run by Alibaba's DAMO Academy as China's equivalent of Hugging Face — and China-origin models (Kolors, Hunyuan, Wan, CogVideoX) launch there first. Your diffusers code doesn't change at all; you only swap where the weights come from:
| 墙外 / 国际版Blocked / international | 国内直连的对应China-accessible equivalent |
|---|---|
huggingface.co | modelscope.cn (魔搭社区)(ModelScope) |
pip install huggingface_hub · hf download | pip install modelscope · modelscope download |
from huggingface_hub import snapshot_download | from modelscope import snapshot_download |
| PyPI(pypi.org,常超时)PyPI (pypi.org, often times out) | 阿里云 / 清华 pip 镜像Aliyun / Tsinghua pip mirror |
diffusers 的 pipelinepipelines | 完全相同——pipeline 代码不变identical — the pipeline code is unchanged |
snapshot_download(...) → from_pretrained(本地路径) → pipe(...) → .save(),你就能在国内、无需翻墙地把这些模型全部跑起来——纯 Python,没有界面挡路。Learn snapshot_download(...) → from_pretrained(local_path) → pipe(...) → .save() and you can run all of these from inside China with no VPN — plain Python, no UI in the way.
需要 Python 3.10+。用阿里云 pip 镜像装包,避免 PyPI 超时。modelscope 负责下载,diffusers 负责推理。You need Python 3.10+. Install through the Aliyun pip mirror so PyPI doesn't time out. modelscope does the downloading, diffusers does the inference.
# 干净的虚拟环境 / a clean virtual environment
python -m venv .venv
# Windows: .venv\Scripts\activate · macOS/Linux: source .venv/bin/activate
# 走阿里云镜像安装,速度快 / install via Aliyun mirror (fast in China)
pip install -i https://mirrors.aliyun.com/pypi/simple/ \
modelscope diffusers transformers accelerate safetensors sentencepiece
pip install -i https://mirrors.aliyun.com/pypi/simple/ torch
pip install -i https://mirrors.aliyun.com/pypi/simple/ imageio imageio-ffmpeg pillow # 视频导出用 / for saving video
~/.cache/modelscope/hub(Windows 在 C:\Users\<你>\.cache\modelscope\hub)。想换位置就设环境变量 MODELSCOPE_CACHE,或下载时用 --local_dir 指定目录。删掉该目录即可释放空间。ModelScope caches weights to ~/.cache/modelscope/hub (on Windows, C:\Users\<you>\.cache\modelscope\hub). Change it with the MODELSCOPE_CACHE env var, or pass --local_dir on download. Delete that folder to free space.
ddtraveller/diffusers-cpu 镜像在运行时仍会去 Hugging Face 拉权重——在墙内会卡死。本页改用魔搭下载,绕开这个问题。The ddtraveller/diffusers-cpu image in the international guide still pulls weights from Hugging Face at runtime, which hangs behind the GFW. This page downloads from ModelScope instead, sidestepping that.
两种方法下载到同一个缓存,脚本都能找到。关键点:snapshot_download() 返回一个本地路径,把这个路径喂给 diffusers 的 from_pretrained() 即可——和直连 Hugging Face 的写法只差这一步。下面以可图 Kolors 为例。Both methods write to the same cache, so your script finds the files either way. The key: snapshot_download() returns a local path — hand that path to diffusers' from_pretrained(). That one line is the only difference from the Hugging Face version. Example: Kolors.
snapshot_downloadMethod A — snapshot_download in Pythonfrom modelscope import snapshot_download
# 从魔搭下载,返回本地目录 / downloads from ModelScope, returns a local dir
model_dir = snapshot_download("Kwai-Kolors/Kolors-diffusers")
print(model_dir) # 例如 / e.g. ~/.cache/modelscope/hub/Kwai-Kolors/Kolors-diffusers
modelscope downloadMethod B — the modelscope CLI# 下载到缓存 / download into the cache
modelscope download --model Kwai-Kolors/Kolors-diffusers
# 或下载到看得见的文件夹 / or into a folder you can see
modelscope download --model Kwai-Kolors/Kolors-diffusers --local_dir ./Kolors
在 modelscope.cn/models 搜模型名就能拿到准确的 组织/模型 id。下一节会列出本页用到的全部 id。Search a model name at modelscope.cn/models to get its exact org/model id. The next sections list every id used here.
可图 Kolors(快手开源)是一个中英双语文生图模型,中文提示词原生支持,中文字形渲染尤其出色。它用 EulerDiscrete 调度器,推荐 guidance_scale=5.0、num_inference_steps=50。注意:Kolors 自带一个 ChatGLM 文本编码器,模型较大(约 10 GB+),建议用 GPU;CPU 能跑但很慢。Kolors (open-sourced by Kuaishou) is a bilingual CN/EN text-to-image model with native Chinese prompt support and excellent Chinese-glyph rendering. It uses the EulerDiscrete scheduler; the recommended settings are guidance_scale=5.0 and num_inference_steps=50. Note: Kolors bundles a ChatGLM text encoder and is large (~10 GB+), so a GPU is recommended; CPU works but is slow.
# t2i.py — 文生图 / text to image, weights from ModelScope
import torch
from diffusers import KolorsPipeline
from modelscope import snapshot_download
# 选设备 / pick a device: NVIDIA → cuda, 苹果芯片 Apple Silicon → mps, 否则 cpu
device = "cuda" if torch.cuda.is_available() \
else "mps" if torch.backends.mps.is_available() else "cpu"
dtype = torch.float16 if device != "cpu" else torch.float32
# 1 — 从魔搭下载(首次下载,之后走缓存)/ download from ModelScope (cached after first run)
model_dir = snapshot_download("Kwai-Kolors/Kolors-diffusers")
# 2 — 加载 pipeline / load the pipeline from the LOCAL path
pipe = KolorsPipeline.from_pretrained(
model_dir, torch_dtype=dtype, variant="fp16",
).to(device)
pipe.enable_attention_slicing() # 省内存 / less RAM
# 3 — 中文提示词直接可用 / Chinese prompt works directly
image = pipe(
prompt="清晨薄雾中的清迈双龙寺,金色阳光,兰纳建筑,高细节",
negative_prompt="模糊, 变形, 低质量",
guidance_scale=5.0, # Kolors 推荐 / recommended
num_inference_steps=50, # Kolors 推荐 / recommended
generator=torch.Generator(device).manual_seed(42), # 可复现 / reproducible
).images[0]
image.save("temple.png")
print("saved temple.png")
python t2i.py # 首次下载约 10 GB / first run downloads ~10 GB, then reuses the cache
不同模型之间,要改的只是 snapshot_download() 里的魔搭 id、对应的 pipeline 类,以及步数 / guidance。Between models, you change only the ModelScope id in snapshot_download(), the matching pipeline class, and the step/guidance settings.
| 模型(魔搭 id)Model (ModelScope id) | Pipeline 类 / 设置Pipeline / settings | 适用于Use it for |
|---|---|---|
Kwai-Kolors/Kolors-diffusers可图 · 快手Kolors · Kuaishou | KolorsPipeline50 步,CFG 550 steps, CFG 5 | 中英双语,文字渲染强——上面的默认。Bilingual, strong text rendering — the default above. |
Xorbits/HunyuanDiT-v1.2-Diffusers-Distilled混元 · 腾讯(蒸馏版)Hunyuan-DiT · Tencent (distilled) | HunyuanDiTPipeline25 步25 steps | 中英双语,蒸馏版步数更少、更轻——CPU 更友好。Bilingual, distilled to fewer steps — friendlier on CPU. |
Wan-AI/Wan2.2-TI2V-5B-Diffusers通义万相 · 阿里(图也能转文)Wan2.2 · Alibaba (also t2i) | WanPipeline | 同一模型也做文生图;主用途见第 4 节图生视频。Same model also does text-to-image; mainly for i2v in §4. |
把第 3 节生成的 temple.png 喂给图生视频模型,让它“动起来”。两个国产开源选择:通义万相 Wan2.2-TI2V-5B(阿里,中文提示词原生支持,720P)和 CogVideoX-5b-I2V(智谱,提示词仅英文,需把中文翻成英文)。Feed the temple.png from §3 to an image-to-video model to make it move. Two open-source Chinese options: Wan2.2-TI2V-5B (Alibaba, native Chinese prompts, 720P) and CogVideoX-5b-I2V (Zhipu, English prompts only — translate Chinese first).
# i2v.py — 图生视频 / image to video (Wan 2.2, Chinese prompts OK)
import torch
from diffusers import WanImageToVideoPipeline
from diffusers.utils import load_image, export_to_video
from modelscope import snapshot_download
model_dir = snapshot_download("Wan-AI/Wan2.2-TI2V-5B-Diffusers")
pipe = WanImageToVideoPipeline.from_pretrained(model_dir, torch_dtype=torch.bfloat16)
pipe.to("cuda") # 视频强烈建议 GPU / video really wants a GPU
pipe.enable_model_cpu_offload() # 显存不够时省显存 / spill to RAM if VRAM is tight
image = load_image("temple.png")
frames = pipe(
image=image,
prompt="云雾在山间缓缓流动,清晨光线,镜头缓慢推进", # 中文 OK / Chinese OK
height=704, width=1280, num_frames=121, # 见模型卡 / see model card
num_inference_steps=50,
).frames[0]
export_to_video(frames, "temple.mp4", fps=24)
print("saved temple.mp4")
sd-turbo(极小、CPU 几秒出图)不同,这些视频模型是几十亿参数的大模型。Wan2.2-TI2V-5B 在一张消费级 4090 上生成 5 秒 720P 视频约需 9 分钟;放到纯 CPU 笔记本上基本不现实,苹果芯片(MPS)能尝试但很慢、可能爆内存。有 N 卡用 N 卡,没有就把视频这步放到 GPU 服务器上跑,文生图那步仍可本地完成。Unlike the tiny sd-turbo in the international guide (seconds on CPU), these are multi-billion-parameter video models. Wan2.2-TI2V-5B makes a 5 s 720P clip in about 9 minutes on a consumer 4090; on a CPU-only laptop it's impractical, and Apple Silicon (MPS) can attempt it but is slow and may run out of memory. Use an NVIDIA GPU if you have one — otherwise run just this step on a GPU box and keep text-to-image local.
ZhipuAI/CogVideoX-5b-I2V,pipeline 用 CogVideoXImageToVideoPipeline,torch_dtype=torch.bfloat16。显存小就开 pipe.enable_sequential_cpu_offload() 和 pipe.vae.enable_tiling()。默认 49 帧、fps=8。提示词只支持英文,中文先翻译成英文。ModelScope id ZhipuAI/CogVideoX-5b-I2V, pipeline CogVideoXImageToVideoPipeline, torch_dtype=torch.bfloat16. For low VRAM, enable pipe.enable_sequential_cpu_offload() and pipe.vae.enable_tiling(). Defaults to 49 frames at fps=8. English prompts only — translate Chinese first.
.md 文件和图片Reference many .md files & images in one render真实项目不会把提示词写死。一部卡通剧集把画风、角色和每个镜头分别放在不同的 .md 文件里,并用参考 .png 锁定真实外观——一本「设定集」。渲染时,脚本会把它们全部读入、把文本拼成一条提示词、并把图片喂进 pipeline。这就是让第 800 帧与第 1 帧保持一致的全部诀窍。可图 Kolors 与通义万相 Wan 都原生支持中文,所以整本设定集都能用中文写。(设定集如何撰写见 准备一次,永远开拍。)Real projects don't hard-code the prompt string. A cartoon series keeps its look, its characters, and each shot in separate .md files, and locks the actual appearance in reference .pngs — a "show bible". At render time a script reads them all, concatenates the text into one prompt, and feeds the images into the pipeline. That is the whole trick to keeping frame #800 on-model with frame #1. Both Kolors and Wan accept Chinese natively, so the whole bible can be written in Chinese. (See Prepare Once, Animate Forever for how the bible is authored.)
.md 文件的文本拼接起来A — Concatenate the text from several .md files每个设定集文件在 # 标题 行之后就是普通 YAML,所以一个极小的加载函数就能读取任意一个。场景文件指明用哪些角色和地点;脚本把这些名字解析成锁定的 token,再把一切拼成一条 prompt。style.md 里的 model 字段填魔搭 id,照样用 snapshot_download 下载。多一个依赖:pip install pyyaml。Each bible file is plain YAML after its # title line, so one tiny loader reads any of them. The scene names which characters and location to use; the script resolves those names to the locked tokens and joins everything into a single prompt. The model field in style.md is a ModelScope id, downloaded the same way with snapshot_download. One extra dependency: pip install pyyaml.
# render_scene.py — 用多个 .md 文件拼出一条提示词再渲染 / assemble ONE prompt from many .md files
import yaml, torch
from pathlib import Path
from diffusers import KolorsPipeline
from modelscope import snapshot_download
def fields(path):
# 去掉 '# 标题' 行后就是 YAML / a .md bible file is YAML once you drop its '# title' line
body = "".join(l for l in open(path, encoding="utf-8") if not l.startswith("#"))
return yaml.safe_load(body)
style = fields("style.md") # render_tokens, negative, model(魔搭 id)
chars = {p.stem: fields(p) for p in Path("characters").glob("*.md")}
scene = fields("scenes/scene_01.md") # cast, action, camera, motion
# 把场景点名的每个角色解析成各自锁定的 look_tokens / resolve scene.cast -> locked look_tokens
looks = [chars[name]["look_tokens"] for name in scene["cast"]]
prompt = ",".join(looks + [scene["action"], scene["camera"], style["render_tokens"]])
model_dir = snapshot_download(style["model"]) # 例如 Kwai-Kolors/Kolors-diffusers
pipe = KolorsPipeline.from_pretrained(model_dir, torch_dtype=torch.float16).to("cuda")
image = pipe(
prompt=prompt,
negative_prompt=style["negative"],
num_inference_steps=50, guidance_scale=5.0, # Kolors 推荐 / recommended
).images[0]
Path("renders").mkdir(exist_ok=True)
image.save("renders/scene_01.png")
cast: [ploy],而不是 40 个字的外观描述。在 characters/ploy.md 里改一次发夹,下次渲染时每个用到她的场景都会继承——不必在上百条提示词里查找替换。The scene file says cast: [ploy], not a 40-word description. Change the hairpin once in characters/ploy.md and every scene that lists her inherits it on the next render — no find-and-replace across hundreds of prompts.
文字会走样,图片不会。要锁定真实画作——角色转面图、场景背景——就把它们作为像素传入。可图自带 Kolors IP-Adapter(魔搭 id Kwai-Kolors/Kolors-IP-Adapter-Plus),它需要显式加载一个 image_encoder;给 ip_adapter_image 传一个列表就能同时参考多张图。Words drift; pictures don't. To pin the actual drawing — the character turnaround, the location backdrop — pass them as pixels. Kolors has its own IP-Adapter (ModelScope id Kwai-Kolors/Kolors-IP-Adapter-Plus), which needs an explicit image_encoder; pass a list to ip_adapter_image to reference several images at once.
# 用图片当参考,而不只是文字 / reference the actual PICTURES, not just words
from transformers import CLIPVisionModelWithProjection
from diffusers.utils import load_image
ipa = snapshot_download("Kwai-Kolors/Kolors-IP-Adapter-Plus") # 参考图适配器 / the IP-Adapter
image_encoder = CLIPVisionModelWithProjection.from_pretrained(
ipa, subfolder="image_encoder", torch_dtype=torch.float16)
pipe = KolorsPipeline.from_pretrained(
model_dir, image_encoder=image_encoder, torch_dtype=torch.float16).to("cuda")
pipe.load_ip_adapter(ipa, subfolder="", weight_name="ip_adapter_plus_general.safetensors")
pipe.set_ip_adapter_scale(0.5) # 参考强度 / how strongly the refs steer it
image = pipe(
prompt=prompt, negative_prompt=style["negative"],
ip_adapter_image=[ # 传一个列表 = 同时参考多张图 / a LIST = several refs at once
load_image(chars["ploy"]["refs"][0]), # characters/ploy_turnaround.png
load_image("locations/village_lane_wide.png"),
],
num_inference_steps=50, guidance_scale=5.0,
).images[0]
refs: 列表直接来自 characters/ploy.md——YAML 加载器已解析好,chars["ploy"]["refs"][0] 就是转面图路径。若想分别独立控制「人物 vs 背景」(每个适配器单独设权重),SDXL 系可加载多个 IP-Adapter——做法见国际版 diffusers 模型指南 第 4 节。只想对单张图轻度重绘,则用 KolorsImg2ImgPipeline 配 image= 和 strength=。The refs: list comes straight from characters/ploy.md — already parsed by the YAML loader, so chars["ploy"]["refs"][0] is the turnaround path. To control "character vs background" independently (a separate scale per adapter), SDXL-family pipelines can load multiple IP-Adapters — see §4 of the international guide. For a light redraw of a single still, use KolorsImg2ImgPipeline with image= + strength=.
因为你刚渲染的静帧本身就是所有参考合成的一帧,让它动起来无需新的参考——这张合成 PNG 直接成为视频的第一帧。而通义万相 Wan 接收文本提示词,所以场景的 motion: 字段可原样当作中文运动提示词。Because the still you just rendered already is every reference composed into one frame, animating it needs no new references — the composed PNG becomes the video's first frame. And since Wan takes a text prompt, the scene's motion: field can be used directly as the (Chinese) motion prompt.
# 合成好的静帧就是视频的参考 / the composed still IS the video's reference (frame 0)
from diffusers import WanImageToVideoPipeline
from diffusers.utils import load_image, export_to_video
vdir = snapshot_download("Wan-AI/Wan2.2-TI2V-5B-Diffusers")
pipe_i2v = WanImageToVideoPipeline.from_pretrained(vdir, torch_dtype=torch.bfloat16).to("cuda")
seed = load_image("renders/scene_01.png")
frames = pipe_i2v(
image=seed,
prompt=scene["motion"], # 场景的 motion: 字段直接当中文运动提示词 / the scene's motion: line, Chinese OK
num_frames=121, num_inference_steps=50,
).frames[0]
export_to_video(frames, "renders/scene_01.mp4", fps=24)
| 来源文件Source file | 字段Field | 进入Goes into |
|---|---|---|
style.md | model | snapshot_download(...) 魔搭 idModelScope id |
style.md | render_tokens | 附加到每条appended to every prompt |
style.md | negative | negative_prompt= |
characters/*.md | look_tokens | 由resolved from scene.cast 解析进into prompt |
characters/*.md | refs (png) | ip_adapter_image= / 初始图init image= |
locations/*.png | — | ip_adapter_image= / i2v 第一帧i2v seed frame |
scenes/scene_NN.md | action, camera | prompt |
scenes/scene_NN.md | motion | Wan i2v 提示词(中文原生)Wan i2v prompt (native Chinese) |
scenes/scene_NN.md | seconds | 片段时长 /clip length / num_frames |
scene_NN.md,运行脚本。提示词永不重打、参考永不重述——.md 文件和 .png 就是输入,pipeline 调用每次都一样。这正是「在界面里探索」与「交付一部剧集」的分界线。Once the loader exists, rendering a new shot is: write a short scene_NN.md, run the script. No prompt is ever retyped, no reference re-described — the .md files and .pngs are the inputs, and the pipeline call is the same every time. That's the line between "exploring in a UI" and "shipping a series".
| 调用Call | 作用What it does |
|---|---|
pipe.enable_attention_slicing() | 分块算注意力——单项最省内存。Attention in chunks — biggest single RAM saver. |
pipe.vae.enable_tiling() | 分块解码画面,视频模型尤其需要。Decodes frames in tiles — key for video. |
pipe.enable_model_cpu_offload() | GPU 用——空闲子模型放回内存,按需搬上显存,省 VRAM。GPU only — idle sub-models stay in RAM, moved to VRAM just in time. |
pipe.enable_sequential_cpu_offload() | 更激进的换出,显存极少时用(更慢)。More aggressive offload for very low VRAM (slower). |
num_inference_steps ↓ | 步数越少越快;蒸馏 / Turbo 模型为此而生。Fewer steps = faster; distilled/turbo models are built for it. |
hf-mirror.com:export HF_ENDPOINT=https://hf-mirror.com(Windows PowerShell:$env:HF_ENDPOINT="https://hf-mirror.com")。Some third-party code hard-codes a Hugging Face download (e.g. a tokenizer). One env var reroutes HF requests to the domestic mirror hf-mirror.com:export HF_ENDPOINT=https://hf-mirror.com (Windows PowerShell: $env:HF_ENDPOINT="https://hf-mirror.com").
| 文生图Text → image | 图生视频Image → video | |
|---|---|---|
| 下载来源Download from | 魔搭 ModelScope — snapshot_download("组织/模型")ModelScope — snapshot_download("org/model") | |
| Pipeline | KolorsPipeline | WanImageToVideoPipeline |
| 推荐模型Model | Kwai-Kolors/Kolors-diffusers | Wan-AI/Wan2.2-TI2V-5B-Diffusers |
| 中文提示词Chinese prompts | 原生支持native | Wan 原生 / CogVideoX 需翻译Wan native / CogVideoX needs translation |
| 硬件Hardware | GPU 佳,CPU 可(慢)GPU best, CPU ok (slow) | 需要 GPUneeds a GPU |
diffusers 的代码一行不改,国内本地就能跑文生图与图生视频。The firewall blocks downloads, not models. Swap the download source from Hugging Face to ModelScope and the diffusers code is unchanged — text-to-image and image-to-video run locally, inside China.