
Alicloud Ai Video Wan Video
- 307 installs
- 396 repo stars
- Updated July 18, 2026
- cinience/alicloud-skills
alicloud-ai-video-wan-video is a Claude Code skill that integrates Alibaba Cloud WAN text and prompt-to-video generation APIs into agents, backends, and media products for developers needing managed cloud video creation.
About
alicloud-ai-video-wan-video is an Alibaba Cloud skill from cinience/alicloud-skills for wiring WAN model text-to-video and prompt-to-video generation into application backends and AI agents. It targets developers building media features who want managed cloud video APIs instead of self-hosted diffusion pipelines. Use it when an agent or service must submit generation prompts, handle asynchronous video jobs, and return hosted video assets through Alibaba Cloud's WAN video product. The skill fits products that combine LLM prompt orchestration with managed media output where operational overhead of custom GPU infrastructure is undesirable.
- WAN video generation API setup
- Prompt and parameter configuration
- Async job lifecycle handling
- Output download and storage
- Agent tool integration patterns
Alicloud Ai Video Wan Video by the numbers
- 307 all-time installs (skills.sh)
- Ranked #510 of 1,335 Generative Media skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/cinience/alicloud-skills --skill alicloud-ai-video-wan-videoAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 307 |
|---|---|
| repo stars | ★ 396 |
| Last updated | July 18, 2026 |
| Repository | cinience/alicloud-skills ↗ |
How do you integrate Alibaba Cloud WAN video generation?
Integrate Alibaba Cloud WAN text or prompt-to-video generation into agents, backends, or media products that need managed cloud video creation APIs.
Who is it for?
Backend and AI engineers on Alibaba Cloud who need managed WAN text-to-video APIs inside agents, microservices, or media products.
Skip if: Teams requiring fully offline or self-hosted video models with no Alibaba Cloud account or WAN service access.
When should I use this skill?
User mentions Alibaba Cloud WAN video, prompt-to-video APIs, or integrating managed AI video generation into an agent backend.
What you get
WAN video API integrations, prompt-to-video job handlers, and cloud-hosted generated video assets in agent or backend services.
- WAN video API client integration
- prompt-to-video job handlers
- hosted video asset URLs
Files
Category: provider
Model Studio Wan Video
Validation
mkdir -p output/alicloud-ai-video-wan-video
python -m py_compile skills/ai/video/alicloud-ai-video-wan-video/scripts/generate_video.py && echo "py_compile_ok" > output/alicloud-ai-video-wan-video/validate.txtPass criteria: command exits 0 and output/alicloud-ai-video-wan-video/validate.txt is generated.
Output And Evidence
- Save task IDs, polling responses, and final video URLs to
output/alicloud-ai-video-wan-video/. - Keep one end-to-end run log for troubleshooting.
Provide consistent video generation behavior for the video-agent pipeline by standardizing video.generate inputs/outputs and using DashScope SDK (Python) with the exact model name.
Critical model names
Use one of these exact model strings:
wan2.6-t2vwan2.6-t2v-uswan2.2-t2v-pluswan2.2-t2v-flashwan2.6-i2v-flashwan2.6-i2vwan2.6-i2v-uswanx2.1-t2v-turbo
Prerequisites
- Install SDK (recommended in a venv to avoid PEP 668 limits):
python3 -m venv .venv
. .venv/bin/activate
python -m pip install dashscope- Set
DASHSCOPE_API_KEYin your environment, or adddashscope_api_keyto~/.alibabacloud/credentials(env takes precedence).
Normalized interface (video.generate)
Request
prompt(string, required)negative_prompt(string, optional)duration(number, required) secondsfps(number, required)size(string, required) e.g.1280*720seed(int, optional)reference_image(string | bytes, optional for t2v, required for i2v family models)motion_strength(number, optional)
Response
video_url(string)duration(number)fps(number)seed(int)
Quick start (Python + DashScope SDK)
Video generation is usually asynchronous. Expect a task ID and poll until completion. Note: Wan i2v models require an input image; pure t2v models such as wan2.6-t2v can omit reference_image.
import os
from dashscope import VideoSynthesis
# Prefer env var for auth: export DASHSCOPE_API_KEY=...
# Or use ~/.alibabacloud/credentials with dashscope_api_key under [default].
def generate_video(req: dict) -> dict:
payload = {
"model": req.get("model", "wan2.6-i2v-flash"),
"prompt": req["prompt"],
"negative_prompt": req.get("negative_prompt"),
"duration": req.get("duration", 4),
"fps": req.get("fps", 24),
"size": req.get("size", "1280*720"),
"seed": req.get("seed"),
"motion_strength": req.get("motion_strength"),
"api_key": os.getenv("DASHSCOPE_API_KEY"),
}
if req.get("reference_image"):
# DashScope expects img_url for i2v models; local files are auto-uploaded.
payload["img_url"] = req["reference_image"]
response = VideoSynthesis.call(**payload)
# Some SDK versions require polling for the final result.
# If a task_id is returned, poll until status is SUCCEEDED.
result = response.output.get("results", [None])[0]
return {
"video_url": None if not result else result.get("url"),
"duration": response.output.get("duration"),
"fps": response.output.get("fps"),
"seed": response.output.get("seed"),
}Async handling (polling)
import os
from dashscope import VideoSynthesis
task = VideoSynthesis.async_call(
model=req.get("model", "wan2.6-i2v-flash"),
prompt=req["prompt"],
img_url=req["reference_image"],
duration=req.get("duration", 4),
fps=req.get("fps", 24),
size=req.get("size", "1280*720"),
api_key=os.getenv("DASHSCOPE_API_KEY"),
)
final = VideoSynthesis.wait(task)
video_url = final.output.get("video_url")Operational guidance
- Video generation can take minutes; expose progress and allow cancel/retry.
- Cache by
(prompt, negative_prompt, duration, fps, size, seed, reference_image hash, motion_strength). - Store video assets in object storage and persist only URLs in metadata.
reference_imagecan be a URL or local path; the SDK auto-uploads local files.- If you get
Field required: input.img_url, the reference image is missing or not mapped. wan2.6-t2vandwan2.6-t2v-usadd multi-shot narrative support and optional audio input according to the official docs.
Size notes
- Use
WxHformat (e.g.1280*720). - Prefer common sizes; unsupported sizes can return 400.
Output location
- Default output:
output/alicloud-ai-video-wan-video/videos/ - Override base dir with
OUTPUT_DIR.
Anti-patterns
- Do not invent model names or aliases; use official Wan i2v model IDs only.
- Do not block the UI without progress updates.
- Do not retry blindly on 4xx; handle validation failures explicitly.
Workflow
1) Confirm user intent, region, identifiers, and whether the operation is read-only or mutating. 2) Run one minimal read-only query first to verify connectivity and permissions. 3) Execute the target operation with explicit parameters and bounded scope. 4) Verify results and save output/evidence files.
References
- See
references/api_reference.mdfor DashScope SDK mapping and async handling notes.
- Source list:
references/sources.md
interface:
display_name: "Alibaba Cloud AI Video Wan Video"
short_description: "AI video generation and orchestration"
default_prompt: "Use $alicloud-ai-video-wan-video to complete this ai/video task on Alibaba Cloud."
DashScope SDK Reference (Wan Video)
Keep this reference minimal and update it only when the DashScope SDK behavior changes.
Install
python3 -m venv .venv
. .venv/bin/activate
python -m pip install dashscopeEnvironment
export DASHSCOPE_API_KEY=your_keyIf env vars are not set, you can also place dashscope_api_key under [default] in ~/.alibabacloud/credentials.
Suggested mapping
import os
from dashscope import VideoSynthesis
payload = {
"model": "wan2.6-i2v-flash",
"prompt": prompt,
"negative_prompt": negative_prompt,
"duration": duration,
"fps": fps,
"size": size,
"seed": seed,
"motion_strength": motion_strength,
"api_key": os.getenv("DASHSCOPE_API_KEY"),
}
if reference_image:
# DashScope expects img_url for i2v models; local files are auto-uploaded.
payload["img_url"] = reference_image
response = VideoSynthesis.call(**payload)Async handling
If the SDK returns a task ID rather than a direct result URL, poll until completion. Use exponential backoff and a hard timeout; fail gracefully with the task ID for later resumption.
task = VideoSynthesis.async_call(**payload)
final = VideoSynthesis.wait(task)
video_url = final.output.get("video_url")Response parsing
Normalize to:
video_urldurationfpsseed
Prefer the first result URL if multiple are returned.
Notes
wan2.6-i2v-flashrequiresimg_url; missing it yieldsField required: input.img_url.reference_imagecan be a URL or local path; the SDK auto-uploads local files.
- 模型上下架与更新(wan2.6-t2v、wan2.6-i2v-flash、wan2.6-r2v-flash): https://help.aliyun.com/zh/model-studio/newly-released-models
- 万相文生视频: https://help.aliyun.com/zh/model-studio/text-to-video-guide
- 万相图生视频-基于首帧: https://help.aliyun.com/zh/model-studio/first-frame-image-to-video
- 模型列表: https://help.aliyun.com/zh/model-studio/models
#!/usr/bin/env python3
"""Generate a dancing video: first create an image, then animate it.
Usage:
python scripts/generate_dancing_video.py --prompt "亚洲美女在跳舞" --output output/dancing_video.mp4
"""
from __future__ import annotations
import argparse
import configparser
import json
import os
import sys
import time
import urllib.request
from pathlib import Path
from typing import Any
try:
from dashscope.aigc.image_generation import ImageGeneration
from dashscope import VideoSynthesis
except ImportError:
print("Error: dashscope is not installed. Run: pip install dashscope", file=sys.stderr)
sys.exit(1)
IMAGE_MODEL = "qwen-image-max"
VIDEO_MODEL = "wan2.6-i2v-flash"
DEFAULT_IMAGE_SIZE = "1024*1024"
DEFAULT_VIDEO_SIZE = "1280*720"
DEFAULT_FPS = 24
DEFAULT_DURATION = 5
def _find_repo_root(start: Path) -> Path | None:
for parent in [start] + list(start.parents):
if (parent / ".git").exists():
return parent
return None
def _load_dotenv(path: Path) -> None:
if not path.exists():
return
for line in path.read_text().splitlines():
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, value = line.split("=", 1)
key = key.strip()
value = value.strip().strip('"').strip("'")
if key and key not in os.environ:
os.environ[key] = value
def _load_env() -> None:
_load_dotenv(Path.cwd() / ".env")
repo_root = _find_repo_root(Path(__file__).resolve())
if repo_root:
_load_dotenv(repo_root / ".env")
def _load_dashscope_api_key_from_credentials() -> None:
if os.environ.get("DASHSCOPE_API_KEY"):
return
credentials_path = Path(os.path.expanduser("~/.alibabacloud/credentials"))
if not credentials_path.exists():
return
config = configparser.ConfigParser()
try:
config.read(credentials_path)
except configparser.Error:
return
profile = os.getenv("ALIBABA_CLOUD_PROFILE") or os.getenv("ALICLOUD_PROFILE") or "default"
if not config.has_section(profile):
return
key = config.get(profile, "dashscope_api_key", fallback="").strip()
if not key:
key = config.get(profile, "DASHSCOPE_API_KEY", fallback="").strip()
if key:
os.environ["DASHSCOPE_API_KEY"] = key
def generate_image(prompt: str, size: str = DEFAULT_IMAGE_SIZE) -> dict[str, Any]:
"""Generate an image of an Asian beauty."""
print(f"Step 1: Generating image with prompt: {prompt}")
messages = [{"role": "user", "content": [{"text": prompt}]}]
response = ImageGeneration.call(
model=IMAGE_MODEL,
messages=messages,
size=size,
api_key=os.getenv("DASHSCOPE_API_KEY"),
)
content = response.output["choices"][0]["message"]["content"]
image_url = None
for item in content:
if isinstance(item, dict) and item.get("image"):
image_url = item["image"]
break
if not image_url:
raise RuntimeError("No image URL returned by DashScope")
print(f" Image generated: {image_url}")
return {"image_url": image_url}
def generate_video(image_url: str, prompt: str, duration: int = DEFAULT_DURATION,
fps: int = DEFAULT_FPS, size: str = DEFAULT_VIDEO_SIZE) -> dict[str, Any]:
"""Generate a dancing video from the image."""
print(f"Step 2: Generating video from image...")
print(f" Video prompt: {prompt}")
print(f" Duration: {duration}s, FPS: {fps}, Size: {size}")
payload = {
"model": VIDEO_MODEL,
"prompt": prompt,
"duration": duration,
"fps": fps,
"size": size,
"api_key": os.getenv("DASHSCOPE_API_KEY"),
"img_url": image_url,
}
task = VideoSynthesis.async_call(**payload)
print(" Waiting for video generation (this may take 2-5 minutes)...")
poll_interval = 10
timeout_s = 600
start = time.time()
while True:
final = VideoSynthesis.wait(task)
output = getattr(final, "output", None) or {}
status = output.get("status")
if status in ("SUCCEEDED", "FAILED") or output.get("video_url"):
break
if time.time() - start > timeout_s:
raise TimeoutError(f"Video generation timed out after {timeout_s}s")
print(f" Still processing... ({int(time.time() - start)}s elapsed)")
time.sleep(poll_interval)
output = getattr(final, "output", None) or {}
video_url = output.get("video_url")
if not video_url:
results = output.get("results") or []
if results and isinstance(results, list):
video_url = results[0].get("url")
if not video_url:
raise RuntimeError("No video URL returned by DashScope")
print(f" Video generated: {video_url}")
return {"video_url": video_url, "duration": output.get("duration"), "fps": output.get("fps")}
def download_file(url: str, output_path: Path) -> None:
"""Download a file from URL."""
output_path.parent.mkdir(parents=True, exist_ok=True)
print(f"Downloading to: {output_path}")
with urllib.request.urlopen(url) as response:
output_path.write_bytes(response.read())
def main() -> None:
parser = argparse.ArgumentParser(description="Generate a dancing video (image + animation)")
parser.add_argument("--prompt", required=True, help="Prompt for the dancing video")
parser.add_argument("--image-prompt", help="Optional separate prompt for the base image")
parser.add_argument("--duration", type=int, default=DEFAULT_DURATION, help="Video duration in seconds")
parser.add_argument("--fps", type=int, default=DEFAULT_FPS, help="Video FPS")
parser.add_argument("--output", help="Output video path")
parser.add_argument("--save-image", action="store_true", help="Also save the generated image")
parser.add_argument("--print-response", action="store_true", help="Print response JSON")
args = parser.parse_args()
_load_env()
_load_dashscope_api_key_from_credentials()
if not os.environ.get("DASHSCOPE_API_KEY"):
print("Error: DASHSCOPE_API_KEY is not set.", file=sys.stderr)
print("Configure via environment variable, .env file, or ~/.alibabacloud/credentials", file=sys.stderr)
sys.exit(1)
# Default image prompt if not specified
image_prompt = args.image_prompt or args.prompt
if not args.image_prompt:
# Enhance the prompt for image generation if user didn't specify
image_prompt = f"一位美丽的亚洲女性,专业摄影,高质量,{args.prompt}"
output_dir = Path(os.getenv("OUTPUT_DIR", "output")) / "ai-video-wan-video" / "videos"
output_path = Path(args.output) if args.output else output_dir / "dancing_video.mp4"
image_output_path = output_path.with_name(output_path.stem + "_reference.png")
try:
# Step 1: Generate image
image_result = generate_image(image_prompt)
# Save image if requested
if args.save_image:
download_file(image_result["image_url"], image_output_path)
print(f"Image saved to: {image_output_path}")
# Step 2: Generate video
video_result = generate_video(
image_result["image_url"],
args.prompt,
duration=args.duration,
fps=args.fps,
)
# Download video
download_file(video_result["video_url"], output_path)
print(f"\nVideo saved to: {output_path}")
if args.print_response:
print(json.dumps({
"image": image_result,
"video": video_result,
"output_path": str(output_path),
}, ensure_ascii=False, indent=2))
print("\nDone!")
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""Generate a video using DashScope (Wan t2v or i2v) from a normalized request.
Usage:
python scripts/generate_video.py --request '{"prompt":"...","model":"wan2.6-t2v"}'
python scripts/generate_video.py --request '{"prompt":"...","model":"wan2.6-i2v-flash","reference_image":"./ref.png"}'
python scripts/generate_video.py --file request.json --output output/ai-video-wan-video/videos/output.mp4
"""
from __future__ import annotations
import argparse
import configparser
import json
import os
import sys
import time
import urllib.request
from pathlib import Path
from typing import Any
try:
from dashscope import VideoSynthesis
except ImportError:
print("Error: dashscope is not installed. Run: pip install dashscope", file=sys.stderr)
sys.exit(1)
MODEL_NAME = "wan2.6-t2v"
DEFAULT_SIZE = "1280*720"
DEFAULT_FPS = 24
DEFAULT_DURATION = 4
def _find_repo_root(start: Path) -> Path | None:
for parent in [start] + list(start.parents):
if (parent / ".git").exists():
return parent
return None
def _load_dotenv(path: Path) -> None:
if not path.exists():
return
for line in path.read_text().splitlines():
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, value = line.split("=", 1)
key = key.strip()
value = value.strip().strip('"').strip("'")
if key and key not in os.environ:
os.environ[key] = value
def _load_env() -> None:
_load_dotenv(Path.cwd() / ".env")
repo_root = _find_repo_root(Path(__file__).resolve())
if repo_root:
_load_dotenv(repo_root / ".env")
def _load_dashscope_api_key_from_credentials() -> None:
if os.environ.get("DASHSCOPE_API_KEY"):
return
credentials_path = Path(os.path.expanduser("~/.alibabacloud/credentials"))
if not credentials_path.exists():
return
config = configparser.ConfigParser()
try:
config.read(credentials_path)
except configparser.Error:
return
profile = os.getenv("ALIBABA_CLOUD_PROFILE") or os.getenv("ALICLOUD_PROFILE") or "default"
if not config.has_section(profile):
return
key = config.get(profile, "dashscope_api_key", fallback="").strip()
if not key:
key = config.get(profile, "DASHSCOPE_API_KEY", fallback="").strip()
if key:
os.environ["DASHSCOPE_API_KEY"] = key
def load_request(args: argparse.Namespace) -> dict[str, Any]:
if args.request:
return json.loads(args.request)
if args.file:
with open(args.file, "r", encoding="utf-8") as f:
return json.load(f)
raise ValueError("Either --request or --file must be provided")
def resolve_reference_image(value: str) -> Any:
if value.startswith("http://") or value.startswith("https://"):
return value
path = Path(value)
if path.exists():
return str(path)
return value
def model_requires_reference_image(model: str) -> bool:
return "-i2v" in model
def call_generate(req: dict[str, Any]) -> dict[str, Any]:
prompt = req.get("prompt")
if not prompt:
raise ValueError("prompt is required")
model = req.get("model", MODEL_NAME)
reference_image = req.get("reference_image")
if model_requires_reference_image(model) and not reference_image:
raise ValueError(f"reference_image is required for {model}")
payload = {
"model": model,
"prompt": prompt,
"negative_prompt": req.get("negative_prompt"),
"duration": req.get("duration", DEFAULT_DURATION),
"fps": req.get("fps", DEFAULT_FPS),
"size": req.get("size", DEFAULT_SIZE),
"seed": req.get("seed"),
"motion_strength": req.get("motion_strength"),
"api_key": os.getenv("DASHSCOPE_API_KEY"),
}
if reference_image:
payload["img_url"] = resolve_reference_image(reference_image)
task = VideoSynthesis.async_call(**payload)
timeout_s = req.get("timeout_s", 600)
poll_interval = req.get("poll_interval_s", 5)
start = time.time()
while True:
final = VideoSynthesis.wait(task)
output = getattr(final, "output", None) or {}
status = output.get("status")
if status in ("SUCCEEDED", "FAILED") or output.get("video_url"):
break
if time.time() - start > timeout_s:
raise TimeoutError(f"Video generation timed out after {timeout_s}s")
time.sleep(poll_interval)
output = getattr(final, "output", None) or {}
video_url = output.get("video_url")
if not video_url:
results = output.get("results") or []
if results and isinstance(results, list):
video_url = results[0].get("url")
if not video_url:
raise RuntimeError("No video URL returned by DashScope")
return {
"video_url": video_url,
"duration": output.get("duration"),
"fps": output.get("fps"),
"seed": output.get("seed"),
}
def download_video(video_url: str, output_path: Path) -> None:
output_path.parent.mkdir(parents=True, exist_ok=True)
with urllib.request.urlopen(video_url) as response:
output_path.write_bytes(response.read())
def main() -> None:
parser = argparse.ArgumentParser(description="Generate video with Wan text-to-video or image-to-video models")
parser.add_argument("--request", help="Inline JSON request string")
parser.add_argument("--file", help="Path to JSON request file")
default_output_dir = Path(os.getenv("OUTPUT_DIR", "output")) / "ai-video-wan-video" / "videos"
parser.add_argument(
"--output",
default=str(default_output_dir / "output.mp4"),
help="Output video path",
)
parser.add_argument("--print-response", action="store_true", help="Print normalized response JSON")
args = parser.parse_args()
_load_env()
_load_dashscope_api_key_from_credentials()
if not os.environ.get("DASHSCOPE_API_KEY"):
print(
"Error: DASHSCOPE_API_KEY is not set. Configure it via env/.env or ~/.alibabacloud/credentials.",
file=sys.stderr,
)
print("Example .env:\n DASHSCOPE_API_KEY=your_key_here", file=sys.stderr)
print(
"Example credentials:\n [default]\n dashscope_api_key=your_key_here",
file=sys.stderr,
)
sys.exit(1)
req = load_request(args)
result = call_generate(req)
download_video(result["video_url"], Path(args.output))
if args.print_response:
print(json.dumps(result, ensure_ascii=True))
if __name__ == "__main__":
main()
Related skills
How it compares
Pick this over generic media skills when the stack is Alibaba Cloud WAN APIs rather than open-source local diffusion models.
FAQ
What does alicloud-ai-video-wan-video integrate?
alicloud-ai-video-wan-video integrates Alibaba Cloud WAN text-to-video and prompt-to-video generation APIs. Developers embed managed cloud video creation into agents, backends, or media products instead of operating self-hosted diffusion infrastructure.
Who should use the WAN video Alibaba Cloud skill?
Backend and AI engineers on Alibaba Cloud should use alicloud-ai-video-wan-video when products need programmatic prompt-to-video generation, asynchronous job handling, and hosted video assets delivered through WAN managed APIs.