本記事の作成者:Ferdin Joe
このデモでは、Alibaba Cloud Elastic Compute Service (ECS) に gradio インターフェースを作成し、gradio が API キーを使用して Alibaba Cloud Model Studio の Wan 2.5 プレビューモデルと接続し、入力として与えられたテキストプロンプトに対する画像とビデオを生成できるようにします。 このデモは、以下の部分で構成されています。
● ECS インスタンスの作成
● gradio 用のコードの開発
● bash スクリプトを使用した ECS へのコードのインストール
● ソリューションを使用するための探索ガイド
ECS インスタンスの作成
パブリック IP アドレスまたは EIP を使用し、通常の設定で ECS インスタンスを作成します。 パブリックネットワークに接続する IP アドレスに対しては、適切な帯域幅を割り当てます。 作成したインスタンスを、ポート 7860 でのインバウンド接続が許可されたセキュリティグループに追加します。

その他のインバウンドルールとアウトバウンドルールは通常通りです。
gradio 用のコードの開発
Gradio では python を使用するため、必要な依存関係をインストールする必要があります。 Model Studio の API キーが必要です。 Model Studio コンソールから作成します。 必要なコードコンポーネントは以下の通りです:
ファイル名:'.env'
リクエストを引き出すための API キーを格納します。
DASHSCOPE_API_KEY=<使用する Model Studio の API キー>
ファイル名:'gradio_wan_app.py'
#!/usr/bin/env python3
"""
WAN でテキストから画像を生成するための Gradio Web インターフェース
DashScope Model Studio API を使用
"""
from http import HTTPStatus
from urllib.parse import urlparse, unquote
from pathlib import PurePosixPath
import requests
from dashscope import ImageSynthesis, VideoSynthesis
from dashscope.audio.tts_v2 import SpeechSynthesizer
import os
import dashscope
import gradio as gr
from dotenv import load_dotenv
from PIL import Image
from io import BytesIO
import logging
import json
# ロギングの設定
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# 環境変数の読み込み
load_dotenv()
# 設定 - シンガポールリージョンの API を使用
dashscope.base_http_api_url = 'https://dashscope-intl.aliyuncs.com/api/v1'
# 環境から API キーを取得
DASHSCOPE_API_KEY = os.getenv("DASHSCOPE_API_KEY", "<Model Studio の API>")
dashscope.api_key = DASHSCOPE_API_KEY
logger.info(f"🚀 Gradio WAN Image Generator を起動中...")
logger.info(f"API エンドポイント:{dashscope.base_http_api_url}")
def generate_image(
prompt: str,
negative_prompt: str = "",
num_images: int = 1,
size: str = "1024*1024",
seed: int = None,
prompt_extend: bool = True,
watermark: bool = False
):
"""
WAN 2.5 モデルを使用して画像を生成
引数:
prompt:テキストによる生成する画像の説明
negative_prompt:画像で避けたい結果
num_images:生成する画像の枚数 (1 ~ 4)
size:画像サイズ (1024*1024、720*1280、1280*720)
seed:再現性を高めるためのランダムシード (オプション)
prompt_extend:プロンプトを自動的に拡張するかどうか
watermark:透かしを追加するかどうか
戻り値:
PIL 画像のリストまたはエラーメッセージ
"""
if not prompt or prompt.strip() == "":
return None, None, "❌ プロンプトを入力してください。"
try:
logger.info(f"🎨 プロンプトの画像を生成中:{prompt}")
# パラメーターの準備
params = {
'api_key': DASHSCOPE_API_KEY,
'model': 'wan2.5-t2i-preview',
'prompt': prompt,
'negative_prompt': negative_prompt,
'n': num_images,
'size': size,
'prompt_extend': prompt_extend,
'watermark': watermark
}
# ある場合はシードを追加
if seed is not None and seed > 0:
params['seed'] = seed
# WAN API を呼び出す
logger.info(f"WAN 2.5 の API パラメーターを次のパラメーターで呼び出し中:{params}")
rsp = ImageSynthesis.call(**params)
logger.info(f"応答ステータス:{rsp.status_code}")
if rsp.status_code == HTTPStatus.OK:
images = []
# 生成された各画像をダウンロードして変換
for idx, result in enumerate(rsp.output.results):
logger.info(f"画像 {idx + 1} をダウンロード中:{result.url}")
# 画像データのダウンロード
image_data = requests.get(result.url).content
# PIL 画像に変換
image = Image.open(BytesIO(image_data))
images.append(image)
logger.info(f"✅ 画像 {idx + 1} がダウンロードされました。")
success_msg = f"✅ {len(images)} 枚の画像が生成されました。"
# 常にギャラリーコンポーネントのリストとして返す
return images, None, success_msg
else:
error_msg = f"❌ 生成に失敗しました。\n\nステータス:{rsp.status_code}\nコード:{rsp.code}\nメッセージ:{rsp.message}"
logger.error(error_msg)
return None, None, error_msg
except Exception as e:
error_msg = f"❌ 画像の生成中にエラーが発生しました。\n\n{str(e)}"
logger.error(f"generate_image でエラー:{e}", exc_info=True)
return None, None, error_msg
def generate_video(
prompt: str,
resolution: str = "1280*720",
duration: str = "5s",
enable_audio: bool = False
):
"""
WAN 2.5 T2V プレビューモデルを使用してビデオを生成
引数:
prompt:生成するビデオのテキスト説明
resolution:ビデオの解像度 (1280*720、960*960、1280*768、768*1280)
duration:ビデオの長さ (5 秒または 10 秒)
enable_audio:ビデオのオーディオを生成するかどうか
戻り値:
ビデオファイルのパスとステータスメッセージ
"""
if not prompt or prompt.strip() == "":
return None, None, "❌ プロンプトを入力してください。"
try:
logger.info(f"🎬 プロンプトでビデオを生成中:{prompt}")
logger.info(f"WAN 2.5 T2V プレビューモデルを使用中。解像度:{resolution}")
logger.info(f"長さ:{duration}")
logger.info(f"オーディオ有効:{enable_audio}")
# VideoSynthesis を使用して WAN 2.5 T2V プレビュー API を呼び出す
# 注:オーディオの生成は別のパラメーターを使用して行われます
logger.info("VideoSynthesis API を呼び出し中...")
# 長さの文字列を秒に変換 (例:"10s" -> 10)
duration_seconds = int(duration.replace('s', ''))
if enable_audio:
# オーディオサポートでモデルを使用する
rsp = VideoSynthesis.call(
model='wan2.5-t2v-preview',
prompt=prompt,
size=resolution,
duration=duration_seconds,
audio=True # オーディオ生成の有効化
)
else:
# オーディオなしの標準ビデオ
rsp = VideoSynthesis.call(
model='wan2.5-t2v-preview',
prompt=prompt,
size=resolution,
duration=duration_seconds
)
logger.info(f"応答ステータス:{rsp.status_code}")
if rsp.status_code == HTTPStatus.OK:
video_url = rsp.output.video_url
logger.info(f"受信したビデオの URL:{video_url}")
# ビデオのダウンロード
logger.info("ビデオのダウンロード中...")
video_data = requests.get(video_url).content
# ファイルに保存
import time
video_filename = f"generated_video_{int(time.time())}.mp4"
with open(video_filename, 'wb') as f:
f.write(video_data)
logger.info(f"✅ 正常にダウンロードされたビデオ:{video_filename}")
audio_status = " with audio" if enable_audio else " (no audio)"
success_msg = f"✅ ビデオが生成されました {audio_status}。\n\n長さ:{duration}\n解像度:{resolution}\nモデル:WAN 2.5 T2V プレビュー"
return None, video_filename, success_msg
else:
error_msg = f"❌ ビデオの生成に失敗しました。\n\nステータス:{rsp.status_code}\nコード:{rsp.code}\nメッセージ:{rsp.message}\n注:現在の API キーではビデオの生成ができない場合があります。"
logger.error(error_msg)
logger.error(f"完全な応答:status_code={rsp.status_code}, code={rsp.code}, message={rsp.message}")
return None, None, error_msg
except Exception as e:
error_msg = f"❌ ビデオ生成中のエラー:\n\n{str(e)}\n\n注:ビデオ生成には WAN T2V モデルへの API アクセスが必要です。"
logger.error(f"generate_video のエラー:{e}", exc_info=True)
return None, None, error_msg
def generate_content(
mode: str,
prompt: str,
negative_prompt: str,
num_images: int,
image_size: str,
video_resolution: str,
video_duration: str,
enable_audio: bool,
seed: int,
prompt_extend: bool,
watermark: bool
):
"""
モードに基づいて適切な生成機能にルーティング
"""
if mode == "テキストから画像":
return generate_image(
prompt=prompt,
negative_prompt=negative_prompt,
num_images=num_images,
size=image_size,
seed=seed,
prompt_extend=prompt_extend,
watermark=watermark
)
else: # テキストからビデオ
return generate_video(
prompt=prompt,
resolution=video_resolution,
duration=video_duration,
enable_audio=enable_audio
)
# Gradio インターフェースの作成
def create_interface():
"""Gradio インターフェースの作成と設定"""
with gr.Blocks(
title="WAN Text-to-Image & Text-to-Video Generator",
theme=gr.themes.Soft()
) as demo:
gr.Markdown(
"""
# 🎨 WAN 2.5 Text-to-Image & Text-to-Video Generator
Alibaba Cloud の WAN モデルを使用して、テキストの説明から見事な画像またはビデオを生成します。
### 使用方法:
1. 生成モードを選択 (画像またはビデオ)
2. 詳細な説明を入力
3. (オプション) 設定を調整
4. **生成** ボタンをクリック
5. 作成されるまで待ちます。 🎞️
"""
)
with gr.Row():
with gr.Column(scale=1):
# モードの選択
mode_radio = gr.Radio(
choices=["テキストから画像", "テキストからビデオ"],
value="テキストから画像",
label="🎭 生成モード",
info="どちらを生成しますか"
)
# 入力コントロール
prompt_input = gr.Textbox(
label="✏️ プロンプト",
placeholder="生成する内容を説明してください... (例:「山の上の美しい夕日」)",
lines=3,
max_lines=5
)
# 画像固有の設定
with gr.Group(visible=True) as image_settings:
gr.Markdown("###🖼️ 画像設定")
negative_prompt_input = gr.Textbox(
label="🚫 ネガティブプロンプト (オプション)",
placeholder="避けたい結果 (例:'ぼやけた、低品質')",
lines=2,
max_lines=3
)
num_images_slider = gr.Slider(
minimum=1,
maximum=4,
value=1,
step=1,
label="画像の枚数"
)
image_size_dropdown = gr.Dropdown(
choices=["1024*1024", "720*1280", "1280*720"],
value="1024*1024",
label="画像サイズ"
)
seed_number = gr.Number(
label="シード (オプション)",
value=None,
precision=0,
info="再現性の高い結果を得るには同じシードを使用します"
)
prompt_extend_checkbox = gr.Checkbox(
label="プロンプトの自動拡張",
value=True,
info="AI にプロンプトを強化させます"
)
watermark_checkbox = gr.Checkbox(
label="透かしの追加",
value=False
)
# ビデオ固有の設定
with gr.Group(visible=False) as video_settings:
gr.Markdown("###🎬 ビデオ設定")
video_resolution_dropdown = gr.Dropdown(
choices=["1280*720", "960*960", "1280*768", "768*1280"],
value="1280*720",
label="ビデオ解像度"
)
video_duration_radio = gr.Radio(
choices=["5 秒", "10 秒"],
value="5 秒",
label="ビデオの長さ"
info="長いビデオの生成には時間がかかります"
)
enable_audio_checkbox = gr.Checkbox(
label="🔊 オーディオを有効にする",
value=False,
info="ビデオ用のオーディオの生成 (注:オーディオのサポートは API の可用性に依存します)"
)
generate_btn = gr.Button(
"🎨 生成 ",
variant="primary",
size="lg"
)
status_output = gr.Textbox(
label="ステータス",
interactive=False,
show_label=True
)
with gr.Column(scale=1):
# 出力の表示
image_output = gr.Gallery(
label="生成された画像",
show_label=True,
visible=True,
columns=2,
rows=2,
object_fit="contain"
)
video_output = gr.Video(
label="生成されたビデオ",
show_label=True,
visible=False
)
# プロンプトの例
gr.Markdown("###💡 プロンプトの例")
with gr.Tab("画像の例"):
gr.Examples(
examples=[
["夕暮れの時間帯、桜の花びらが舞い、錦鯉の泳ぐ池と伝統的な五重塔がある静かな日本庭園"],
["ネオンが輝き、空飛ぶ車が行き交い、超高層ビルが立ち並ぶ未来的なサイバーパンク都市"],
["暖かな照明、木製家具、植物に囲まれた居心地のよいカフェの店内"],
["オーロラの下、雪に覆われた山々の上空を飛ぶ威厳あるドラゴン"],
["古い書物でいっぱいの図書館で本を読んでいるかわいいロボット"],
],
inputs=[prompt_input]
)
with gr.Tab("ビデオの例"):
gr.Examples(
examples=[
["山々の風景の上を、青空に流れる雲のタイムラプス映像"],
["夕暮れ時、砂浜に穏やかに寄せては返す海の波"],
["花にとまり、ゆっくりと羽を広げる蝶"],
["雨粒が窓に落ち、背後にはぼやけた都市の景色が広がる様子"],
["雪原の上空で夜空に舞うオーロラ"],
],
inputs=[prompt_input]
)
# モードに基づいて表示を切り替え
def update_visibility(mode):
if mode == "テキストから画像":
return (
gr.update(visible=True), # image_settings
gr.update(visible=False), # video_settings
gr.update(visible=True), # image_output
gr.update(visible=False), # video_output
gr.update(value="🎨 画像を生成") # ボタンテキスト
)
else:
return (
gr.update(visible=False), # image_settings
gr.update(visible=True), # video_settings
gr.update(visible=False), # image_output
gr.update(visible=True), # video_output
gr.update(value="🎬 ビデオの生成") # ボタンテキスト
)
mode_radio.change(
fn=update_visibility,
inputs=[mode_radio],
outputs=[image_settings, video_settings, image_output, video_output, generate_btn]
)
# 生成ボタンを接続
generate_btn.click(
fn=generate_content,
inputs=[
mode_radio,
prompt_input,
negative_prompt_input,
num_images_slider,
image_size_dropdown,
video_resolution_dropdown,
video_duration_radio,
enable_audio_checkbox,
seed_number,
prompt_extend_checkbox,
watermark_checkbox
],
outputs=[image_output, video_output, status_output]
)
return demo
if __name__ == "__main__":
# API キーの検証
if not DASHSCOPE_API_KEY or DASHSCOPE_API_KEY == "":
logger.error("❌ 環境変数に DASHSCOPE_API_KEY が見つかりません")
print("\n⚠️ .env ファイルの DASHSCOPE_API_KEY を設定してください\n")
exit(1)
# インターフェースの作成と起動
demo = create_interface()
logger.info("🌐 Gradio インターフェースの起動中...")
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=False,
show_error=True
)
ファイル名:deploy_to_ecs.sh
#!/bin/bash
# Alibaba Cloud ECS に Gradio WAN アプリをデプロイするスクリプト
# ファイル転送後に ECS インスタンスでこのスクリプトを実行
set -e # エラーで終了
echo "🚀 Gradio WAN アプリのデプロイを開始中..."
# 出力の色
GREEN='\033[0;32m'
BLUE='\033[0;34m'
RED='\033[0;31m'
NC='\033[0m' # 無色
# 設定
APP_DIR="/root/financeapp"
SERVICE_NAME="gradio-wan"
echo -e "${BLUE}📦 ステップ 1:システム依存関係のインストール中...${NC}"
if command -v apt &> /dev/null; then
# Ubuntu/Debian
sudo apt update
sudo apt install -y python3 python3.12-venv python3-pip git build-essential
elif command -v yum &> /dev/null; then
# CentOS/RHEL
sudo yum update -y
sudo yum install -y python39 python39-pip git gcc gcc-c++ make
fi
echo -e "${BLUE}📂 ステップ 2:アプリケーションディレクトリの設定中...${NC}"
cd $APP_DIR
echo -e "${BLUE}🐍 ステップ 3:Python 仮想環境の作成中...${NC}"
python3 -m venv .venv
source .venv/bin/activate
echo -e "${BLUE}📥 ステップ 4:Python 依存関係のインストール中...${NC}"
pip install --upgrade pip
pip install gradio==4.16.0 gradio-client==0.8.1
pip install dashscope>=1.23.4
pip install python-dotenv>=1.0.0
pip install requests>=2.31.0
pip install pillow>=10.0.0
pip install "huggingface_hub<1.0.0"
pip install numpy>=1.24.0
echo -e "${BLUE}⚙️ ステップ 5:systemd サービスの作成中...${NC}"
sudo tee /etc/systemd/system/${SERVICE_NAME}.service > /dev/null <<EOF
[Unit]
Description=Gradio WAN Image and Video Generator
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=$APP_DIR
Environment="PATH=$APP_DIR/.venv/bin"
ExecStart=$APP_DIR/.venv/bin/python gradio_wan_app.py
Restart=always
RestartSec=10
StandardOutput=append:/var/log/${SERVICE_NAME}.log
StandardError=append:/var/log/${SERVICE_NAME}.error.log
[Install]
WantedBy=multi-user.target
EOF
echo -e "${BLUE}🔄 ステップ 6:サービスを有効化および開始中...${NC}"
sudo systemctl daemon-reload
sudo systemctl enable ${SERVICE_NAME}
sudo systemctl restart ${SERVICE_NAME}
echo -e "${GREEN}✅ デプロイが完了しました。${NC}"
echo ""
echo "📊 サービスステータス:"
sudo systemctl status ${SERVICE_NAME} --no-pager
echo ""
echo "🌐 Gradio アプリにこちらからアクセスできるようになりました:"
echo " http://$(curl -s ifconfig.me):7860"
echo ""
echo "📝 便利なコマンド:"
echo " ログの表示: sudo journalctl -u ${SERVICE_NAME} -f"
echo " サービスの停止: sudo systemctl stop ${SERVICE_NAME}"
echo " サービスの開始: sudo systemctl start ${SERVICE_NAME}"
echo " 再起動: sudo systemctl restart ${SERVICE_NAME}"
echo " ステータス: sudo systemctl status ${SERVICE_NAME}"
echo ""
echo "⚠️ 重要:ECS セキュリティグループでポート 7860 が開いていることを確認してください。"
上記の 3 つのファイルを仮想環境 .venv で指定されたルートフォルダーに読み込みます。 必要なすべてをインストールするためのコマンドについては次のセクションで説明します。
bash スクリプトを使用した ECS へのコードのインストール
ローカル端末から以下のコマンドを使用してファイルを ECS にアップロードします。
# 必要なすべてのファイルを転送 (<ECS_IP> を実際の ECS のパブリック IP に置き換え)
scp gradio_wan_app.py root@<ECS_IP>:/root/targetfolder/
scp .env root@<ECS_IP>:/root/targetfolder/
scp deploy_to_ecs.sh root@<ECS_IP>:/root/targetfolder/
python、pip、仮想環境、および必要なライブラリから必要なすべてをインストールするには、以下のコマンドを実行します。
cd /root/targetfolder
chmod +x deploy_to_ecs.sh
./deploy_to_ecs.sh
シェルスクリプトが実行され、アドレス http://ECS-Public-IP:7860 でインターフェースを実行できるようになります。

テキストから画像の場合、同時に 4 枚の画像を作成できます。 テキストからビデオの場合、さまざまな解像度の wan ビデオを作成し、オーディオを有効化または無効化して、5 秒または 10 秒の長さのビデオを取得できます。 このアプリケーションは、エージェントモードを使用して Qoder IDE を使用して開発されました。
この記事は、英語版から翻訳されました。 原文については、https://www.alibabacloud.com/blog/image-and-video-generation-from-text-prompts-using-wan-2-5-preview-model-from-model-studio_602726 をご参照ください。
การสร้างภาพและวิดีโอจากพรอมต์โดยใช้โมเดลตัวอย่าง Wan 2.5 จาก Model Studio
129 posts | 4 followers
FollowRegional Content Hub - November 25, 2024
Regional Content Hub - April 21, 2025
Regional Content Hub - May 7, 2025
Regional Content Hub - March 8, 2024
Regional Content Hub - October 8, 2024
Regional Content Hub - February 26, 2024
129 posts | 4 followers
Follow
ECS(Elastic Compute Service)
Elastic and secure virtual cloud servers to cater all your cloud hosting needs.
Learn More
Elastic Desktop Service
A convenient and secure cloud-based Desktop-as-a-Service (DaaS) solution
Learn More
IDaaS
Make identity management a painless experience and eliminate Identity Silos
Learn More
Container Service for Kubernetes
Alibaba Cloud Container Service for Kubernetes is a fully managed cloud container management service that supports native Kubernetes and integrates with other Alibaba Cloud products.
Learn MoreMore Posts by Regional Content Hub