Initial commit: Pixel AI comic/video creation platform

- FastAPI backend with SQLModel, Alembic migrations, AgentScope agents
- Next.js 15 frontend with React 19, Tailwind, Zustand, React Flow
- Multi-provider AI system (DashScope, Kling, MiniMax, Volcengine, OpenAI, etc.)
- All HTTP clients migrated from sync requests to async httpx
- Admin-managed API keys via environment variables
- SSRF vulnerability fixed in ensure_url()
This commit is contained in:
张鹏
2026-04-29 01:20:12 +08:00
commit f9f4560459
808 changed files with 151724 additions and 0 deletions

View File

@@ -0,0 +1,198 @@
from sqlmodel import create_engine, SQLModel, Session
from sqlalchemy.pool import StaticPool, QueuePool
from sqlalchemy import text
from sqlalchemy import event
from src.config.settings import DB_PATH, DATABASE_URL
import logging
import time
import os
logger = logging.getLogger(__name__)
# Slow query threshold in seconds
SLOW_QUERY_THRESHOLD = float(os.getenv("SLOW_QUERY_THRESHOLD", "1.0"))
# Connection pool configuration from environment variables
POOL_SIZE = int(os.getenv("DB_POOL_SIZE", "20"))
MAX_OVERFLOW = int(os.getenv("DB_MAX_OVERFLOW", "10"))
POOL_TIMEOUT = int(os.getenv("DB_POOL_TIMEOUT", "30"))
POOL_RECYCLE = int(os.getenv("DB_POOL_RECYCLE", "3600"))
POOL_PRE_PING = os.getenv("DB_POOL_PRE_PING", "true").lower() == "true"
# Create the database engine with optimized connection pooling
if DATABASE_URL:
# PostgreSQL Configuration with configurable connection pool
engine = create_engine(
DATABASE_URL,
echo=False,
poolclass=QueuePool,
pool_size=POOL_SIZE,
max_overflow=MAX_OVERFLOW,
pool_timeout=POOL_TIMEOUT,
pool_recycle=POOL_RECYCLE,
pool_pre_ping=POOL_PRE_PING,
# Additional optimizations
connect_args={
"connect_timeout": 10,
"options": "-c statement_timeout=120000" # 120 second statement timeout for AI operations
}
)
logger.info(
f"PostgreSQL engine created with pool_size={POOL_SIZE}, "
f"max_overflow={MAX_OVERFLOW}, pool_timeout={POOL_TIMEOUT}s, "
f"pool_recycle={POOL_RECYCLE}s, pool_pre_ping={POOL_PRE_PING}"
)
else:
# SQLite Configuration (Fallback)
engine = create_engine(
f"sqlite:///{DB_PATH}",
echo=False,
connect_args={
"check_same_thread": False,
"timeout": 30 # 30 second busy timeout
},
poolclass=StaticPool, # Use StaticPool for SQLite
)
logger.info(f"SQLite engine created with StaticPool at {DB_PATH}")
# Add slow query logging
@event.listens_for(engine, "before_cursor_execute")
def before_cursor_execute(conn, cursor, statement, parameters, context, executemany):
""" 记录 query start time."""
conn.info.setdefault("query_start_time", []).append(time.time())
@event.listens_for(engine, "after_cursor_execute")
def after_cursor_execute(conn, cursor, statement, parameters, context, executemany):
""" 日志 slow queries."""
total_time = time.time() - conn.info["query_start_time"].pop()
if total_time > SLOW_QUERY_THRESHOLD:
logger.warning(
f"Slow query detected (took {total_time:.2f}s): {statement[:200]}",
extra={
"query_time": total_time,
"query": statement[:500],
"parameters": str(parameters)[:200] if parameters else None
}
)
def init_db():
""" Initialize the database tables."""
from sqlalchemy.exc import OperationalError
# Try to create all tables
try:
SQLModel.metadata.create_all(engine)
except OperationalError as e:
if "already exists" in str(e):
# Table or index already exists, skip creation
logger.warning(f"Skipping table/index creation: {e}")
else:
raise
def get_session():
""" 依赖 for getting a database session.
Ensures proper cleanup and connection management.
"""
with Session(engine) as session:
try:
yield session
finally:
# 会话 is automatically closed by context manager
# This ensures connections are returned to the pool
pass
def get_pool_status() -> dict:
""" Get current connection pool status for monitoring.
Returns pool statistics including size, checked out connections, etc.
"""
pool = engine.pool
status = {
"pool_size": getattr(pool, "size", lambda: 0)(),
"checked_out": getattr(pool, "checkedout", lambda: 0)(),
"overflow": getattr(pool, "overflow", lambda: 0)(),
"checked_in": getattr(pool, "checkedin", lambda: 0)(),
}
# Add pool-specific attributes if available
if hasattr(pool, "_pool"):
status["available"] = pool._pool.qsize()
return status
def check_database_health() -> tuple[bool, str]:
"""
Check database connectivity and health.
Returns (is_healthy, message).
"""
try:
with Session(engine) as session:
# Simple connectivity probe without model dependency.
session.exec(text("SELECT 1"))
return True, "Database connection healthy"
except Exception as e:
logger.error(f"Database health check failed: {e}")
return False, f"Database connection failed: {str(e)}"
def check_pool_health() -> dict:
"""
Comprehensive pool health check with recommendations.
Returns detailed pool status and health indicators.
"""
status = get_pool_status()
pool = engine.pool
# Calculate health metrics
total_connections = status.get("pool_size", 0) + status.get("overflow", 0)
checked_out = status.get("checked_out", 0)
available = status.get("available", 0)
# Health checks
health = {
"status": "healthy",
"checks": {},
"recommendations": [],
"pool_status": status
}
# Check 1: Connection exhaustion
if checked_out >= total_connections * 0.9:
health["checks"]["exhaustion"] = "critical"
health["status"] = "critical"
health["recommendations"].append(
f"Pool near exhaustion: {checked_out}/{total_connections} connections in use. "
f"Consider increasing DB_POOL_SIZE or DB_MAX_OVERFLOW."
)
elif checked_out >= total_connections * 0.75:
health["checks"]["exhaustion"] = "warning"
health["status"] = "warning"
health["recommendations"].append(
f"Pool usage high: {checked_out}/{total_connections} connections in use."
)
else:
health["checks"]["exhaustion"] = "healthy"
# Check 2: Available connections
if available == 0 and total_connections > 0:
health["checks"]["availability"] = "warning"
if health["status"] == "healthy":
health["status"] = "warning"
else:
health["checks"]["availability"] = "healthy"
# Check 3: Pool size configuration
if total_connections < 5:
health["recommendations"].append(
"Pool size may be too small for production workloads. "
"Consider DB_POOL_SIZE >= 10"
)
return health

View File

@@ -0,0 +1,217 @@
"""
异步数据库配置模块
提供 SQLAlchemy 2.0 AsyncSession 支持,用于完全异步的数据库操作。
支持 PostgreSQL (asyncpg) 和 SQLite (aiosqlite)。
"""
import logging
import os
import time
from typing import AsyncGenerator
from sqlalchemy import text
from sqlalchemy.ext.asyncio import (
create_async_engine,
AsyncSession,
async_sessionmaker,
AsyncEngine,
)
from sqlalchemy.pool import NullPool
from sqlmodel import SQLModel
from src.config.settings import DB_PATH, DATABASE_URL
logger = logging.getLogger(__name__)
# Slow query threshold in seconds
SLOW_QUERY_THRESHOLD = float(os.getenv("SLOW_QUERY_THRESHOLD", "1.0"))
# Connection pool configuration from environment variables
POOL_SIZE = int(os.getenv("DB_POOL_SIZE", "20"))
MAX_OVERFLOW = int(os.getenv("DB_MAX_OVERFLOW", "10"))
POOL_TIMEOUT = int(os.getenv("DB_POOL_TIMEOUT", "30"))
POOL_RECYCLE = int(os.getenv("DB_POOL_RECYCLE", "3600"))
POOL_PRE_PING = os.getenv("DB_POOL_PRE_PING", "true").lower() == "true"
# Global engine instance
async_engine: AsyncEngine | None = None
async_session_maker: async_sessionmaker[AsyncSession] | None = None
def _get_async_url() -> str:
"""Generate async database URL from settings."""
if DATABASE_URL:
# Convert PostgreSQL URL to async version
if DATABASE_URL.startswith("postgresql://"):
return DATABASE_URL.replace("postgresql://", "postgresql+asyncpg://", 1)
elif DATABASE_URL.startswith("postgresql+psycopg2://"):
return DATABASE_URL.replace("postgresql+psycopg2://", "postgresql+asyncpg://", 1)
return DATABASE_URL
else:
# SQLite async URL
return f"sqlite+aiosqlite:///{DB_PATH}"
def init_async_engine() -> AsyncEngine:
"""Initialize async database engine with optimized connection pooling."""
global async_engine
if async_engine is not None:
return async_engine
async_url = _get_async_url()
if "postgresql" in async_url:
# PostgreSQL async configuration
async_engine = create_async_engine(
async_url,
echo=False,
pool_size=POOL_SIZE,
max_overflow=MAX_OVERFLOW,
pool_timeout=POOL_TIMEOUT,
pool_recycle=POOL_RECYCLE,
pool_pre_ping=POOL_PRE_PING,
connect_args={
"timeout": 10,
"command_timeout": 30,
},
)
logger.info(
f"Async PostgreSQL engine created with pool_size={POOL_SIZE}, "
f"max_overflow={MAX_OVERFLOW}, pool_timeout={POOL_TIMEOUT}s"
)
else:
# SQLite async configuration
async_engine = create_async_engine(
async_url,
echo=False,
poolclass=NullPool, # SQLite doesn't support connection pooling well
connect_args={
"timeout": 30,
"check_same_thread": False,
},
)
logger.info(f"Async SQLite engine created at {DB_PATH}")
return async_engine
def init_async_session_maker() -> async_sessionmaker[AsyncSession]:
"""Initialize async session maker."""
global async_session_maker
if async_session_maker is not None:
return async_session_maker
engine = init_async_engine()
async_session_maker = async_sessionmaker(
engine,
class_=AsyncSession,
expire_on_commit=False,
autocommit=False,
autoflush=False,
)
return async_session_maker
async def init_db_async():
"""Initialize database tables asynchronously."""
engine = init_async_engine()
async with engine.begin() as conn:
await conn.run_sync(SQLModel.metadata.create_all)
logger.info("Database tables initialized (async)")
async def get_async_session() -> AsyncGenerator[AsyncSession, None]:
"""
Dependency for getting async database session.
Usage:
@router.get("/items")
async def get_items(session: AsyncSession = Depends(get_async_session)):
...
"""
session_maker = init_async_session_maker()
async with session_maker() as session:
try:
yield session
finally:
await session.close()
async def get_async_session_context() -> AsyncSession:
"""
Get async session as context manager.
Usage:
async with get_async_session_context() as session:
result = await session.execute(...)
"""
session_maker = init_async_session_maker()
return session_maker()
async def get_pool_status_async() -> dict:
"""
Get current connection pool status for monitoring.
Returns pool statistics including size, checked out connections, etc.
"""
engine = init_async_engine()
pool = engine.pool
status = {
"pool_size": getattr(pool, "size", lambda: 0)(),
"checked_out": getattr(pool, "checkedout", lambda: 0)(),
"overflow": getattr(pool, "overflow", lambda: 0)(),
}
return status
async def check_database_health_async() -> tuple[bool, str]:
"""
Check database connectivity and health asynchronously.
Returns (is_healthy, message).
"""
try:
engine = init_async_engine()
async with engine.connect() as conn:
start_time = time.time()
await conn.execute(text("SELECT 1"))
elapsed = time.time() - start_time
return True, f"Database connection healthy ({elapsed:.3f}s)"
except Exception as e:
logger.error(f"Database health check failed: {e}")
return False, f"Database connection failed: {str(e)}"
async def close_async_engine():
"""Close async engine and cleanup connections."""
global async_engine, async_session_maker
if async_engine is not None:
await async_engine.dispose()
async_engine = None
async_session_maker = None
logger.info("Async database engine closed")
# Import guards for sync operations
async def migrate_sync_to_async():
"""
Migration helper to ensure both sync and async engines are initialized.
During transition period, both can coexist.
"""
# Initialize async engine
init_async_engine()
init_async_session_maker()
# Sync engine is already initialized in database.py
logger.info("Both sync and async database engines are ready")

View File

@@ -0,0 +1,465 @@
{
"image": {
"aspectRatios": {
"label": "比例",
"options": [
{ "value": "1:1", "label": "1:1 (正方形)" },
{ "value": "3:4", "label": "3:4 (竖版)" },
{ "value": "4:3", "label": "4:3 (横版)" },
{ "value": "9:16", "label": "9:16 (手机竖版)" },
{ "value": "16:9", "label": "16:9 (宽屏)" }
],
"default": "16:9"
},
"resolutions": {
"label": "分辨率",
"options": [
{ "value": "1K", "label": "1K (标准)", "description": "1280x720 或 1024x1024" },
{ "value": "2K", "label": "2K (高清)", "description": "2560x1440 或 2048x2048" },
{ "value": "4K", "label": "4K (超高清)", "description": "3840x2160 或 4096x4096" }
],
"default": "1K"
},
"counts": {
"label": "生成数量",
"options": [
{ "value": 1, "label": "1张" },
{ "value": 2, "label": "2张" },
{ "value": 3, "label": "3张" },
{ "value": 4, "label": "4张" }
],
"default": 1,
"min": 1,
"max": 4
},
"templates": {
"label": "模板类型",
"options": [
{ "value": "general", "label": "通用", "description": "通用图片生成" },
{ "value": "character_white_bg", "label": "角色白底图", "description": "角色图片,白色背景" },
{ "value": "character_three_view", "label": "角色三视图", "description": "角色正面、侧面、背面视图" },
{ "value": "storyboard_integrated", "label": "分镜出图", "description": "基于分镜生成图片" }
],
"default": "general"
}
},
"video": {
"aspectRatios": {
"label": "比例",
"options": [
{ "value": "1:1", "label": "1:1 (正方形)" },
{ "value": "3:4", "label": "3:4 (竖版)" },
{ "value": "4:3", "label": "4:3 (横版)" },
{ "value": "9:16", "label": "9:16 (手机竖版)" },
{ "value": "16:9", "label": "16:9 (宽屏)" }
],
"default": "16:9"
},
"resolutions": {
"label": "分辨率",
"options": [
{ "value": "720p", "label": "720P (1280x720)", "width": 1280, "height": 720 },
{ "value": "1080p", "label": "1080P (1920x1080)", "width": 1920, "height": 1080 }
],
"default": "1080p"
},
"durations": {
"label": "时长",
"options": [
{ "value": "2s", "label": "2秒" },
{ "value": "3s", "label": "3秒" },
{ "value": "4s", "label": "4秒" },
{ "value": "5s", "label": "5秒" },
{ "value": "6s", "label": "6秒" },
{ "value": "7s", "label": "7秒" },
{ "value": "8s", "label": "8秒" },
{ "value": "10s", "label": "10秒" }
],
"default": "5s",
"description": "视频时长(秒)"
},
"counts": {
"label": "生成数量",
"options": [
{ "value": 1, "label": "1个" },
{ "value": 2, "label": "2个" },
{ "value": 3, "label": "3个" },
{ "value": 4, "label": "4个" }
],
"default": 1,
"min": 1,
"max": 4
}
},
"audio": {
"durations": {
"label": "时长",
"options": [
{ "value": "5s", "label": "5秒" },
{ "value": "10s", "label": "10秒" },
{ "value": "30s", "label": "30秒" },
{ "value": "60s", "label": "1分钟" }
],
"default": "10s"
},
"formats": {
"label": "音频格式",
"options": [
{ "value": "mp3", "label": "MP3" },
{ "value": "wav", "label": "WAV" }
],
"default": "mp3"
}
},
"music": {
"formats": {
"label": "音频格式",
"options": [
{ "value": "mp3", "label": "MP3" },
{ "value": "wav", "label": "WAV" },
{ "value": "pcm", "label": "PCM" }
],
"default": "mp3"
},
"sampleRates": {
"label": "采样率",
"options": [
{ "value": 16000, "label": "16kHz" },
{ "value": 24000, "label": "24kHz" },
{ "value": 32000, "label": "32kHz" },
{ "value": 44100, "label": "44.1kHz" }
],
"default": 44100
},
"bitrates": {
"label": "码率",
"options": [
{ "value": 32000, "label": "32kbps" },
{ "value": 64000, "label": "64kbps" },
{ "value": 128000, "label": "128kbps" },
{ "value": 256000, "label": "256kbps" }
],
"default": 256000
},
"outputFormats": {
"label": "返回格式",
"options": [
{ "value": "url", "label": "URL (24小时有效)" },
{ "value": "hex", "label": "HEX" }
],
"default": "url"
}
},
"script": {
"movieTones": {
"label": "整体基调",
"options": [
{ "value": "悬疑/惊悚", "label": "悬疑/惊悚 (Suspense/Thriller)", "en": "Suspense/Thriller" },
{ "value": "古装/权谋", "label": "古装/权谋 (Historical/Political)", "en": "Historical/Political" },
{ "value": "现代/都市", "label": "现代/都市 (Modern/Urban)", "en": "Modern/Urban" },
{ "value": "科幻/未来", "label": "科幻/未来 (Sci-Fi/Future)", "en": "Sci-Fi/Future" },
{ "value": "喜剧/荒诞", "label": "喜剧/荒诞 (Comedy/Absurd)", "en": "Comedy/Absurd" },
{ "value": "动作/犯罪", "label": "动作/犯罪 (Action/Crime)", "en": "Action/Crime" },
{ "value": "爱情/治愈", "label": "爱情/治愈 (Romance/Healing)", "en": "Romance/Healing" },
{ "value": "奇幻/仙侠", "label": "奇幻/仙侠 (Fantasy/Xianxia)", "en": "Fantasy/Xianxia" },
{ "value": "现实/人文", "label": "现实/人文 (Realistic/Humanistic)", "en": "Realistic/Humanistic" }
],
"default": "现代/都市"
},
"targetAudiences": {
"label": "目标受众",
"options": [
{ "value": "全年龄段", "label": "全年龄段 (All Ages)", "en": "All Ages" },
{ "value": "青少年", "label": "青少年 (Teenagers)", "en": "Teenagers" },
{ "value": "年轻女性", "label": "年轻女性 (Young Women)", "en": "Young Women" },
{ "value": "年轻男性", "label": "年轻男性 (Young Men)", "en": "Young Men" },
{ "value": "成年观众", "label": "成年观众 (Adults)", "en": "Adults" },
{ "value": "家庭观众", "label": "家庭观众 (Family)", "en": "Family" },
{ "value": "资深影迷", "label": "资深影迷 (Cinephiles)", "en": "Cinephiles" }
],
"default": "全年龄段"
}
},
"director": {
"narrativeStyles": {
"label": "叙事手法",
"options": [
{ "value": "线性叙事", "label": "线性叙事 (Linear)", "en": "Linear Narrative" },
{ "value": "非线性/插叙", "label": "非线性/插叙 (Non-linear)", "en": "Non-linear Narrative" },
{ "value": "多线并行", "label": "多线并行 (Multi-line)", "en": "Multi-line Narrative" },
{ "value": "倒叙", "label": "倒叙 (Flashback)", "en": "Flashback" },
{ "value": "意识流", "label": "意识流 (Stream of Consciousness)", "en": "Stream of Consciousness" },
{ "value": "伪纪录片", "label": "伪纪录片 (Mockumentary)", "en": "Mockumentary" }
],
"default": "线性叙事"
},
"editingPaces": {
"label": "剪辑节奏",
"options": [
{ "value": "缓慢/沉浸", "label": "缓慢/沉浸 (Slow/Immersive)", "en": "Slow/Immersive" },
{ "value": "明快/流畅", "label": "明快/流畅 (Brisk/Fluid)", "en": "Brisk/Fluid" },
{ "value": "快速/凌厉", "label": "快速/凌厉 (Fast/Sharp)", "en": "Fast/Sharp" },
{ "value": "极速/碎片化", "label": "极速/碎片化 (Rapid/Fragmented)", "en": "Rapid/Fragmented" },
{ "value": "舒缓/诗意", "label": "舒缓/诗意 (Soothing/Poetic)", "en": "Soothing/Poetic" }
],
"default": "明快/流畅"
},
"styles": {
"label": "导演风格",
"options": [
{ "value": "孔笙 (Kong Sheng)", "label": "孔笙 (厚重/写实/山海情)", "en": "Kong Sheng Style" },
{ "value": "郑晓龙 (Zheng Xiaolong)", "label": "郑晓龙 (宫廷/传奇/甄嬛传)", "en": "Zheng Xiaolong Style" },
{ "value": "张黎 (Zhang Li)", "label": "张黎 (历史/权谋/大明王朝)", "en": "Zhang Li Style" },
{ "value": "辛爽 (Xin Shuang)", "label": "辛爽 (悬疑/美学/漫长的季节)", "en": "Xin Shuang Style" },
{ "value": "王家卫 (Wong Kar-wai)", "label": "王家卫 (繁花/光影/霓虹)", "en": "Wong Kar-wai Style" },
{ "value": "李路 (Li Lu)", "label": "李路 (史诗/人世间/人民的名义)", "en": "Li Lu Style" },
{ "value": "曹盾 (Cao Dun)", "label": "曹盾 (视觉/长镜头/长安十二时辰)", "en": "Cao Dun Style" },
{ "value": "王伟 (Wang Wei)", "label": "王伟 (硬汉/刑侦/白夜追凶)", "en": "Wang Wei Style" },
{ "value": "汪俊 (Wang Jun)", "label": "汪俊 (都市/细腻/小欢喜)", "en": "Wang Jun Style" },
{ "value": "徐纪周 (Xu Jizhou)", "label": "徐纪周 (群像/狂飙/快节奏)", "en": "Xu Jizhou Style" },
{ "value": "吕行 (Lu Xing)", "label": "吕行 (犯罪/人性/无证之罪)", "en": "Lu Xing Style" },
{ "value": "丁黑 (Ding Hei)", "label": "丁黑 (警察荣誉/那年花开)", "en": "Ding Hei Style" }
],
"default": "孔笙 (Kong Sheng)"
}
},
"character": {
"genders": {
"label": "性别",
"options": [
{ "value": "男", "label": "男" },
{ "value": "女", "label": "女" },
{ "value": "未知", "label": "未知" }
],
"default": "未知"
},
"costumeStyles": {
"label": "服装风格",
"options": [
{ "value": "现代日常", "label": "现代日常 (Modern Daily)", "en": "Modern Daily" },
{ "value": "古装汉服", "label": "古装汉服 (Ancient Hanfu)", "en": "Ancient Hanfu" },
{ "value": "民国风情", "label": "民国风情 (Republic Era)", "en": "Republic Era" },
{ "value": "赛博科幻", "label": "赛博科幻 (Cyberpunk Sci-Fi)", "en": "Cyberpunk Sci-Fi" },
{ "value": "职业制服", "label": "职业制服 (Professional Uniform)", "en": "Professional Uniform" },
{ "value": "街头潮流", "label": "街头潮流 (Streetwear)", "en": "Streetwear" },
{ "value": "极简森系", "label": "极简森系 (Minimalist Mori)", "en": "Minimalist Mori" },
{ "value": "奢华礼服", "label": "奢华礼服 (Luxury/Formal)", "en": "Luxury/Formal" }
],
"default": "现代日常"
},
"roles": {
"label": "角色定位",
"options": [
{ "value": "主角", "label": "主角" },
{ "value": "配角", "label": "配角" },
{ "value": "反派", "label": "反派" },
{ "value": "龙套", "label": "龙套" },
{ "value": "群演", "label": "群演" }
],
"default": "配角"
},
"emotions": {
"label": "情绪基调",
"options": [
{ "value": "平静", "label": "平静 (Neutral)", "en": "Neutral/Calm" },
{ "value": "喜悦", "label": "喜悦 (Happy)", "en": "Happy/Joyful" },
{ "value": "悲伤", "label": "悲伤 (Sad)", "en": "Sad/Sorrowful" },
{ "value": "愤怒", "label": "愤怒 (Angry)", "en": "Angry/Furious" },
{ "value": "恐惧", "label": "恐惧 (Fearful)", "en": "Fearful/Scared" },
{ "value": "惊讶", "label": "惊讶 (Surprised)", "en": "Surprised/Shocked" },
{ "value": "自信", "label": "自信 (Confident)", "en": "Confident/Bold" },
{ "value": "思索", "label": "思索 (Thinking)", "en": "Thinking/Pensive" }
],
"default": "平静"
}
},
"storyboard": {
"shotTypes": {
"label": "镜头类型",
"options": [
{ "value": "大远景 (ELS)", "label": "大远景 (ELS)", "en": "Extreme Long Shot (ELS)" },
{ "value": "远景 (LS)", "label": "远景 (LS)", "en": "Long Shot (LS)" },
{ "value": "全景 (FS)", "label": "全景 (FS)", "en": "Full Shot (FS)" },
{ "value": "中远景 (MLS)", "label": "中远景 (MLS)", "en": "Medium Long Shot (MLS)" },
{ "value": "中景 (MS)", "label": "中景 (MS)", "en": "Medium Shot (MS)" },
{ "value": "中特写 (MCU)", "label": "中特写 (MCU)", "en": "Medium Close-Up (MCU)" },
{ "value": "特写 (CU)", "label": "特写 (CU)", "en": "Close-Up (CU)" },
{ "value": "大特写 (ECU)", "label": "大特写 (ECU)", "en": "Extreme Close-Up (ECU)" },
{ "value": "建立镜头", "label": "建立镜头", "en": "Establishing Shot" },
{ "value": "主观镜头 (POV)", "label": "主观镜头 (POV)", "en": "Point of View (POV)" },
{ "value": "过肩镜头 (OTS)", "label": "过肩镜头 (OTS)", "en": "Over the Shoulder (OTS)" }
],
"default": "中景 (MS)"
},
"cameraMovements": {
"label": "运镜方式",
"options": [
{ "value": "固定镜头 (Static)", "label": "固定镜头 (Static)", "en": "Static" },
{ "value": "左摇 (Pan Left)", "label": "左摇 (Pan Left)", "en": "Pan Left" },
{ "value": "右摇 (Pan Right)", "label": "右摇 (Pan Right)", "en": "Pan Right" },
{ "value": "上仰 (Tilt Up)", "label": "上仰 (Tilt Up)", "en": "Tilt Up" },
{ "value": "下俯 (Tilt Down)", "label": "下俯 (Tilt Down)", "en": "Tilt Down" },
{ "value": "推镜头 (Zoom In)", "label": "推镜头 (Zoom In)", "en": "Zoom In" },
{ "value": "拉镜头 (Zoom Out)", "label": "拉镜头 (Zoom Out)", "en": "Zoom Out" },
{ "value": "前移 (Dolly In)", "label": "前移 (Dolly In)", "en": "Dolly In" },
{ "value": "后移 (Dolly Out)", "label": "后移 (Dolly Out)", "en": "Dolly Out" },
{ "value": "跟随 (Tracking)", "label": "跟随 (Tracking)", "en": "Tracking" },
{ "value": "环绕 (Arc)", "label": "环绕 (Arc)", "en": "Arc" },
{ "value": "手持 (Handheld)", "label": "手持 (Handheld)", "en": "Handheld" }
],
"default": "固定镜头 (Static)"
},
"transitions": {
"label": "转场效果",
"options": [
{ "value": "切 (Cut)", "label": "切 (Cut)", "en": "Cut" },
{ "value": "叠化 (Dissolve)", "label": "叠化 (Dissolve)", "en": "Dissolve" },
{ "value": "淡入 (Fade In)", "label": "淡入 (Fade In)", "en": "Fade In" },
{ "value": "淡出 (Fade Out)", "label": "淡出 (Fade Out)", "en": "Fade Out" },
{ "value": "划像 (Wipe)", "label": "划像 (Wipe)", "en": "Wipe" },
{ "value": "圈入 (Iris In)", "label": "圈入 (Iris In)", "en": "Iris In" },
{ "value": "圈出 (Iris Out)", "label": "圈出 (Iris Out)", "en": "Iris Out" },
{ "value": "匹配剪辑 (Match Cut)", "label": "匹配剪辑 (Match Cut)", "en": "Match Cut" },
{ "value": "跳接 (Jump Cut)", "label": "跳接 (Jump Cut)", "en": "Jump Cut" }
],
"default": "切 (Cut)"
},
"compositions": {
"label": "构图方式",
"options": [
{ "value": "三分法 (Rule of Thirds)", "label": "三分法 (Rule of Thirds)", "en": "Rule of Thirds" },
{ "value": "中心构图 (Center Framed)", "label": "中心构图 (Center Framed)", "en": "Center Framed" },
{ "value": "对称构图 (Symmetrical)", "label": "对称构图 (Symmetrical)", "en": "Symmetrical" },
{ "value": "引导线 (Leading Lines)", "label": "引导线 (Leading Lines)", "en": "Leading Lines" },
{ "value": "对角线 (Diagonal)", "label": "对角线 (Diagonal)", "en": "Diagonal" },
{ "value": "框架构图 (Framing)", "label": "框架构图 (Framing)", "en": "Framing" },
{ "value": "极简留白 (Minimalist/Negative Space)", "label": "极简留白 (Minimalist/Negative Space)", "en": "Minimalist/Negative Space" },
{ "value": "黄金螺旋 (Golden Spiral)", "label": "黄金螺旋 (Golden Spiral)", "en": "Golden Spiral" }
],
"default": "三分法 (Rule of Thirds)"
}
},
"scene": {
"timesOfDay": {
"label": "拍摄时段",
"options": [
{ "value": "清晨", "label": "清晨 (Dawn)", "en": "Dawn" },
{ "value": "早晨", "label": "早晨 (Morning)", "en": "Morning" },
{ "value": "正午", "label": "正午 (Noon)", "en": "Noon" },
{ "value": "下午", "label": "下午 (Afternoon)", "en": "Afternoon" },
{ "value": "黄金时刻", "label": "黄金时刻 (Golden Hour)", "en": "Golden Hour" },
{ "value": "傍晚", "label": "傍晚 (Dusk)", "en": "Dusk" },
{ "value": "蓝调时刻", "label": "蓝调时刻 (Blue Hour)", "en": "Blue Hour" },
{ "value": "夜晚", "label": "夜晚 (Night)", "en": "Night" },
{ "value": "深夜", "label": "深夜 (Late Night)", "en": "Late Night" }
],
"default": "早晨"
},
"environmentTypes": {
"label": "空间类型",
"options": [
{ "value": "室内", "label": "室内 (Interior)", "en": "Interior" },
{ "value": "室外", "label": "室外 (Exterior)", "en": "Exterior" },
{ "value": "半室外", "label": "半室外 (Semi-Exterior)", "en": "Semi-Exterior" }
],
"default": "室内"
},
"weather": {
"label": "天气环境",
"options": [
{ "value": "晴朗", "label": "晴朗 (Clear)", "en": "Clear/Sunny" },
{ "value": "多云", "label": "多云 (Cloudy)", "en": "Partly Cloudy" },
{ "value": "阴天", "label": "阴天 (Overcast)", "en": "Overcast" },
{ "value": "小雨", "label": "小雨 (Rainy)", "en": "Light Rain" },
{ "value": "大雨", "label": "大雨 (Heavy Rain)", "en": "Heavy Rain" },
{ "value": "暴风雨", "label": "暴风雨 (Storm)", "en": "Storm" },
{ "value": "小雪", "label": "小雪 (Snowy)", "en": "Light Snow" },
{ "value": "大雪", "label": "大雪 (Heavy Snow)", "en": "Heavy Snow" },
{ "value": "大雾", "label": "大雾 (Foggy)", "en": "Dense Fog" },
{ "value": "沙尘", "label": "沙尘 (Dusty)", "en": "Dusty/Sandstorm" }
],
"default": "晴朗"
}
},
"cinematic": {
"visualStyles": {
"label": "视觉画风",
"options": [
{ "value": "现实主义/纪录片感", "label": "现实主义/纪录片感 (Realistic/Documentary)", "en": "Realistic/Documentary" },
{ "value": "电影质感/胶片风", "label": "电影质感/胶片风 (Cinematic/Film)", "en": "Cinematic/Film" },
{ "value": "赛博朋克/霓虹", "label": "赛博朋克/霓虹 (Cyberpunk/Neon)", "en": "Cyberpunk/Neon" },
{ "value": "古风/水墨", "label": "古风/水墨 (Ancient/Ink Wash)", "en": "Ancient/Ink Wash" },
{ "value": "极简主义/冷淡", "label": "极简主义/冷淡 (Minimalist/Cold)", "en": "Minimalist/Cold" },
{ "value": "唯美/梦幻", "label": "唯美/梦幻 (Aesthetic/Dreamy)", "en": "Aesthetic/Dreamy" },
{ "value": "暗黑/哥特", "label": "暗黑/哥特 (Dark/Gothic)", "en": "Dark/Gothic" },
{ "value": "动画/二次元", "label": "动画/二次元 (Anime/2D)", "en": "Anime/2D" }
],
"default": "电影质感/胶片风"
},
"cameraAngles": {
"label": "镜头角度",
"options": [
{ "value": "平视", "label": "平视 (Eye Level)", "en": "Eye Level" },
{ "value": "俯拍", "label": "俯拍 (High Angle)", "en": "High Angle" },
{ "value": "仰拍", "label": "仰拍 (Low Angle)", "en": "Low Angle" },
{ "value": "顶拍", "label": "顶拍 (Top Down)", "en": "Top Down/Bird's Eye" },
{ "value": "底拍", "label": "底拍 (Worm's Eye)", "en": "Worm's Eye View" },
{ "value": "斜角镜头", "label": "斜角镜头 (Dutch Angle)", "en": "Dutch Angle" }
],
"default": "平视"
},
"lighting": {
"label": "灯光风格",
"options": [
{ "value": "电影感光效", "label": "电影感 (Cinematic)", "en": "Cinematic Lighting" },
{ "value": "自然光", "label": "自然光 (Natural)", "en": "Natural Lighting" },
{ "value": "柔光", "label": "柔光 (Soft)", "en": "Soft Lighting" },
{ "value": "强反差/明暗对照", "label": "强反差 (High Contrast)", "en": "Chiaroscuro/High Contrast" },
{ "value": "轮廓光", "label": "轮廓光 (Rim Lighting)", "en": "Rim Lighting" },
{ "value": "三点式亮光", "label": "三点式亮光 (Three-point Lighting)", "en": "Three-point Lighting" },
{ "value": "工作室光效", "label": "工作室 (Studio)", "en": "Studio Lighting" }
],
"default": "电影感光效"
},
"colorStyle": {
"label": "色调氛围",
"options": [
{ "value": "电影感", "label": "电影感 (Cinematic)", "en": "Cinematic" },
{ "value": "暖色调", "label": "暖色调 (Warm Tones)", "en": "Warm Tones" },
{ "value": "冷色调", "label": "冷色调 (Cold Tones)", "en": "Cold Tones" },
{ "value": "黑白", "label": "黑白 (Black and White)", "en": "Black and White" },
{ "value": "复古/胶片感", "label": "复古/胶片 (Vintage)", "en": "Vintage Film" },
{ "value": "赛博朋克", "label": "赛博朋克 (Cyberpunk)", "en": "Cyberpunk" },
{ "value": "高饱和", "label": "高饱和 (Vibrant)", "en": "Vibrant" },
{ "value": "低饱和/灰色调", "label": "低饱和 (Muted)", "en": "Muted/Desaturated" }
],
"default": "电影感"
},
"lenses": {
"label": "镜头焦距",
"options": [
{ "value": "广角镜头", "label": "超广角 (14-24mm)", "en": "Ultra Wide Lens" },
{ "value": "标准广角", "label": "广角 (35mm)", "en": "Wide Angle Lens" },
{ "value": "标准镜头", "label": "标准 (50mm)", "en": "Standard/Nifty Fifty" },
{ "value": "人像镜头", "label": "长焦 (85mm)", "en": "Portrait/Short Telephoto" },
{ "value": "远摄镜头", "label": "超长焦 (200mm+)", "en": "Telephoto Lens" },
{ "value": "鱼眼镜头", "label": "鱼眼 (Fisheye)", "en": "Fisheye Lens" },
{ "value": "变焦镜头", "label": "变焦 (Anamorphic)", "en": "Anamorphic Lens" }
],
"default": "标准镜头"
},
"focus": {
"label": "焦点控制",
"options": [
{ "value": "自动对焦", "label": "自动对焦 (Auto)", "en": "Auto Focus" },
{ "value": "浅景深/虚化", "label": "浅景深 (Shallow Bokeh)", "en": "Shallow Depth of Field" },
{ "value": "大深景", "label": "大深景 (Deep Focus)", "en": "Deep Depth of Field" },
{ "value": "焦点转移", "label": "变焦对焦 (Rack Focus)", "en": "Rack Focus" },
{ "value": "微距焦点", "label": "微距 (Macro)", "en": "Macro Focus" },
{ "value": "移轴效果", "label": "移轴 (Tilt-Shift)", "en": "Tilt-Shift" }
],
"default": "自动对焦"
}
}
}

View File

@@ -0,0 +1,16 @@
{
"roles": {
"story_architect": "moonshot-v1-8k",
"character_consultant": "moonshot-v1-8k",
"scriptwriter": "moonshot-v1-8k",
"director": "moonshot-v1-8k",
"auditor": "moonshot-v1-8k",
"moderator": "moonshot-v1-8k",
"psychologist": "moonshot-v1-8k",
"visualizer": "moonshot-v1-8k",
"continuity_manager": "moonshot-v1-8k",
"showrunner": "moonshot-v1-8k",
"chief_editor": "moonshot-v1-8k",
"specialist": "moonshot-v1-8k"
}
}

View File

@@ -0,0 +1,5 @@
{
"id": "aliyun",
"name": "阿里云",
"description": "阿里云提供的包括图像超分、视频超分等服务"
}

View File

@@ -0,0 +1,8 @@
{
"videoenhan": {
"name": "阿里巴巴图像超分",
"class": "backend.src.services.post_process.super_resolution.SuperResolutionService",
"args": [],
"enabled": true
}
}

View File

@@ -0,0 +1,16 @@
{
"id": "anthropic",
"name": "Anthropic",
"description": "Claude 系列模型",
"dashboard_url": "https://console.anthropic.com/settings/keys",
"helpUrl": "https://console.anthropic.com/settings/keys",
"fields": [
{
"name": "apiKey",
"label": "API Key",
"placeholder": "sk-ant-...",
"required": true,
"type": "password"
}
]
}

View File

@@ -0,0 +1,488 @@
{
"cosyvoice-v3-plus": {
"name": "CosyVoice-V3-Plus",
"class": "backend.src.services.provider.dashscope.audio.DashScopeAudioService",
"args": ["cosyvoice-v3-plus"],
"voices": [
{
"id": "longanyang",
"name": "龙安洋",
"gender": "male",
"desc": "阳光大男孩"
},
{
"id": "longanhuan",
"name": "龙安欢",
"gender": "female",
"desc": "欢脱元气女"
},
{
"id": "longhuhu_v3",
"name": "龙呼呼",
"gender": "female",
"desc": "天真烂漫女童"
},
{
"id": "longpaopao_v3",
"name": "龙泡泡",
"gender": "female",
"desc": "飞天泡泡音"
},
{
"id": "longjielidou_v3",
"name": "龙杰力豆",
"gender": "male",
"desc": "阳光顽皮男童"
},
{
"id": "longxian_v3",
"name": "龙仙",
"gender": "female",
"desc": "豪放可爱女童"
},
{
"id": "longling_v3",
"name": "龙铃",
"gender": "female",
"desc": "稚气呆板女童"
},
{
"id": "longshanshan_v3",
"name": "龙闪闪",
"gender": "female",
"desc": "戏剧化童声"
},
{
"id": "longniuniu_v3",
"name": "龙牛牛",
"gender": "male",
"desc": "阳光男童声"
},
{
"id": "longjiaxin_v3",
"name": "龙嘉欣",
"gender": "female",
"desc": "优雅粤语女"
},
{
"id": "longjiayi_v3",
"name": "龙嘉怡",
"gender": "female",
"desc": "知性粤语女"
},
{
"id": "longanyue_v3",
"name": "龙安粤",
"gender": "male",
"desc": "欢脱粤语男"
},
{
"id": "longlaotie_v3",
"name": "龙老铁",
"gender": "male",
"desc": "东北直率男"
},
{
"id": "longshange_v3",
"name": "龙陕哥",
"gender": "male",
"desc": "原味陕北男"
},
{
"id": "longanmin_v3",
"name": "龙安闽",
"gender": "female",
"desc": "清纯闽南女"
},
{
"id": "loongkyong_v3",
"name": "loongkyong",
"gender": "female",
"desc": "韩语女"
},
{
"id": "loongriko_v3",
"name": "Riko",
"gender": "female",
"desc": "二次元日语女"
},
{
"id": "loongtomoka_v3",
"name": "loongtomoka",
"gender": "female",
"desc": "日语女"
},
{
"id": "longfei_v3",
"name": "龙飞",
"gender": "male",
"desc": "热血磁性男"
},
{
"id": "longxiaochun_v3",
"name": "龙小淳",
"gender": "female",
"desc": "清丽温柔女"
},
{
"id": "longxiaoxia_v3",
"name": "龙小夏",
"gender": "female",
"desc": "活泼甜美女"
},
{
"id": "longshu_v3",
"name": "龙舒",
"gender": "female",
"desc": "知性温婉女"
},
{
"id": "longyue_v3",
"name": "龙悦",
"gender": "male",
"desc": "阳光青年男"
},
{
"id": "longcheng_v3",
"name": "龙城",
"gender": "male",
"desc": "成熟稳重男"
},
{
"id": "longhua_v3",
"name": "龙华",
"gender": "male",
"desc": "标准男声"
},
{
"id": "longwan_v3",
"name": "龙婉",
"gender": "female",
"desc": "温婉知性女"
},
{
"id": "longjing_v3",
"name": "龙静",
"gender": "female",
"desc": "标准女声"
},
{
"id": "longmiao_v3",
"name": "龙淼",
"gender": "female",
"desc": "标准女声"
},
{
"id": "longshuo_v3",
"name": "龙硕",
"gender": "male",
"desc": "标准男声"
},
{
"id": "longxiang_v3",
"name": "龙翔",
"gender": "male",
"desc": "标准男声"
},
{
"id": "longyuan_v3",
"name": "龙源",
"gender": "male",
"desc": "标准男声"
}
],
"enabled": true
},
"qwen3-tts-flash": {
"name": "Qwen3-TTS-Flash",
"class": "backend.src.services.provider.dashscope.audio.DashScopeAudioService",
"args": ["qwen3-tts-flash"],
"voices": [
{
"id": "Cherry",
"name": "芊悦",
"gender": "female",
"desc": "阳光积极、亲切自然小姐姐"
},
{
"id": "Serena",
"name": "苏瑶",
"gender": "female",
"desc": "温柔小姐姐"
},
{
"id": "Ethan",
"name": "晨煦",
"gender": "male",
"desc": "阳光、温暖、活力、朝气"
},
{
"id": "Chelsie",
"name": "千雪",
"gender": "female",
"desc": "二次元虚拟女友"
},
{
"id": "Momo",
"name": "茉兔",
"gender": "female",
"desc": "撒娇搞怪,逗你开心"
},
{
"id": "Vivian",
"name": "十三",
"gender": "female",
"desc": "拽拽的、可爱的小暴躁"
},
{ "id": "Moon", "name": "月白", "gender": "male", "desc": "率性帅气" },
{
"id": "Maia",
"name": "四月",
"gender": "female",
"desc": "知性与温柔的碰撞"
},
{ "id": "Kai", "name": "凯", "gender": "male", "desc": "耳朵的一场SPA" },
{
"id": "Nofish",
"name": "不吃鱼",
"gender": "male",
"desc": "不会翘舌音的设计师"
},
{
"id": "Bella",
"name": "萌宝",
"gender": "female",
"desc": "喝酒不打醉拳的小萝莉"
},
{
"id": "Jennifer",
"name": "詹妮弗",
"gender": "female",
"desc": "品牌级、电影质感般美语女声"
},
{
"id": "Ryan",
"name": "甜茶",
"gender": "male",
"desc": "节奏拉满,戏感炸裂"
},
{
"id": "Katerina",
"name": "卡捷琳娜",
"gender": "female",
"desc": "御姐音色,韵律回味十足"
},
{
"id": "Aiden",
"name": "艾登",
"gender": "male",
"desc": "精通厨艺的美语大男孩"
},
{
"id": "Eldric Sage",
"name": "沧明子",
"gender": "male",
"desc": "沉稳睿智的老者"
},
{
"id": "Mia",
"name": "乖小妹",
"gender": "female",
"desc": "温顺如春水,乖巧如初雪"
},
{
"id": "Mochi",
"name": "沙小弥",
"gender": "male",
"desc": "聪明伶俐的小大人"
},
{
"id": "Bellona",
"name": "燕铮莺",
"gender": "female",
"desc": "金戈铁马,千面人声"
},
{
"id": "Vincent",
"name": "田叔",
"gender": "male",
"desc": "沙哑烟嗓,江湖豪情"
},
{
"id": "Bunny",
"name": "萌小姬",
"gender": "female",
"desc": "萌属性爆棚的小萝莉"
},
{
"id": "Neil",
"name": "阿闻",
"gender": "male",
"desc": "字正腔圆的新闻主持人"
},
{
"id": "Elias",
"name": "墨讲师",
"gender": "female",
"desc": "严谨又通俗的知识讲解"
},
{
"id": "Arthur",
"name": "徐大爷",
"gender": "male",
"desc": "质朴嗓音,奇闻异事"
},
{
"id": "Nini",
"name": "邻家妹妹",
"gender": "female",
"desc": "又软又黏的甜蜜嗓音"
},
{
"id": "Ebona",
"name": "诡婆婆",
"gender": "female",
"desc": "幽暗低语,神秘诡异"
},
{
"id": "Seren",
"name": "小婉",
"gender": "female",
"desc": "温和舒缓,助眠音色"
},
{
"id": "Pip",
"name": "顽屁小孩",
"gender": "male",
"desc": "调皮捣蛋却充满童真"
},
{
"id": "Stella",
"name": "少女阿月",
"gender": "female",
"desc": "甜到发腻的迷糊少女音"
},
{
"id": "Bodega",
"name": "博德加",
"gender": "male",
"desc": "热情的西班牙大叔"
},
{
"id": "Sonrisa",
"name": "索尼莎",
"gender": "female",
"desc": "热情开朗的拉美大姐"
},
{
"id": "Alek",
"name": "阿列克",
"gender": "male",
"desc": "战斗民族的冷与暖"
},
{
"id": "Dolce",
"name": "多尔切",
"gender": "male",
"desc": "慵懒的意大利大叔"
},
{
"id": "Sohee",
"name": "素熙",
"gender": "female",
"desc": "温柔开朗的韩国欧尼"
},
{
"id": "Ono Anna",
"name": "小野杏",
"gender": "female",
"desc": "鬼灵精怪的青梅竹马"
},
{
"id": "Lenn",
"name": "莱恩",
"gender": "male",
"desc": "理性底色的德国青年"
},
{
"id": "Emilien",
"name": "埃米尔安",
"gender": "male",
"desc": "浪漫的法国大哥哥"
},
{
"id": "Andre",
"name": "安德雷",
"gender": "male",
"desc": "声音磁性,沉稳男生"
},
{
"id": "Radio Gol",
"name": "拉迪奥·戈尔",
"gender": "male",
"desc": "足球诗人解说员"
},
{
"id": "Jada",
"name": "上海-阿珍",
"gender": "female",
"desc": "风风火火的沪上阿姐"
},
{
"id": "Dylan",
"name": "北京-晓东",
"gender": "male",
"desc": "北京胡同里长大的少年"
},
{
"id": "Li",
"name": "南京-老李",
"gender": "male",
"desc": "耐心的瑜伽老师"
},
{
"id": "Marcus",
"name": "陕西-秦川",
"gender": "male",
"desc": "面宽话短,心实声沉"
},
{
"id": "Roy",
"name": "闽南-阿杰",
"gender": "male",
"desc": "诙谐直爽的台湾哥仔"
},
{
"id": "Peter",
"name": "天津-李彼得",
"gender": "male",
"desc": "天津相声,专业捧哏"
},
{
"id": "Sunny",
"name": "四川-晴儿",
"gender": "female",
"desc": "甜到你心里的川妹子"
},
{
"id": "Eric",
"name": "四川-程川",
"gender": "male",
"desc": "跳脱市井的成都男子"
},
{
"id": "Rocky",
"name": "粤语-阿强",
"gender": "male",
"desc": "幽默风趣,在线陪聊"
},
{
"id": "Kiki",
"name": "粤语-阿清",
"gender": "female",
"desc": "甜美的港妹闺蜜"
}
],
"enabled": true
}
}

View File

@@ -0,0 +1,143 @@
{
"z-image": {
"name": "Z-Image",
"class": "backend.src.services.provider.dashscope.image.ZImageService",
"args": [
"z-image"
],
"capabilities": {
"supportsRefImage": false,
"supportsLora": false
},
"variants": {
"t2i": "z-image-turbo"
},
"resolutions": {
"1K": {
"16:9": "1536*864",
"9:16": "864*1536",
"1:1": "1280*1280",
"4:3": "1280*960",
"3:4": "960*1280",
"21:9": "1680*720",
"9:21": "720*1680"
},
"2K": {
"16:9": "2048*1152",
"9:16": "1152*2048",
"21:9": "2016*864",
"9:21": "864*2016"
}
},
"counts": {
"min": 1,
"max": 4
},
"enabled": true
},
"wan2.6-image": {
"name": "Wan 2.6",
"class": "backend.src.services.provider.dashscope.image.WanImageService",
"args": [
"wan2.6-image"
],
"capabilities": {
"supportsRefImage": true,
"supportsLora": false
},
"variants": {
"t2i": "wan2.6-t2i",
"i2i": "wan2.6-image"
},
"resolutions": {
"1K": {
"16:9": "1280*720",
"9:16": "720*1280",
"1:1": "1280*1280",
"4:3": "1280*960",
"3:4": "960*1280"
},
"2K": {
"16:9": "2560*1440",
"9:16": "1440*2560",
"1:1": "2048*2048",
"4:3": "2560*1920",
"3:4": "1920*2560"
}
},
"counts": {
"min": 1,
"max": 4
},
"enabled": true
},
"wan2.5-image": {
"name": "Wan 2.5",
"class": "backend.src.services.provider.dashscope.image.WanImageService",
"args": [
"wan2.5-image"
],
"capabilities": {
"supportsRefImage": true,
"supportsLora": false
},
"variants": {
"t2i": "wan2.5-t2i-preview",
"i2i": "wan2.5-i2i-preview"
},
"resolutions": {
"1K": {
"16:9": "1280*720",
"9:16": "720*1280",
"1:1": "1280*1280",
"4:3": "1280*960",
"3:4": "960*1280"
},
"2K": {
"16:9": "2560*1440",
"9:16": "1440*2560",
"1:1": "2048*2048",
"4:3": "2560*1920",
"3:4": "1920*2560"
}
},
"counts": {
"min": 1,
"max": 4
},
"enabled": true
},
"qwen-image": {
"name": "Qwen Image",
"class": "backend.src.services.provider.dashscope.image.QwenImageService",
"args": [
"qwen-image"
],
"capabilities": {
"supportsRefImage": true,
"supportsLora": false
},
"variants": {
"t2i": "qwen-image-plus",
"i2i": "qwen-image-edit-plus"
},
"resolutions": {
"1K": {
"16:9": "1664*928",
"9:16": "928*1664",
"1:1": "1328*1328",
"4:3": "1472*1140",
"3:4": "1140*1472"
},
"2K": {
"16:9": "2560*1440",
"9:16": "1440*2560",
"1:1": "2048*2048",
"4:3": "2560*1920",
"3:4": "1920*2560"
}
},
"counts": {"min": 1, "max": 4},
"enabled": true
}
}

View File

@@ -0,0 +1,39 @@
{
"base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
"qwen-plus": {
"name": "Qwen Plus",
"class": "backend.src.services.provider.openai_service.OpenAIService",
"args": ["qwen-plus"],
"enabled": true
},
"qwen3-max": {
"name": "Qwen Max",
"class": "backend.src.services.provider.openai_service.OpenAIService",
"args": ["qwen3-max"],
"enabled": true
},
"qwen-flash": {
"name": "Qwen Flash",
"class": "backend.src.services.provider.openai_service.OpenAIService",
"args": ["qwen-flash"],
"enabled": true
},
"deepseek": {
"name": "Deepseek",
"class": "backend.src.services.provider.openai_service.OpenAIService",
"args": ["deepseek-v3.2"],
"enabled": true
},
"kimi-k2.5": {
"name": "Kimi K2.5",
"class": "backend.src.services.provider.openai_service.OpenAIService",
"args": ["kimi-k2.5"],
"enabled": true
},
"MiniMax-M2.1": {
"name": "MiniMax M2.1",
"class": "backend.src.services.provider.openai_service.OpenAIService",
"args": ["MiniMax-M2.1"],
"enabled": true
}
}

View File

@@ -0,0 +1,16 @@
{
"id": "dashscope",
"name": "阿里云百炼",
"description": "阿里云提供的大模型服务",
"dashboard_url": "https://dashscope.console.aliyun.com/",
"helpUrl": "https://dashscope.console.aliyun.com/apiKey",
"fields": [
{
"name": "apiKey",
"label": "API Key",
"placeholder": "sk-...",
"required": true,
"type": "password"
}
]
}

View File

@@ -0,0 +1,196 @@
{
"wan2.6-video": {
"name": "Wan 2.6",
"class": "backend.src.services.provider.dashscope.video.WanVideoService",
"args": [
"wan2.6-video"
],
"capabilities": {
"supportsTextToVideo": true,
"supportsImageToVideo": true,
"supportsVideoToVideo": true,
"supportsFirstFrame": true,
"supportsLastFrame": false,
"supportsMultiImage": true,
"supportsMultiVideo": true,
"supportsAudio": true,
"supportsShotType": true,
"supportsNegativePrompt": true,
"supportsLora": false
},
"variants": {
"t2v": "wan2.6-t2v",
"i2v": "wan2.6-i2v",
"r2v": "wan2.6-r2v"
},
"resolutions": {
"720P": {
"16:9": "1280*720",
"9:16": "720*1280",
"1:1": "1280*1280",
"4:3": "1280*960",
"3:4": "960*1280"
},
"1080P": {
"16:9": "1920*1080",
"9:16": "1080*1920",
"1:1": "1920*1920",
"4:3": "1920*1440",
"3:4": "1440*1920"
}
},
"durations": {
"min": 2,
"max": 10
},
"counts": {
"min": 1,
"max": 4
},
"enabled": true
},
"wan2.6-video-flash": {
"name": "Wan 2.6 Flash",
"class": "backend.src.services.provider.dashscope.video.WanVideoService",
"args": [
"wan2.6-video-flash"
],
"capabilities": {
"supportsTextToVideo": true,
"supportsImageToVideo": true,
"supportsVideoToVideo": true,
"supportsFirstFrame": true,
"supportsLastFrame": false,
"supportsMultiImage": true,
"supportsMultiVideo": true,
"supportsAudio": true,
"supportsShotType": true,
"supportsNegativePrompt": true,
"supportsLora": false
},
"variants": {
"t2v": "wan2.6-t2v",
"i2v": "wan2.6-i2v-flash",
"r2v": "wan2.6-r2v-flash"
},
"resolutions": {
"720P": {
"16:9": "1280*720",
"9:16": "720*1280",
"1:1": "1280*1280",
"4:3": "1280*960",
"3:4": "960*1280"
},
"1080P": {
"16:9": "1920*1080",
"9:16": "1080*1920",
"1:1": "1920*1920",
"4:3": "1920*1440",
"3:4": "1440*1920"
}
},
"durations": {
"min": 2,
"max": 10
},
"counts": {
"min": 1,
"max": 4
},
"enabled": true
},
"wan2.5-video": {
"name": "Wan 2.5",
"class": "backend.src.services.provider.dashscope.video.WanVideoService",
"args": [
"wan2.5-video"
],
"capabilities": {
"supportsTextToVideo": true,
"supportsImageToVideo": true,
"supportsFirstFrame": true,
"supportsLastFrame": false,
"supportsMultiImage": false,
"supportsMultiVideo": false,
"supportsLora": false
},
"variants": {
"t2v": "wan2.5-t2v-preview",
"i2v": "wan2.5-i2v-preview"
},
"resolutions": {
"720P": {
"16:9": "1280*720",
"9:16": "720*1280",
"1:1": "1280*1280",
"4:3": "1280*960",
"3:4": "960*1280"
},
"1080P": {
"16:9": "1920*1080",
"9:16": "1080*1920",
"1:1": "1920*1920",
"4:3": "1920*1440",
"3:4": "1440*1920"
}
},
"durations": {
"values": [
5,
10
]
},
"counts": {
"min": 1,
"max": 4
},
"enabled": true
},
"wan2.2-video": {
"name": "Wan 2.2",
"class": "backend.src.services.provider.dashscope.video.WanVideoService",
"args": [
"wan2.2-video"
],
"capabilities": {
"supportsTextToVideo": true,
"supportsImageToVideo": true,
"supportsFirstFrame": true,
"supportsLastFrame": true,
"supportsMultiImage": false,
"supportsMultiVideo": false,
"supportsLora": false
},
"variants": {
"t2v": "wan2.2-t2v-plus",
"i2v": "wan2.2-i2v-flash",
"kf2v": "wan2.2-kf2v-flash"
},
"resolutions": {
"720P": {
"16:9": "1280*720",
"9:16": "720*1280",
"1:1": "1280*1280",
"4:3": "1280*960",
"3:4": "960*1280"
},
"1080P": {
"16:9": "1920*1080",
"9:16": "1080*1920",
"1:1": "1920*1920",
"4:3": "1920*1440",
"3:4": "1440*1920"
}
},
"durations": {
"values": [
5
]
},
"counts": {
"min": 1,
"max": 4
},
"enabled": true
}
}

View File

@@ -0,0 +1,7 @@
{
"llm": "qwen-plus",
"image": "z-image",
"video": "wan2.6-video",
"audio": "qwen3-tts-flash",
"upscale": "ali-videoenhan/videoenhan"
}

View File

@@ -0,0 +1,27 @@
{
"base_url": "https://generativelanguage.googleapis.com/v1beta/openai/",
"gemini-1.5-pro": {
"name": "Gemini-1.5-Pro",
"class": "backend.src.services.provider.openai_service.OpenAIService",
"args": [
"gemini-1.5-pro"
],
"enabled": false
},
"gemini-1.5-flash": {
"name": "Gemini-1.5-Flash",
"class": "backend.src.services.provider.openai_service.OpenAIService",
"args": [
"gemini-1.5-flash"
],
"enabled": false
},
"gemini-2.0-flash": {
"name": "Gemini-2.0-Flash",
"class": "backend.src.services.provider.openai_service.OpenAIService",
"args": [
"gemini-2.0-flash"
],
"enabled": false
}
}

View File

@@ -0,0 +1,16 @@
{
"id": "google",
"name": "Google",
"description": "Gemini 系列模型",
"dashboard_url": "https://aistudio.google.com/app/apikey",
"helpUrl": "https://aistudio.google.com/app/apikey",
"fields": [
{
"name": "apiKey",
"label": "API Key",
"placeholder": "...",
"required": true,
"type": "password"
}
]
}

View File

@@ -0,0 +1,27 @@
{
"id": "kling",
"name": "可灵 AI",
"description": "快手视频生成 - 需要 Access Key 和 Secret Key",
"dashboard_url": "https://klingai.kuaishou.com/",
"param_mapping": {
"api_key": "access_key",
"api_secret": "secret_key"
},
"helpUrl": "https://klingai.kuaishou.com/",
"fields": [
{
"name": "accessKey",
"label": "Access Key",
"placeholder": "Access Key",
"required": true,
"type": "text"
},
{
"name": "secretKey",
"label": "Secret Key",
"placeholder": "Secret Key",
"required": true,
"type": "password"
}
]
}

View File

@@ -0,0 +1,124 @@
{
"kling-v2-5-turbo": {
"name": "Kling V2.5 Turbo",
"class": "src.services.provider.kling.KlingVideoService",
"args": [
"kling-v2-5-turbo"
],
"capabilities": {
"supportsTextToVideo": true,
"supportsImageToVideo": true,
"supportsFirstFrame": true,
"supportsLastFrame": true,
"supportsMultiImage": false,
"supportsMultiVideo": false,
"supportsAudio": false,
"supportsNegativePrompt": true,
"supportsCameraControl": true,
"supportsLora": false
},
"variants": {
"t2v": "kling-v2-5-turbo",
"i2v": "kling-v2-5-turbo",
"kf2v": "kling-v2-5-turbo"
},
"modes": ["std", "pro"],
"resolutions": {
"720P": {
"16:9": "1280*720",
"9:16": "720*1280",
"1:1": "1024*1024"
},
"1080P": {
"16:9": "1920*1080",
"9:16": "1080*1920",
"1:1": "1024*1024"
}
},
"durations": {
"values": [5, 10]
},
"counts": {"min": 1, "max": 4},
"enabled": true
},
"kling-v2-6": {
"name": "Kling V2.6",
"class": "src.services.provider.kling.KlingVideoService",
"args": [
"kling-v2-6"
],
"capabilities": {
"supportsTextToVideo": true,
"supportsImageToVideo": true,
"supportsFirstFrame": true,
"supportsLastFrame": true,
"supportsMultiImage": false,
"supportsMultiVideo": false,
"supportsAudio": true,
"supportsNegativePrompt": true,
"supportsCameraControl": true,
"supportsLora": false
},
"variants": {
"t2v": "kling-v2-6",
"i2v": "kling-v2-6",
"kf2v": "kling-v2-6"
},
"modes": ["pro"],
"resolutions": {
"720P": {
"16:9": "1280*720",
"9:16": "720*1280",
"1:1": "1024*1024"
},
"1080P": {
"16:9": "1920*1080",
"9:16": "1080*1920",
"1:1": "1024*1024"
}
},
"durations": {
"values": [5, 10]
},
"counts": {"min": 1, "max": 4},
"enabled": true
},
"kling-video-o1": {
"name": "Kling Omni (O1)",
"class": "src.services.provider.kling.KlingVideoService",
"args": [
"kling-video-o1"
],
"capabilities": {
"supportsTextToVideo": true,
"supportsImageToVideo": true,
"supportsVideoToVideo": true,
"supportsFirstFrame": true,
"supportsLastFrame": true,
"supportsMultiImage": true,
"supportsMultiVideo": true,
"supportsAudio": true,
"supportsNegativePrompt": true,
"supportsLora": false
},
"variants": {
"t2v": "kling-video-o1",
"i2v": "kling-video-o1",
"v2v": "kling-video-o1",
"kf2v": "kling-video-o1"
},
"resolutions": {
"720P": {
"16:9": "1280*720",
"9:16": "720*1280",
"1:1": "1024*1024"
}
},
"durations": {
"min": 3,
"max": 10
},
"counts": {"min": 1, "max": 4},
"enabled": true
}
}

View File

@@ -0,0 +1,34 @@
{
"midjourney": {
"name": "Midjourney",
"class": "src.services.provider.midjourney.MidjourneyImageService",
"args": [
"midjourney"
],
"capabilities": {
"supportsRefImage": false,
"supportsLora": false
},
"variants": {
"t2i": "midjourney"
},
"resolutions": {
"1K": {
"1:1": "1024*1024",
"16:9": "1280*720",
"9:16": "720*1280",
"4:3": "1280*960",
"3:4": "960*1280"
},
"2K": {
"1:1": "1456*1456",
"16:9": "1456*816",
"9:16": "816*1456",
"4:3": "1232*928",
"3:4": "928*1232"
}
},
"counts": {"min": 1, "max": 4},
"enabled": false
}
}

View File

@@ -0,0 +1,23 @@
{
"id": "midjourney",
"name": "Midjourney悠船",
"description": "悠船 API - 需要 App ID 和 Secret Key",
"dashboard_url": "https://ali.youchuan.cn/",
"helpUrl": "https://ali.youchuan.cn/",
"fields": [
{
"name": "apiKey",
"label": "App ID",
"placeholder": "应用 ID",
"required": true,
"type": "text"
},
{
"name": "apiSecret",
"label": "Secret Key",
"placeholder": "密钥",
"required": true,
"type": "password"
}
]
}

View File

@@ -0,0 +1,378 @@
{
"speech-2.8-hd": {
"name": "speech-2.8-hd",
"class": "src.services.provider.minimax.MiniMaxAudioService",
"args": [
"speech-2.8-hd"
],
"voices": [
{
"id": "male-qn-qingse",
"name": "青涩青年",
"gender": "male",
"desc": "青涩青年风格中文普通话男声"
},
{
"id": "male-qn-jingying",
"name": "精英青年",
"gender": "male",
"desc": "精英青年风格中文普通话男声"
},
{
"id": "male-qn-badao",
"name": "霸道青年",
"gender": "male",
"desc": "沉稳有力的中文普通话青年男声"
},
{
"id": "male-qn-daxuesheng",
"name": "青年大学生",
"gender": "male",
"desc": "青年大学生风格中文普通话男声"
},
{
"id": "female-shaonv",
"name": "少女",
"gender": "female",
"desc": "清亮少女风格中文普通话女声"
},
{
"id": "female-yujie",
"name": "御姐",
"gender": "female",
"desc": "成熟干练风格中文普通话女声"
},
{
"id": "female-chengshu",
"name": "成熟女性",
"gender": "female",
"desc": "成熟女性风格中文普通话女声"
},
{
"id": "female-tianmei",
"name": "甜美女性",
"gender": "female",
"desc": "甜美风格中文普通话女声"
},
{
"id": "Chinese (Mandarin)_News_Anchor",
"name": "新闻女声",
"gender": "female",
"desc": "专业播音腔的中年女性新闻主播,标准普通话"
},
{
"id": "Chinese (Mandarin)_Male_Announcer",
"name": "播报男声",
"gender": "male",
"desc": "富有磁性的中年男性播报员声音,标准普通话,清晰而权威"
},
{
"id": "Chinese (Mandarin)_Gentleman",
"name": "温润男声",
"gender": "male",
"desc": "温润磁性的青年男性声音,标准普通话"
},
{
"id": "Chinese (Mandarin)_Sweet_Lady",
"name": "甜美女声",
"gender": "female",
"desc": "温柔甜美的青年女性声音,标准普通话"
},
{
"id": "Cantonese_ProfessionalHostF)",
"name": "粤语专业女主持",
"gender": "female",
"desc": "中性、专业的青年女性粤语主持人声音"
},
{
"id": "Cantonese_ProfessionalHostM)",
"name": "粤语专业男主持",
"gender": "male",
"desc": "中性、专业的青年男性粤语主持人声音"
}
],
"enabled": true
},
"speech-2.6-hd": {
"name": "speech-2.6-hd",
"class": "src.services.provider.minimax.MiniMaxAudioService",
"args": [
"speech-2.6-hd"
],
"voices": [
{
"id": "male-qn-qingse",
"name": "青涩青年",
"gender": "male",
"desc": "青涩青年风格中文普通话男声"
},
{
"id": "male-qn-jingying",
"name": "精英青年",
"gender": "male",
"desc": "精英青年风格中文普通话男声"
},
{
"id": "male-qn-badao",
"name": "霸道青年",
"gender": "male",
"desc": "沉稳有力的中文普通话青年男声"
},
{
"id": "male-qn-daxuesheng",
"name": "青年大学生",
"gender": "male",
"desc": "青年大学生风格中文普通话男声"
},
{
"id": "female-shaonv",
"name": "少女",
"gender": "female",
"desc": "清亮少女风格中文普通话女声"
},
{
"id": "female-yujie",
"name": "御姐",
"gender": "female",
"desc": "成熟干练风格中文普通话女声"
},
{
"id": "female-chengshu",
"name": "成熟女性",
"gender": "female",
"desc": "成熟女性风格中文普通话女声"
},
{
"id": "female-tianmei",
"name": "甜美女性",
"gender": "female",
"desc": "甜美风格中文普通话女声"
},
{
"id": "Chinese (Mandarin)_News_Anchor",
"name": "新闻女声",
"gender": "female",
"desc": "专业、播音腔的中年女性新闻主播,标准普通话"
},
{
"id": "Chinese (Mandarin)_Male_Announcer",
"name": "播报男声",
"gender": "male",
"desc": "富有磁性的中年男性播报员声音,标准普通话,清晰而权威"
},
{
"id": "Chinese (Mandarin)_Gentleman",
"name": "温润男声",
"gender": "male",
"desc": "温润磁性的青年男性声音,标准普通话"
},
{
"id": "Chinese (Mandarin)_Sweet_Lady",
"name": "甜美女声",
"gender": "female",
"desc": "温柔甜美的青年女性声音,标准普通话"
},
{
"id": "Cantonese_ProfessionalHostF)",
"name": "粤语专业女主持",
"gender": "female",
"desc": "中性、专业的青年女性粤语主持人声音"
},
{
"id": "Cantonese_ProfessionalHostM)",
"name": "粤语专业男主持",
"gender": "male",
"desc": "中性、专业的青年男性粤语主持人声音"
}
],
"enabled": true
},
"speech-2.8-turbo": {
"name": "speech-2.8-turbo",
"class": "src.services.provider.minimax.MiniMaxAudioService",
"args": [
"speech-2.8-turbo"
],
"voices": [
{
"id": "male-qn-qingse",
"name": "青涩青年",
"gender": "male",
"desc": "青涩青年风格中文普通话男声"
},
{
"id": "male-qn-jingying",
"name": "精英青年",
"gender": "male",
"desc": "精英青年风格中文普通话男声"
},
{
"id": "male-qn-badao",
"name": "霸道青年",
"gender": "male",
"desc": "沉稳有力的中文普通话青年男声"
},
{
"id": "male-qn-daxuesheng",
"name": "青年大学生",
"gender": "male",
"desc": "青年大学生风格中文普通话男声"
},
{
"id": "female-shaonv",
"name": "少女",
"gender": "female",
"desc": "清亮少女风格中文普通话女声"
},
{
"id": "female-yujie",
"name": "御姐",
"gender": "female",
"desc": "成熟干练风格中文普通话女声"
},
{
"id": "female-chengshu",
"name": "成熟女性",
"gender": "female",
"desc": "成熟女性风格中文普通话女声"
},
{
"id": "female-tianmei",
"name": "甜美女性",
"gender": "female",
"desc": "甜美风格中文普通话女声"
},
{
"id": "Chinese (Mandarin)_News_Anchor",
"name": "新闻女声",
"gender": "female",
"desc": "专业、播音腔的中年女性新闻主播,标准普通话"
},
{
"id": "Chinese (Mandarin)_Male_Announcer",
"name": "播报男声",
"gender": "male",
"desc": "富有磁性的中年男性播报员声音,标准普通话,清晰而权威"
},
{
"id": "Chinese (Mandarin)_Gentleman",
"name": "温润男声",
"gender": "male",
"desc": "温润磁性的青年男性声音,标准普通话"
},
{
"id": "Chinese (Mandarin)_Sweet_Lady",
"name": "甜美女声",
"gender": "female",
"desc": "温柔甜美的青年女性声音,标准普通话"
},
{
"id": "Cantonese_ProfessionalHostF)",
"name": "粤语专业女主持",
"gender": "female",
"desc": "中性、专业的青年女性粤语主持人声音"
},
{
"id": "Cantonese_ProfessionalHostM)",
"name": "粤语专业男主持",
"gender": "male",
"desc": "中性、专业的青年男性粤语主持人声音"
}
],
"enabled": true
},
"speech-2.6-turbo": {
"name": "speech-2.6-turbo",
"class": "src.services.provider.minimax.MiniMaxAudioService",
"args": [
"speech-2.6-turbo"
],
"voices": [
{
"id": "male-qn-qingse",
"name": "青涩青年",
"gender": "male",
"desc": "青涩青年风格中文普通话男声"
},
{
"id": "male-qn-jingying",
"name": "精英青年",
"gender": "male",
"desc": "精英青年风格中文普通话男声"
},
{
"id": "male-qn-badao",
"name": "霸道青年",
"gender": "male",
"desc": "沉稳有力的中文普通话青年男声"
},
{
"id": "male-qn-daxuesheng",
"name": "青年大学生",
"gender": "male",
"desc": "青年大学生风格中文普通话男声"
},
{
"id": "female-shaonv",
"name": "少女",
"gender": "female",
"desc": "清亮少女风格中文普通话女声"
},
{
"id": "female-yujie",
"name": "御姐",
"gender": "female",
"desc": "成熟干练风格中文普通话女声"
},
{
"id": "female-chengshu",
"name": "成熟女性",
"gender": "female",
"desc": "成熟女性风格中文普通话女声"
},
{
"id": "female-tianmei",
"name": "甜美女性",
"gender": "female",
"desc": "甜美风格中文普通话女声"
},
{
"id": "Chinese (Mandarin)_News_Anchor",
"name": "新闻女声",
"gender": "female",
"desc": "专业、播音腔的中年女性新闻主播,标准普通话"
},
{
"id": "Chinese (Mandarin)_Male_Announcer",
"name": "播报男声",
"gender": "male",
"desc": "富有磁性的中年男性播报员声音,标准普通话,清晰而权威"
},
{
"id": "Chinese (Mandarin)_Gentleman",
"name": "温润男声",
"gender": "male",
"desc": "温润磁性的青年男性声音,标准普通话"
},
{
"id": "Chinese (Mandarin)_Sweet_Lady",
"name": "甜美女声",
"gender": "female",
"desc": "温柔甜美的青年女性声音,标准普通话"
},
{
"id": "Cantonese_ProfessionalHostF)",
"name": "粤语专业女主持",
"gender": "female",
"desc": "中性、专业的青年女性粤语主持人声音"
},
{
"id": "Cantonese_ProfessionalHostM)",
"name": "粤语专业男主持",
"gender": "male",
"desc": "中性、专业的青年男性粤语主持人声音"
}
],
"enabled": true
}
}

View File

@@ -0,0 +1,64 @@
{
"image-01": {
"name": "image-01",
"class": "src.services.provider.minimax.MiniMaxImageService",
"capabilities": {
"supportsRefImage": false,
"supportsLora": false
},
"resolutions": {
"1K": {
"1:1": "1024x1024",
"16:9": "1280x720",
"9:16": "720x1280",
"4:3": "1152x864",
"3:4": "864x1152",
"3:2": "1248x832",
"2:3": "832x1248",
"21:9": "1344x576"
},
"2K": {
"1:1": "2048x2048",
"16:9": "2560x1440",
"9:16": "1440x2560",
"4:3": "2304x1728",
"3:4": "1728x2304",
"3:2": "2496x1664",
"2:3": "1664x2496",
"21:9": "2688x1152"
}
},
"counts": {"min": 1, "max": 4}
},
"image-01-live": {
"name": "image-01-live",
"class": "src.services.provider.minimax.MiniMaxImageService",
"capabilities": {
"supportsRefImage": true,
"supportsLora": false
},
"resolutions": {
"1K": {
"1:1": "1024x1024",
"16:9": "1280x720",
"9:16": "720x1280",
"4:3": "1152x864",
"3:4": "864x1152",
"3:2": "1248x832",
"2:3": "832x1248",
"21:9": "1344x576"
},
"2K": {
"1:1": "2048x2048",
"16:9": "2560x1440",
"9:16": "1440x2560",
"4:3": "2304x1728",
"3:4": "1728x2304",
"3:2": "2496x1664",
"2:3": "1664x2496",
"21:9": "2688x1152"
}
},
"counts": {"min": 1, "max": 4}
}
}

View File

@@ -0,0 +1,11 @@
{
"base_url": "https://api.minimaxi.com/v1",
"MiniMax-M2.11": {
"name": "MiniMax M2.1",
"class": "src.services.provider.openai_service.OpenAIService",
"args": [
"MiniMax-M2.1"
],
"enabled": true
}
}

View File

@@ -0,0 +1,22 @@
{
"lyrics-2.5": {
"name": "lyrics-2.5",
"class": "src.services.provider.minimax.MiniMaxMusicService",
"args": [
"music-2.5"
],
"type": "lyrics",
"enabled": true,
"is_default": true
},
"music-2.5": {
"name": "music-2.5",
"class": "src.services.provider.minimax.MiniMaxMusicService",
"args": [
"music-2.5"
],
"type": "music",
"enabled": true,
"is_default": true
}
}

View File

@@ -0,0 +1,23 @@
{
"id": "minimax",
"name": "MiniMax",
"description": "海螺AI",
"dashboard_url": "https://platform.minimaxi.com/",
"helpUrl": "https://platform.minimaxi.com/user-center/basic-information/interface-key",
"fields": [
{
"name": "apiKey",
"label": "API Key",
"placeholder": "sk-api-...",
"required": true,
"type": "password"
},
{
"name": "groupId",
"label": "Group ID (可选)",
"placeholder": "分组 ID",
"required": false,
"type": "text"
}
]
}

View File

@@ -0,0 +1,68 @@
{
"MiniMax-Hailuo-2.3": {
"name": "Hailuo 2.3",
"class": "src.services.provider.minimax.MiniMaxVideoService",
"capabilities": {
"supportsTextToVideo": true,
"supportsImageToVideo": true,
"supportsFirstFrame": true,
"supportsLastFrame": true,
"supportsMultiImage": false,
"supportsMultiVideo": false,
"supportsAudio": false,
"supportsNegativePrompt": false,
"supportsLora": false
},
"durations": {
"values": [
6,
10
]
},
"counts": {"min": 1, "max": 4}
},
"MiniMax-Hailuo-02": {
"name": "Hailuo 02",
"class": "src.services.provider.minimax.MiniMaxVideoService",
"capabilities": {
"supportsTextToVideo": true,
"supportsImageToVideo": true,
"supportsFirstFrame": true,
"supportsLastFrame": true,
"supportsMultiImage": false,
"supportsMultiVideo": false,
"supportsAudio": false,
"supportsNegativePrompt": false,
"supportsLora": false
},
"durations": {
"values": [
6,
10
]
},
"counts": {"min": 1, "max": 4}
},
"T2V-01-Director": {
"name": "T2V-01-Director",
"class": "src.services.provider.minimax.MiniMaxVideoService",
"capabilities": {
"supportsTextToVideo": true,
"supportsImageToVideo": true,
"supportsFirstFrame": true,
"supportsLastFrame": true,
"supportsMultiImage": false,
"supportsMultiVideo": false,
"supportsAudio": false,
"supportsNegativePrompt": false,
"supportsLora": false
},
"durations": {
"values": [
6,
10
]
},
"counts": {"min": 1, "max": 4}
}
}

View File

@@ -0,0 +1,143 @@
{
"qwen-image": {
"name": "Qwen Image",
"class": "backend.src.services.provider.modelscope.image.ModelScopeImageService",
"args": [
"Qwen/Qwen-Image"
],
"capabilities": {
"supportsRefImage": false,
"supportsLora": true
},
"resolutions": {
"1K": {
"16:9": "1664x928",
"9:16": "928x1664",
"1:1": "1328x1328"
},
"2K": {
"16:9": "2560x1440",
"9:16": "1440x2560",
"1:1": "2048x2048"
}
},
"counts": {"min": 1, "max": 4},
"enabled": true
},
"qwen-image-edit": {
"name": "Qwen Image Edit",
"class": "backend.src.services.provider.modelscope.image.ModelScopeImageService",
"args": [
"Qwen/Qwen-Image-Edit-2511"
],
"capabilities": {
"supportsRefImage": true,
"supportsLora": true
},
"resolutions": {
"1K": {
"16:9": "1664x928",
"9:16": "928x1664",
"1:1": "1328x1328",
"4:3": "1328x1024",
"3:4": "1024x1328"
},
"2K": {
"16:9": "2560x1440",
"9:16": "1440x2560",
"1:1": "2048x2048",
"4:3": "2560x1920",
"3:4": "1920x2560"
}
},
"counts": {"min": 1, "max": 4},
"enabled": true
},
"flux-dev": {
"name": "FLUX.2 Dev",
"class": "backend.src.services.provider.modelscope.image.ModelScopeImageService",
"args": [
"black-forest-labs/FLUX.2-dev"
],
"capabilities": {
"supportsRefImage": false,
"supportsLora": true
},
"resolutions": {
"1K": {
"16:9": "1280x720",
"9:16": "720x1280",
"1:1": "1024x1024",
"4:3": "1024x768",
"3:4": "768x1024"
},
"2K": {
"16:9": "2560x1440",
"9:16": "1440x2560",
"1:1": "2048x2048",
"4:3": "2048x1536",
"3:4": "1536x2048"
}
},
"counts": {"min": 1, "max": 4},
"enabled": true
},
"z-image-turbo": {
"name": "Z Image Turbo",
"class": "backend.src.services.provider.modelscope.image.ModelScopeImageService",
"args": [
"Tongyi-MAI/Z-Image-Turbo"
],
"capabilities": {
"supportsRefImage": false,
"supportsLora": true
},
"resolutions": {
"1K": {
"16:9": "1280x720",
"9:16": "720x1280",
"1:1": "1024x1024",
"4:3": "1024x768",
"3:4": "768x1024"
},
"2K": {
"16:9": "2560x1440",
"9:16": "1440x2560",
"1:1": "2048x2048",
"4:3": "2048x1536",
"3:4": "1536x2048"
}
},
"counts": {"min": 1, "max": 4},
"enabled": true
},
"awportrait-z": {
"name": "AWPortrait Z",
"class": "backend.src.services.provider.modelscope.image.ModelScopeImageService",
"args": [
"LiblibAI/AWPortrait-Z"
],
"capabilities": {
"supportsRefImage": false,
"supportsLora": true
},
"resolutions": {
"1K": {
"16:9": "1280x720",
"9:16": "720x1280",
"1:1": "1024x1024",
"4:3": "1024x768",
"3:4": "768x1024"
},
"2K": {
"16:9": "2560x1440",
"9:16": "1440x2560",
"1:1": "2048x2048",
"4:3": "2048x1536",
"3:4": "1536x2048"
}
},
"counts": {"min": 1, "max": 4},
"enabled": true
}
}

View File

@@ -0,0 +1,16 @@
{
"id": "modelscope",
"name": "ModelScope",
"description": "开源模型平台",
"dashboard_url": "https://modelscope.cn/",
"helpUrl": "https://www.modelscope.cn/my/myaccesstoken",
"fields": [
{
"name": "apiKey",
"label": "API Token",
"placeholder": "ms-...",
"required": true,
"type": "password"
}
]
}

View File

@@ -0,0 +1,11 @@
{
"base_url": "https://api.moonshot.cn/v1",
"kimi-k2.5": {
"name": "Kimi 2.5",
"class": "backend.src.services.provider.openai_service.OpenAIService",
"args": [
"kimi-k2.5"
],
"enabled": true
}
}

View File

@@ -0,0 +1,16 @@
{
"id": "moonshot",
"name": "月之暗面",
"description": "Kimi 大模型",
"dashboard_url": "https://platform.moonshot.cn/",
"helpUrl": "https://platform.moonshot.cn/",
"fields": [
{
"name": "apiKey",
"label": "API Key",
"placeholder": "sk-...",
"required": true,
"type": "password"
}
]
}

View File

@@ -0,0 +1,42 @@
{
"tts-1": {
"name": "TTS-1",
"class": "src.services.provider.openai.OpenAIAudioService",
"args": [
"tts-1"
],
"voices": [
{
"id": "alloy",
"name": "Alloy",
"gender": "female"
},
{
"id": "nova",
"name": "Nova",
"gender": "female"
},
{
"id": "shimmer",
"name": "Shimmer",
"gender": "female"
},
{
"id": "fable",
"name": "Fable",
"gender": "female"
},
{
"id": "echo",
"name": "Echo",
"gender": "male"
},
{
"id": "onyx",
"name": "Onyx",
"gender": "male"
}
],
"enabled": true
}
}

View File

@@ -0,0 +1,25 @@
{
"dall-e-3": {
"name": "DALL-E 3",
"class": "src.services.provider.openai.OpenAIImageService",
"args": [
"dall-e-3"
],
"capabilities": {
"supportsRefImage": false,
"supportsLora": false
},
"variants": {
"t2i": "dall-e-3"
},
"resolutions": {
"1K": {
"1:1": "1024*1024",
"16:9": "1792*1024",
"9:16": "1024*1792"
}
},
"counts": {"min": 1, "max": 1},
"enabled": true
}
}

View File

@@ -0,0 +1,16 @@
{
"id": "openai",
"name": "OpenAI",
"description": "GPT-4、DALL-E、Sora",
"dashboard_url": "https://platform.openai.com/",
"helpUrl": "https://platform.openai.com/api-keys",
"fields": [
{
"name": "apiKey",
"label": "API Key",
"placeholder": "sk-...",
"required": true,
"type": "password"
}
]
}

View File

@@ -0,0 +1,7 @@
{
"id": "provider-id",
"name": "Provider Display Name",
"description": "Optional description",
"api_key": "YOUR_API_KEY_OR_SET_VIA_ENV",
"dashboard_url": "https://example.com/dashboard"
}

View File

@@ -0,0 +1,42 @@
{
"doubao-seedream-4.5": {
"name": "SeeDream 4.5",
"class": "src.services.provider.volcengine.image.VolcengineImageService",
"args": [
"doubao-seedream-4.5"
],
"capabilities": {
"supportsRefImage": true,
"supportsLora": false
},
"variants": {
"t2i": "doubao-seedream-4-5-251128",
"i2i": "doubao-seedream-4-5-251128"
},
"resolutions": {
"1K": {
"16:9": "1280x720",
"9:16": "720x1280",
"1:1": "1024x1024",
"4:3": "1152x864",
"3:4": "864x1152"
},
"2K": {
"16:9": "2560x1440",
"9:16": "1440x2560",
"1:1": "2048x2048",
"4:3": "2304x1728",
"3:4": "1728x2304"
},
"4K": {
"16:9": "3840x2160",
"9:16": "2160x3840",
"1:1": "4096x4096",
"4:3": "3456x2592",
"3:4": "2592x3456"
}
},
"counts": {"min": 1, "max": 4},
"enabled": true
}
}

View File

@@ -0,0 +1,11 @@
{
"base_url": "https://ark.cn-beijing.volces.com/api/v3",
"doubao-1.5-pro": {
"name": "Doubao 1.5 Pro",
"class": "backend.src.services.provider.openai_service.OpenAIService",
"args": [
"doubao-1-5-pro-32k-250115"
],
"enabled": true
}
}

View File

@@ -0,0 +1,16 @@
{
"id": "volcengine",
"name": "火山引擎",
"description": "豆包大模型",
"dashboard_url": "https://console.volcengine.com/ark/",
"helpUrl": "https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey",
"fields": [
{
"name": "apiKey",
"label": "API Key",
"placeholder": "...",
"required": true,
"type": "password"
}
]
}

View File

@@ -0,0 +1,138 @@
{
"doubao-seedance-1.5-pro": {
"name": "SeeDance 1.5 Pro",
"class": "src.services.provider.volcengine.video.VolcengineVideoService",
"args": [
"doubao-seedance-1.5-pro"
],
"capabilities": {
"supportsTextToVideo": true,
"supportsImageToVideo": true,
"supportsFirstFrame": true,
"supportsLastFrame": true,
"supportsMultiImage": false,
"supportsMultiVideo": false,
"supportsLora": false
},
"variants": {
"t2v": "doubao-seedance-1-5-pro-251215",
"i2v": "doubao-seedance-1-5-pro-251215",
"kf2v": "doubao-seedance-1-5-pro-251215"
},
"resolutions": {
"720P": {
"16:9": "1280x720",
"9:16": "720x1280",
"1:1": "1280x1280",
"4:3": "1280x960",
"3:4": "960x1280"
}
},
"durations": {
"values": [
4,
12
]
},
"counts": {
"min": 1,
"max": 4
},
"enabled": true
},
"doubao-seedance-1.0-pro": {
"name": "SeeDance 1.0 Pro",
"class": "src.services.provider.volcengine.video.VolcengineVideoService",
"args": [
"doubao-seedance-1-0-pro-250528"
],
"capabilities": {
"supportsTextToVideo": true,
"supportsImageToVideo": true,
"supportsFirstFrame": true,
"supportsLastFrame": true,
"supportsMultiImage": false,
"supportsMultiVideo": false,
"supportsLora": false
},
"variants": {
"t2v": "doubao-seedance-1-0-pro-250528",
"i2v": "doubao-seedance-1-0-pro-250528",
"kf2v": "doubao-seedance-1-0-pro-250528"
},
"resolutions": {
"720P": {
"16:9": "1248×704",
"9:16": "704x1248",
"1:1": "960×960",
"4:3": "1120×832",
"3:4": "832x1120"
},
"1080P": {
"16:9": "1920x1088",
"9:16": "1088x1920",
"1:1": "1440×1440",
"4:3": "1664×1248",
"3:4": "1248x1664"
}
},
"durations": {
"values": [
2,
12
]
},
"counts": {
"min": 1,
"max": 4
},
"enabled": true
},
"doubao-seedance-1.0-pro-fast": {
"name": "SeeDance 1.0 Pro Fast",
"class": "src.services.provider.volcengine.video.VolcengineVideoService",
"args": [
"doubao-seedance-1-0-pro-fast-251015"
],
"capabilities": {
"supportsTextToVideo": true,
"supportsImageToVideo": true,
"supportsFirstFrame": true,
"supportsLastFrame": false,
"supportsMultiImage": false,
"supportsMultiVideo": false,
"supportsLora": false
},
"variants": {
"t2v": "doubao-seedance-1-0-pro-fast-251015",
"i2v": "doubao-seedance-1-0-pro-fast-251015"
},
"resolutions": {
"720P": {
"16:9": "1248×704",
"9:16": "704x1248",
"1:1": "960×960",
"4:3": "1120×832",
"3:4": "832x1120"
},
"1080P": {
"16:9": "1920x1088",
"9:16": "1088x1920",
"1:1": "1440×1440",
"4:3": "1664×1248",
"3:4": "1248x1664"
}
},
"durations": {
"values": [
2,
12
]
},
"counts": {
"min": 1,
"max": 4
},
"enabled": true
}
}

View File

@@ -0,0 +1,98 @@
import logging
import os
import json
from dotenv import load_dotenv
logger = logging.getLogger(__name__)
# Load environment variables
load_dotenv()
# Load Storage Configuration
SETTINGS_DIR = os.path.dirname(os.path.abspath(__file__))
STORAGE_CONFIG_PATH = os.path.join(SETTINGS_DIR, 'storage.json')
storage_config = {}
if os.path.exists(STORAGE_CONFIG_PATH):
try:
with open(STORAGE_CONFIG_PATH, 'r') as f:
storage_config = json.load(f)
except Exception as e:
logger.error(f"Failed to load storage config: {e}")
# 服务器 Configuration
PY_PORT = int(os.getenv('PY_PORT', '8000'))
NODE_ENV = os.getenv('NODE_ENV', 'development')
# CORS Configuration
ALLOWED_ORIGINS = [o for o in os.getenv('CORS_ALLOWED_ORIGINS', '').split(',') if o]
DEV_ALLOWED_ORIGINS = [
o for o in os.getenv(
'CORS_DEV_ALLOWED_ORIGINS',
'http://localhost:3000,http://127.0.0.1:3000,http://localhost:3001,http://127.0.0.1:3001'
).split(',') if o
]
ALLOW_DEV_ORIGINS = (os.getenv('ALLOW_DEV_ORIGINS', '1') != '0' and NODE_ENV != 'production')
# 数据库 Configuration
DATA_DIR = os.getenv('DATA_DIR') or os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'data'))
DB_PATH = os.getenv('DB_PATH') or os.path.join(DATA_DIR, 'pixel.db')
DATABASE_URL = os.getenv('DATABASE_URL')
# Alibaba Cloud OSS Configuration (env vars take precedence over storage.json)
OSS_REGION = os.getenv('OSS_REGION') or storage_config.get('OSS_REGION', 'oss-cn-shanghai')
OSS_ENDPOINT = os.getenv('OSS_ENDPOINT') or storage_config.get('OSS_ENDPOINT', 'oss-cn-shanghai.aliyuncs.com')
OSS_BUCKET = os.getenv('OSS_BUCKET') or storage_config.get('OSS_BUCKET')
ALIBABA_CLOUD_ACCESS_KEY_ID = os.getenv('ALIBABA_CLOUD_ACCESS_KEY_ID') or storage_config.get('ALIBABA_CLOUD_ACCESS_KEY_ID')
ALIBABA_CLOUD_ACCESS_KEY_SECRET = os.getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET') or storage_config.get('ALIBABA_CLOUD_ACCESS_KEY_SECRET')
# DashScope Configuration (Qwen, Wanx)
DASHSCOPE_API_KEY = os.getenv('DASHSCOPE_API_KEY')
# 模型Scope Configuration
MODELSCOPE_API_TOKEN = os.getenv('MODELSCOPE_API_TOKEN')
# Volcengine Configuration
VOLCENGINE_API_KEY = os.getenv('VOLCENGINE_API_KEY') # 火山方舟 (LLM)
# Google Configuration
GOOGLE_API_KEY = os.getenv('GOOGLE_API_KEY')
# OpenAI Configuration
OPENAI_API_KEY = os.getenv('OPENAI_API_KEY')
OPENAI_BASE_URL = os.getenv('OPENAI_BASE_URL') # 可选: for proxies
# MiniMax Configuration
MINIMAX_API_KEY = os.getenv('MINIMAX_API_KEY')
MINIMAX_GROUP_ID = os.getenv('MINIMAX_GROUP_ID') # Sometimes needed
# Kling AI Configuration
KLING_ACCESS_KEY = os.getenv('KLING_ACCESS_KEY')
KLING_SECRET_KEY = os.getenv('KLING_SECRET_KEY')
KLING_API_BASE = os.getenv('KLING_API_BASE', 'https://api-beijing.klingai.com/v1')
# Midjourney Configuration (Youchuan / Proxy)
MIDJOURNEY_API_KEY = os.getenv('MIDJOURNEY_API_KEY')
MIDJOURNEY_PROXY_URL = os.getenv('MIDJOURNEY_PROXY_URL')
YOUCHUAN_APP_ID = os.getenv('YOUCHUAN_APP_ID')
YOUCHUAN_SECRET_KEY = os.getenv('YOUCHUAN_SECRET_KEY')
# Application Settings
UPLOAD_DIR = os.path.join(DATA_DIR, 'uploads')
# 存储 Configuration
STORAGE_TYPE = os.getenv('STORAGE_TYPE') or storage_config.get('STORAGE_TYPE', 'local') # 'local' or 'oss'
PROJECTS_DIR = os.path.join(DATA_DIR, "projects")
CANVAS_DIR = os.path.join(DATA_DIR, "canvas")
# Redis Configuration
REDIS_URL = os.getenv('REDIS_URL', 'redis://localhost:6379')
REDIS_ENABLED = os.getenv('REDIS_ENABLED', '1') != '0'
# 追踪 Configuration
TRACING_ENABLED = os.getenv('TRACING_ENABLED', '0') != '0'
OTLP_ENDPOINT = os.getenv('OTLP_ENDPOINT', 'http://localhost:4317')
# Task Management Configuration
# Unified task manager is now always used

View File

@@ -0,0 +1,6 @@
{
"OSS_REGION": "oss-cn-shanghai",
"OSS_ENDPOINT": "oss-cn-shanghai.aliyuncs.com",
"OSS_BUCKET": "your-bucket-name",
"STORAGE_TYPE": "oss"
}

View File

@@ -0,0 +1,152 @@
{
"styles": [
{
"id": "cyberpunk",
"name": "赛博朋克",
"type": "prompt",
"desc": "高对比度霓虹灯光,未来主义建筑,机械改造",
"prompt": "cyberpunk style, neon lights, high contrast, futuristic buildings, mechanical modifications",
"color": "from-pink-500/20 to-blue-500/20"
},
{
"id": "ink",
"name": "水墨风",
"type": "prompt",
"desc": "传统中国水墨渲染,黑白灰为主,意境深远",
"prompt": "traditional chinese ink painting style, black and white, artistic conception, ink wash",
"color": "from-gray-200/10 to-gray-900/10"
},
{
"id": "pixar",
"name": "皮克斯风格",
"type": "prompt",
"desc": "3D卡通渲染色彩鲜艳光影柔和表情夸张",
"prompt": "pixar style, 3d cartoon rendering, vibrant colors, soft lighting, expressive",
"color": "from-orange-400/20 to-yellow-400/20"
},
{
"id": "anime",
"name": "日漫",
"type": "prompt",
"desc": "典型日本动画风格,线条清晰,赛璐璐上色",
"prompt": "japanese anime style, clear lines, cel shading, 2d animation",
"color": "from-purple-500/20 to-pink-500/20"
},
{
"id": "chinese-anime",
"name": "国漫风",
"type": "prompt",
"desc": "中国现代动画风格,融合传统与现代元素,色彩华丽",
"prompt": "chinese donghua style, chinese anime, elegant, detailed background, vibrant colors, mix of traditional and modern aesthetics",
"color": "from-red-500/20 to-yellow-500/20"
},
{
"id": "cel-shading",
"name": "赛璐璐风",
"type": "prompt",
"desc": "经典的赛璐璐上色风格,阴影边缘硬朗,色彩鲜明",
"prompt": "cel shading, hard shadows, flat colors, anime coloring style, clean lines",
"color": "from-blue-400/20 to-indigo-400/20"
},
{
"id": "korean-webtoon",
"name": "韩漫风",
"type": "prompt",
"desc": "韩国条漫风格,人物美型,色彩明亮,光影细腻",
"prompt": "manhwa style, korean webtoon, beautiful characters, detailed eyes, soft lighting, vibrant digital art",
"color": "from-pink-400/20 to-rose-400/20"
},
{
"id": "american-comic",
"name": "美漫风",
"type": "prompt",
"desc": "美国漫画风格,线条粗犷,阴影浓重,动态感强",
"prompt": "american comic book style, bold lines, heavy shadows, dynamic poses, halftone patterns, marvel/dc style",
"color": "from-red-600/20 to-blue-600/20"
},
{
"id": "ghibli",
"name": "吉卜力风格",
"type": "prompt",
"desc": "宫崎骏动画风格,色彩清新自然,细节丰富,治愈系",
"prompt": "studio ghibli style, miyazaki hayao style, anime scenery, vibrant colors, lush greenery, detailed clouds, soothing atmosphere",
"color": "from-green-400/20 to-blue-400/20"
},
{
"id": "realistic",
"name": "写实",
"type": "prompt",
"desc": "电影级写实渲染,细节丰富,光照真实",
"prompt": "cinematic realistic, highly detailed, photorealistic, 8k, movie quality",
"color": "from-blue-900/20 to-slate-900/20"
},
{
"id": "hand-drawn",
"name": "手绘",
"type": "prompt",
"desc": "传统手绘质感,笔触明显,艺术感强",
"prompt": "hand-drawn style, visible brush strokes, artistic, sketch",
"color": "from-emerald-500/20 to-teal-500/20"
},
{
"id": "watercolor",
"name": "水彩画",
"type": "prompt",
"desc": "水彩晕染效果,色彩通透,艺术感强",
"prompt": "watercolor painting, wet on wet, soft blending, artistic, translucent colors, paper texture",
"color": "from-cyan-400/20 to-blue-300/20"
},
{
"id": "oil-painting",
"name": "油画",
"type": "prompt",
"desc": "厚涂油画质感,笔触丰富,光影层次感强",
"prompt": "oil painting, impasto, textured canvas, classical art, rich colors, visible brushwork",
"color": "from-amber-700/20 to-yellow-600/20"
},
{
"id": "pixel-art",
"name": "像素风",
"type": "prompt",
"desc": "复古8-bit/16-bit像素艺术怀旧游戏风格",
"prompt": "pixel art, 16-bit, retro game style, dot art, low resolution aesthetics",
"color": "from-purple-600/20 to-indigo-600/20"
},
{
"id": "ukiyo-e",
"name": "浮世绘",
"type": "prompt",
"desc": "日本传统木刻版画风格,线条流畅,色彩古朴",
"prompt": "ukiyo-e style, japanese woodblock print, traditional japanese art, flat colors, bold outlines",
"color": "from-red-400/20 to-orange-300/20"
},
{
"id": "vaporwave",
"name": "蒸汽波",
"type": "prompt",
"desc": "80年代复古未来主义霓虹色彩故障艺术",
"prompt": "vaporwave style, 80s retro aesthetics, neon pink and blue, glitch art, surrealism, statue, palm trees",
"color": "from-pink-600/20 to-purple-600/20"
},
{
"id": "low-poly",
"name": "低多边形",
"type": "prompt",
"desc": "3D几何多边形风格简约抽象棱角分明",
"prompt": "low poly style, 3d geometric, minimalist, angular, flat shading, isometric",
"color": "from-blue-500/20 to-cyan-500/20"
},
{
"id": "clay-style-lora",
"name": "黏土风 (LoRA)",
"type": "lora",
"desc": "特殊的黏土材质风格",
"lora": {
"id": "lora-clay-v1",
"base_model": "modelscope/qwen-image",
"trigger_word": "clay style"
},
"color": "from-amber-600/20 to-orange-600/20"
}
]
}

View File

@@ -0,0 +1,8 @@
{
"defaultImageModel": "dashscope/z-image",
"defaultVideoModel": "dashscope/wan2.6-video",
"defaultAudioModel": "minimax/speech-2.8-turbo",
"defaultLLMModel": "dashscope/qwen-plus",
"defaultStyle": "anime",
"defaultAspectRatio": "16:9"
}