├── src-tauri ├── build.rs ├── icons │ ├── 32x32.png │ ├── 64x64.png │ ├── icon.icns │ ├── icon.ico │ ├── icon.png │ ├── 128x128.png │ ├── 128x128@2x.png │ ├── StoreLogo.png │ ├── Square30x30Logo.png │ ├── Square44x44Logo.png │ ├── Square71x71Logo.png │ ├── Square89x89Logo.png │ ├── Square107x107Logo.png │ ├── Square142x142Logo.png │ ├── Square150x150Logo.png │ ├── Square284x284Logo.png │ ├── Square310x310Logo.png │ ├── icon_macos_resize.png │ ├── ios │ │ ├── AppIcon-512@2x.png │ │ ├── AppIcon-20x20@1x.png │ │ ├── AppIcon-20x20@2x.png │ │ ├── AppIcon-20x20@3x.png │ │ ├── AppIcon-29x29@1x.png │ │ ├── AppIcon-29x29@2x.png │ │ ├── AppIcon-29x29@3x.png │ │ ├── AppIcon-40x40@1x.png │ │ ├── AppIcon-40x40@2x.png │ │ ├── AppIcon-40x40@3x.png │ │ ├── AppIcon-60x60@2x.png │ │ ├── AppIcon-60x60@3x.png │ │ ├── AppIcon-76x76@1x.png │ │ ├── AppIcon-76x76@2x.png │ │ ├── AppIcon-20x20@2x-1.png │ │ ├── AppIcon-29x29@2x-1.png │ │ ├── AppIcon-40x40@2x-1.png │ │ └── AppIcon-83.5x83.5@2x.png │ └── android │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── ic_launcher_foreground.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── ic_launcher_foreground.png │ │ ├── values │ │ └── ic_launcher_background.xml │ │ └── mipmap-anydpi-v26 │ │ └── ic_launcher.xml ├── Info.plist ├── wix │ └── license.rtf ├── Cargo.toml ├── src │ └── main.rs ├── capabilities │ └── default.json └── tauri.conf.json ├── src ├── adapters │ ├── modelscope │ │ ├── parsers │ │ │ ├── index.ts │ │ │ └── imageParser.ts │ │ └── config.ts │ ├── kie │ │ ├── parsers │ │ │ ├── index.ts │ │ │ ├── videoParser.ts │ │ │ └── imageParser.ts │ │ ├── config.ts │ │ └── models │ │ │ ├── z-image.ts │ │ │ ├── index.ts │ │ │ ├── grok-imagine.ts │ │ │ ├── nano-banana-pro.ts │ │ │ ├── hailuo-2-3.ts │ │ │ ├── seedream-4.5.ts │ │ │ ├── kling-v2-6.ts │ │ │ ├── seedream-4.0.ts │ │ │ └── grok-imagine-video.ts │ ├── fal │ │ ├── parsers │ │ │ ├── index.ts │ │ │ ├── imageParser.ts │ │ │ └── videoParser.ts │ │ └── models │ │ │ ├── fal-ai-nano-banana-pro.ts │ │ │ ├── fal-ai-bytedance-seedream-v4.ts │ │ │ ├── fal-ai-bytedance-seedream-v4.5.ts │ │ │ ├── fal-ai-nano-banana.ts │ │ │ └── fal-ai-kling-video-v2.6-pro.ts │ ├── _template │ │ ├── parsers │ │ │ ├── index.ts │ │ │ ├── audioParser.ts │ │ │ ├── videoParser.ts │ │ │ └── imageParser.ts │ │ ├── models │ │ │ ├── index.ts │ │ │ └── exampleModel.ts │ │ ├── config.ts │ │ └── types.ts │ ├── ppio │ │ ├── parsers │ │ │ ├── index.ts │ │ │ ├── imageParser.ts │ │ │ ├── audioParser.ts │ │ │ └── videoParser.ts │ │ ├── config.ts │ │ └── models │ │ │ ├── seedream.ts │ │ │ ├── index.ts │ │ │ ├── wan.ts │ │ │ ├── pixverse.ts │ │ │ ├── kling-2.5-turbo.ts │ │ │ ├── minimax-hailuo-2.3.ts │ │ │ ├── minimax-hailuo-02.ts │ │ │ └── seedance.ts │ └── index.ts ├── vite-env.d.ts ├── components │ ├── ui │ │ ├── ParamRow.tsx │ │ ├── TextInput.tsx │ │ ├── Toggle.tsx │ │ └── ProgressBar.tsx │ └── TestModeIndicator.tsx ├── types │ └── index.ts ├── main.tsx ├── models │ ├── kie-grok-imagine.ts │ ├── kie-z-image.ts │ ├── kling-2.5-turbo.ts │ ├── kie-nano-banana-pro.ts │ ├── fal-ai-minimax-hailuo-2.3.ts │ ├── kie-hailuo-2-3.ts │ ├── pixverse-v4.5.ts │ ├── minimax-hailuo-2.3.ts │ ├── kie-seedream-4.5.ts │ ├── kie-grok-imagine-video.ts │ ├── qwen-image-edit-2509.ts │ ├── fal-ai-kling-image-o1.ts │ ├── kie-hailuo-02.ts │ ├── kie-kling-v2-6.ts │ ├── fal-ai-nano-banana.ts │ ├── fal-ai-kling-video-v2.6-pro.ts │ ├── kie-seedream-4.0.ts │ ├── fal-ai-nano-banana-pro.ts │ ├── kling-video-o1.ts │ ├── fal-ai-wan-25-preview.ts │ └── seedance-v1.ts ├── utils │ ├── progress.ts │ ├── modelConfig.ts │ └── polling.ts └── styles │ └── scrollbar.css ├── postcss.config.js ├── tsconfig.node.json ├── docs └── api │ ├── fal │ ├── sora2 │ │ └── sora-2-Price.txt │ ├── wan │ │ └── wan-25-Price.txt │ ├── LTX-2 │ │ └── LTX-2-Price.txt │ ├── pixverse │ │ └── pixverse-v5.5-Price.txt │ ├── minimax │ │ ├── minimax-hailuo-2.3-Price.txt │ │ └── minimax-hailuo-02-Price.txt │ ├── kling │ │ └── kling-Price.txt │ ├── vidu-q2 │ │ └── vidu-q2-Price.txt │ ├── base │ │ └── model-endpoints.md │ ├── bytedance │ │ └── Seedance-Price.txt │ └── veo3.1 │ │ └── veo3.1_价格.txt │ ├── 派欧云PPIO │ ├── 基础 │ │ ├── API_鉴权方式.md │ │ ├── 获取账户信息.md │ │ └── API_错误码说明.md │ ├── 其他 │ │ ├── 文字擦除.md │ │ └── 背景替换.md │ ├── 图像 │ │ ├── 背景移除.md │ │ ├── 图像背景移除.md │ │ ├── 对象擦除.md │ │ ├── 人脸融合.md │ │ ├── 图像高清化.md │ │ ├── Qwen-Image_图像编辑.md │ │ ├── 图像擦除.md │ │ └── Hunyuan_Image_3.md │ ├── 大语言 │ │ ├── 检索模型.md │ │ ├── 列出模型.md │ │ └── 创建嵌入请求.md │ └── 视频 │ │ ├── Minimax_Video-01.md │ │ ├── Kling-o1_图生视频.md │ │ ├── Kling-o1_文生视频.md │ │ ├── KLING_V1.6_文生视频.md │ │ ├── Seedance_V1_Pro_文生视频.md │ │ ├── Seedance_V1_Lite_文生视频.md │ │ ├── Kling-o1_视频编辑.md │ │ ├── Minimax_Hailuo_2.3_Fast_图生视频.md │ │ ├── Kling_V2.5_Turbo_文生视频.md │ │ ├── Kling_V2.5_Turbo_图生视频.md │ │ ├── Kling-o1_参考生视频.md │ │ ├── PixVerse_V4.5_文生视频.md │ │ ├── KLING_V1.6_图生视频.md │ │ ├── Vidu_Q1_文生视频.md │ │ ├── Seedance_V1_Pro_图生视频.md │ │ ├── Minimax_Hailuo_2.3_图生视频.md │ │ ├── PixVerse_V4.5_图生视频.md │ │ ├── Vidu_2.0_图生视频.md │ │ ├── Seedance_V1_Lite_图生视频.md │ │ ├── Vidu_Q1_图生视频.md │ │ └── Minimax_Hailuo_2.3_文生视频.md │ └── KIE │ └── veo3 │ └── 05-获取-1080P-视频.md ├── vite.config.ts ├── tailwind.config.js ├── .eslintrc.json ├── tsconfig.json ├── index.html ├── .gitignore └── package.json /src-tauri/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | tauri_build::build(); 3 | } 4 | 5 | -------------------------------------------------------------------------------- /src/adapters/modelscope/parsers/index.ts: -------------------------------------------------------------------------------- 1 | export { parseImageResponse } from './imageParser' 2 | -------------------------------------------------------------------------------- /src-tauri/icons/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/32x32.png -------------------------------------------------------------------------------- /src-tauri/icons/64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/64x64.png -------------------------------------------------------------------------------- /src-tauri/icons/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/icon.icns -------------------------------------------------------------------------------- /src-tauri/icons/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/icon.ico -------------------------------------------------------------------------------- /src-tauri/icons/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/icon.png -------------------------------------------------------------------------------- /src-tauri/icons/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/128x128.png -------------------------------------------------------------------------------- /src-tauri/icons/128x128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/128x128@2x.png -------------------------------------------------------------------------------- /src-tauri/icons/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/StoreLogo.png -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } -------------------------------------------------------------------------------- /src-tauri/icons/Square30x30Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/Square30x30Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square44x44Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/Square44x44Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square71x71Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/Square71x71Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square89x89Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/Square89x89Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square107x107Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/Square107x107Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square142x142Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/Square142x142Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square150x150Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/Square150x150Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square284x284Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/Square284x284Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square310x310Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/Square310x310Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/icon_macos_resize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/icon_macos_resize.png -------------------------------------------------------------------------------- /src-tauri/icons/ios/AppIcon-512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/ios/AppIcon-512@2x.png -------------------------------------------------------------------------------- /src-tauri/icons/ios/AppIcon-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/ios/AppIcon-20x20@1x.png -------------------------------------------------------------------------------- /src-tauri/icons/ios/AppIcon-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/ios/AppIcon-20x20@2x.png -------------------------------------------------------------------------------- /src-tauri/icons/ios/AppIcon-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/ios/AppIcon-20x20@3x.png -------------------------------------------------------------------------------- /src-tauri/icons/ios/AppIcon-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/ios/AppIcon-29x29@1x.png -------------------------------------------------------------------------------- /src-tauri/icons/ios/AppIcon-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/ios/AppIcon-29x29@2x.png -------------------------------------------------------------------------------- /src-tauri/icons/ios/AppIcon-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/ios/AppIcon-29x29@3x.png -------------------------------------------------------------------------------- /src-tauri/icons/ios/AppIcon-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/ios/AppIcon-40x40@1x.png -------------------------------------------------------------------------------- /src-tauri/icons/ios/AppIcon-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/ios/AppIcon-40x40@2x.png -------------------------------------------------------------------------------- /src-tauri/icons/ios/AppIcon-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/ios/AppIcon-40x40@3x.png -------------------------------------------------------------------------------- /src-tauri/icons/ios/AppIcon-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/ios/AppIcon-60x60@2x.png -------------------------------------------------------------------------------- /src-tauri/icons/ios/AppIcon-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/ios/AppIcon-60x60@3x.png -------------------------------------------------------------------------------- /src-tauri/icons/ios/AppIcon-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/ios/AppIcon-76x76@1x.png -------------------------------------------------------------------------------- /src-tauri/icons/ios/AppIcon-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/ios/AppIcon-76x76@2x.png -------------------------------------------------------------------------------- /src-tauri/icons/ios/AppIcon-20x20@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/ios/AppIcon-20x20@2x-1.png -------------------------------------------------------------------------------- /src-tauri/icons/ios/AppIcon-29x29@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/ios/AppIcon-29x29@2x-1.png -------------------------------------------------------------------------------- /src-tauri/icons/ios/AppIcon-40x40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/ios/AppIcon-40x40@2x-1.png -------------------------------------------------------------------------------- /src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/ios/AppIcon-83.5x83.5@2x.png -------------------------------------------------------------------------------- /src/adapters/kie/parsers/index.ts: -------------------------------------------------------------------------------- 1 | export { parseImageResponse } from './imageParser' 2 | export { parseVideoResponse } from './videoParser' 3 | -------------------------------------------------------------------------------- /src-tauri/icons/android/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/android/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /src-tauri/icons/android/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/android/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/android/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/android/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/android/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/android/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/android/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/android/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /src/adapters/fal/parsers/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Fal 响应解析器导出 3 | */ 4 | export { parseImageResponse } from './imageParser' 5 | export { parseVideoResponse } from './videoParser' 6 | -------------------------------------------------------------------------------- /src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/android/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/henjicc/Henji-AI/HEAD/src-tauri/icons/android/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /src-tauri/icons/android/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #fff 4 | -------------------------------------------------------------------------------- /src/adapters/_template/parsers/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 响应解析器统一导出 3 | */ 4 | 5 | export { imageParser } from './imageParser' 6 | export { videoParser } from './videoParser' 7 | export { audioParser } from './audioParser' 8 | -------------------------------------------------------------------------------- /src/adapters/ppio/parsers/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 派欧云响应解析器导出 3 | */ 4 | export { parseImageResponse } from './imageParser' 5 | export { parseVideoResponse } from './videoParser' 6 | export { parseAudioResponse } from './audioParser' 7 | -------------------------------------------------------------------------------- /src/adapters/ppio/config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 派欧云适配器配置 3 | */ 4 | export const PPIO_CONFIG = { 5 | baseURL: 'https://api.ppinfra.com/v3', 6 | statusEndpoint: '/async/task-result', 7 | pollInterval: 3000, 8 | maxPollAttempts: 120 9 | } as const 10 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | interface ImportMetaEnv { 4 | readonly DEV: boolean 5 | readonly PROD: boolean 6 | readonly MODE: string 7 | } 8 | 9 | interface ImportMeta { 10 | readonly env: ImportMetaEnv 11 | } 12 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } -------------------------------------------------------------------------------- /docs/api/fal/sora2/sora-2-Price.txt: -------------------------------------------------------------------------------- 1 | Sora 2 Image To Video Pro & Sora 2 Text To Video Pro: 2 | The pricing is $0.30/s for 720p and $0.50/s for 1080p. 3 | 4 | Sora 2 Video To Video Remix & Fal Ai Sora 2 Text To Video & Fal Ai Sora 2 Image To Video: 5 | The pricing is $0.1/s for Sora 2. 6 | 7 | -------------------------------------------------------------------------------- /src-tauri/icons/android/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /docs/api/fal/wan/wan-25-Price.txt: -------------------------------------------------------------------------------- 1 | Fal Ai Wan 25 Preview Image To Image & Fal Ai Wan 25 Preview Text To Image: 2 | Your request will cost $0.05 per image. 3 | 4 | Fal Ai Wan 25 Preview Image To Video & Fal Ai Wan 25 Preview Text To Video: 5 | Your request will cost $0.05 per second for 480p, $0.10 per second for 720p, $0.15 per second for 1080p. 6 | 7 | -------------------------------------------------------------------------------- /docs/api/fal/LTX-2/LTX-2-Price.txt: -------------------------------------------------------------------------------- 1 | Ltx 2 Text To Video & Ltx 2 Image To Video: 2 | Your request will cost $0.06 per second for 1080p, $0.12 per second for 1440p or $0.24 per second for 2160p. 3 | 4 | Ltx 2 Image To Video Fast & Ltx 2 Text To Video Fast: 5 | Your request will cost $0.04 per second for 1080p, $0.08 per second for 1440p or $0.16 per second for 2160p. 6 | 7 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/基础/API_鉴权方式.md: -------------------------------------------------------------------------------- 1 | # API 鉴权方式 2 | 3 | PPIO 派欧云平台 API 使用请求头中的 `Authorization` 字段携带 API 密钥进行身份认证。您可以在 [API 密钥管理页面](https://ppio.com/settings/key-management) 查看和管理您的 API 密钥。 4 | 5 | 在请求头中添加以下字段: 6 | 7 | ```json 8 | { 9 | "Authorization": "Bearer {{API 密钥}}" 10 | } 11 | ``` 12 | 13 | > 有关 API 错误码的说明,请参阅 [API 错误码说明](/docs/models/reference-error-code)。 -------------------------------------------------------------------------------- /src/components/ui/ParamRow.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | type ParamRowProps = { 4 | children: React.ReactNode 5 | className?: string 6 | } 7 | 8 | export default function ParamRow(props: ParamRowProps) { 9 | const { children, className } = props 10 | return ( 11 |
{children}
12 | ) 13 | } 14 | 15 | -------------------------------------------------------------------------------- /src/adapters/modelscope/config.ts: -------------------------------------------------------------------------------- 1 | export const MODELSCOPE_CONFIG = { 2 | baseURL: 'https://api-inference.modelscope.cn', 3 | statusEndpoint: '/v1/tasks', 4 | pollInterval: 3000, 5 | maxPollAttempts: 120 6 | } as const 7 | 8 | // 预设模型列表(方便修改) 9 | export const PRESET_MODELS = [ 10 | { id: 'Tongyi-MAI/Z-Image-Turbo', name: 'Z-Image-Turbo' }, 11 | { id: 'Qwen/Qwen-Image', name: 'Qwen-image' }, 12 | { id: 'black-forest-labs/FLUX.1-Krea-dev', name: 'FLUX.1-Krea-dev' } 13 | ] as const 14 | -------------------------------------------------------------------------------- /docs/api/fal/pixverse/pixverse-v5.5-Price.txt: -------------------------------------------------------------------------------- 1 | Pixverse V5.5 Transition & Pixverse V5.5 Image To Video & Pixverse V5.5 Text To Video: 2 | For a 5s video in single-clip mode without audio, your request will cost $0.15 for 360p and 540p, $0.2 for 720p, and $0.4 for 1080p. Enabling audio adds $0.05, and multi-clip mode adds $0.10 (or $0.15 with audio). For 8-second videos, costs double; for 10-second videos, costs are 2.2x the 5-second base (1080p not supported for 10s). For $1 you can run this model with approximately 2 times. 3 | -------------------------------------------------------------------------------- /src-tauri/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleLocalizations 6 | 7 | zh_CN 8 | zh_Hans 9 | zh 10 | en 11 | 12 | CFBundleDevelopmentRegion 13 | zh_CN 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/adapters/ppio/parsers/imageParser.ts: -------------------------------------------------------------------------------- 1 | import { ImageResult } from '@/adapters/base/BaseAdapter' 2 | 3 | /** 4 | * 解析派欧云图片响应 5 | */ 6 | export const parseImageResponse = async ( 7 | responseData: any 8 | ): Promise => { 9 | if (responseData.images && responseData.images.length > 0) { 10 | // 返回所有图片URL,用分隔符连接 11 | return { 12 | url: responseData.images.join('|||'), 13 | createdAt: new Date() 14 | } 15 | } 16 | 17 | throw new Error('No image returned from API') 18 | } 19 | -------------------------------------------------------------------------------- /src/types/index.ts: -------------------------------------------------------------------------------- 1 | export interface MediaResult { 2 | id: string 3 | type: 'image' | 'video' | 'audio' 4 | url: string 5 | filePath?: string 6 | base64Data?: string // 添加Base64数据字段,用于离线下载和复制 7 | prompt: string 8 | createdAt: Date 9 | } 10 | 11 | export interface Provider { 12 | id: string 13 | name: string 14 | type: string 15 | models: Model[] 16 | } 17 | 18 | export interface Model { 19 | id: string 20 | name: string 21 | type: 'image' | 'video' | 'audio' 22 | description: string 23 | } 24 | -------------------------------------------------------------------------------- /src/adapters/kie/config.ts: -------------------------------------------------------------------------------- 1 | export const KIE_CONFIG = { 2 | baseURL: 'https://api.kie.ai', 3 | uploadBaseURL: 'https://kieai.redpandaai.co', 4 | createTaskEndpoint: '/api/v1/jobs/createTask', 5 | statusEndpoint: '/api/v1/jobs/recordInfo', 6 | fileUploadEndpoint: '/api/file-stream-upload', 7 | pollInterval: 3000, // 轮询间隔(毫秒) 8 | maxPollAttempts: 200, // 最大轮询次数(10分钟) 9 | 10 | // 模型预估轮询次数配置 11 | modelEstimatedPolls: { 12 | 'nano-banana-pro': 30, // 预估30次轮询(约1.5分钟) 13 | } 14 | } as const 15 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | import path from 'path' 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [react()], 8 | resolve: { 9 | alias: { 10 | '@': path.resolve(__dirname, './src') 11 | } 12 | }, 13 | server: { 14 | port: 3000 15 | }, 16 | build: { 17 | rollupOptions: { 18 | output: { 19 | manualChunks: { 20 | 'react-vendor': ['react', 'react-dom'], 21 | } 22 | } 23 | } 24 | } 25 | }) -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: [ 4 | "./index.html", 5 | "./src/**/*.{js,ts,jsx,tsx}", 6 | ], 7 | theme: { 8 | extend: { 9 | colors: { 10 | // 暗色主题 11 | dark: { 12 | bg: '#0a0b0d', 13 | 'bg-secondary': '#1a1a1a', 14 | text: '#ffffff', 15 | 'text-secondary': '#a0a0a0', 16 | border: '#404040', 17 | accent: '#007eff', 18 | } 19 | } 20 | }, 21 | }, 22 | plugins: [], 23 | darkMode: 'class', 24 | } 25 | -------------------------------------------------------------------------------- /docs/api/fal/minimax/minimax-hailuo-2.3-Price.txt: -------------------------------------------------------------------------------- 1 | Hailuo 2.3 Pro Image To Video & Hailuo 2.3 Pro Text To Video: 2 | Your request will cost $0.49 per video generation. 3 | 4 | Hailuo 2.3 Fast Standard Image To Video: 5 | Your request will cost $0.19 per 6 second video generation, and a $0.32 per 10 second video generation. 6 | 7 | Hailuo 2.3 Standard Image To Video & Hailuo 2.3 Standard Text To Video: 8 | Your request will cost $0.28 per 6 second video generation, and a $0.56 per 10 second video generation. 9 | 10 | Hailuo 2.3 Fast Pro Image To Video: 11 | Your request will cost $0.33 per video. 12 | 13 | -------------------------------------------------------------------------------- /src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import App from './App' 4 | import './index.css' 5 | import './styles/scrollbar.css' 6 | import { DragDropProvider } from './contexts/DragDropContext' 7 | import GlobalContextMenuProvider from './contexts/GlobalContextMenuProvider' 8 | 9 | ReactDOM.createRoot(document.getElementById('root')!).render( 10 | 11 | 12 | 13 | 14 | 15 | 16 | , 17 | ) 18 | -------------------------------------------------------------------------------- /src/adapters/_template/parsers/audioParser.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 音频响应解析器模板 3 | */ 4 | 5 | import { ResponseParser } from '../types' 6 | import { AudioResult } from '../../base/BaseAdapter' 7 | 8 | export const audioParser: ResponseParser = { 9 | async parse(responseData: any, _adapter: any): Promise { 10 | if (responseData.audio_url || responseData.url) { 11 | return { 12 | url: responseData.audio_url || responseData.url, 13 | status: 'completed' 14 | } 15 | } 16 | 17 | throw new Error('No audio found in response') 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/adapters/ppio/parsers/audioParser.ts: -------------------------------------------------------------------------------- 1 | import { AudioResult } from '@/adapters/base/BaseAdapter' 2 | 3 | /** 4 | * 解析派欧云音频响应 5 | */ 6 | export const parseAudioResponse = async ( 7 | responseData: any 8 | ): Promise => { 9 | // MiniMax Speech 2.6 返回格式: { audio: "url", extra_info: {...} } 10 | if (responseData.audio) { 11 | return { 12 | url: responseData.audio 13 | } 14 | } 15 | 16 | // 其他音频模型可能的格式: { audios: [{audio_url: "url"}] } 17 | if (responseData.audios && responseData.audios.length > 0) { 18 | return { 19 | url: responseData.audios[0].audio_url 20 | } 21 | } 22 | 23 | throw new Error('No audio returned from API') 24 | } 25 | -------------------------------------------------------------------------------- /src/adapters/_template/models/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 模型路由注册中心 3 | * 4 | * 使用说明: 5 | * 1. 导入所有模型路由 6 | * 2. 添加到 routes 数组 7 | * 3. findRoute 函数会自动查找匹配的路由 8 | */ 9 | 10 | import { ModelRoute } from '../types' 11 | import { exampleModelRoute } from './exampleModel' 12 | // import { anotherModelRoute } from './anotherModel' // 添加更多模型 13 | 14 | /** 15 | * 所有模型路由列表 16 | */ 17 | export const routes: ModelRoute[] = [ 18 | exampleModelRoute, 19 | // anotherModelRoute, // 添加更多路由 20 | ] 21 | 22 | /** 23 | * 查找匹配的模型路由 24 | * @param modelId 模型ID 25 | * @returns 匹配的路由,如果没找到返回 undefined 26 | */ 27 | export const findRoute = (modelId: string): ModelRoute | undefined => { 28 | return routes.find(route => route.matches(modelId)) 29 | } 30 | -------------------------------------------------------------------------------- /docs/api/fal/minimax/minimax-hailuo-02-Price.txt: -------------------------------------------------------------------------------- 1 | Hailuo 02 Standard Text To Video: 2 | For each second of video generated, it will cost $0.045/sec. A single 6 second video will cost $0.27/video. 3 | 4 | Minimax Hailuo 02 Fast Image To Video: 5 | For each second of video generated at 512P, it will cost roughly $0.017/sec 6 | 7 | Hailuo 02 Standard Image To Video: 8 | For each second of video generated at 768P, it will cost $0.045/sec. For each second of video generated at 512P, it will cost roughly $0.017/sec. A single 6 second 768p video will cost $0.27/video. 9 | 10 | Hailuo 02 Pro Image To Video & Hailuo 02 Pro Text To Video: 11 | For each second of video generated, it will cost $0.08/sec. A single 6 second video will cost $0.48/video. 12 | 13 | -------------------------------------------------------------------------------- /src-tauri/wix/license.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\deff0 {\fonttbl {\f0 Times New Roman;}} 2 | {\colortbl;\red0\green0\blue0;} 3 | \f0\fs24 4 | \b 痕迹AI 许可协议 5 | 6 | 版权所有 (c) 2024 痕迹AI开发团队 7 | 8 | 感谢您选择使用痕迹AI。本软件按以下条款和条件提供: 9 | 10 | 一、使用许可 11 | 在您遵守本许可协议条款的前提下,我们授予您非独占、不可转让的许可,以使用本软件。 12 | 13 | 二、限制条款 14 | 1. 禁止逆向工程、反编译或反汇编本软件。 15 | 2. 禁止修改、翻译或创建基于本软件的衍生作品。 16 | 3. 禁止分发、出租、租赁或转让本软件。 17 | 18 | 三、数据使用 19 | 本软件可能需要调用第三方AI服务API,请确保您: 20 | 1. 遵守各API服务提供商的使用条款。 21 | 2. 承担所有API调用产生的费用。 22 | 3. 保护您的API密钥安全。 23 | 24 | 四、免责声明 25 | 本软件按"现状"提供,不提供任何明示或暗示的担保。使用本软件产生的任何损失由用户自行承担。 26 | 27 | 五、责任限制 28 | 在任何情况下,开发者都不承担因使用或无法使用本软件而造成的任何直接、间接、偶然或特殊损害。 29 | 30 | 六、条款变更 31 | 我们保留随时修改本许可协议的权利,变更后的协议将在软件更新时生效。 32 | 33 | 如有任何问题,请联系我们:https://henji.ai 34 | 35 | 最后更新:2024年 36 | } -------------------------------------------------------------------------------- /src/adapters/fal/parsers/imageParser.ts: -------------------------------------------------------------------------------- 1 | import { ImageResult } from '@/adapters/base/BaseAdapter' 2 | 3 | /** 4 | * 解析 Fal 图片响应 5 | */ 6 | export const parseImageResponse = async ( 7 | responseData: any 8 | ): Promise => { 9 | // 官方 SDK 返回的结构:{ data: { images: [...] }, requestId: "..." } 10 | // 或旧的队列 API 结构:{ images: [...], description: "..." } 11 | 12 | // 优先检查官方 SDK 格式 13 | const data = responseData.data || responseData 14 | 15 | if (data.images && data.images.length > 0) { 16 | const imageUrls = data.images.map((img: any) => img.url) 17 | return { 18 | url: imageUrls.join('|||'), 19 | createdAt: new Date() 20 | } 21 | } 22 | 23 | throw new Error('No images returned from queue') 24 | } 25 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true, 5 | "node": true 6 | }, 7 | "extends": [ 8 | "eslint:recommended", 9 | "plugin:@typescript-eslint/recommended", 10 | "plugin:react-hooks/recommended" 11 | ], 12 | "parser": "@typescript-eslint/parser", 13 | "parserOptions": { 14 | "ecmaFeatures": { 15 | "jsx": true 16 | }, 17 | "ecmaVersion": 12, 18 | "sourceType": "module" 19 | }, 20 | "plugins": [ 21 | "react-refresh", 22 | "@typescript-eslint" 23 | ], 24 | "rules": { 25 | "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }], 26 | "react-refresh/only-export-components": "warn", 27 | "no-unused-vars": "off" 28 | } 29 | } -------------------------------------------------------------------------------- /src-tauri/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "henji-ai" 3 | version = "0.1.1" 4 | description = "一个聚合多家AI供应商,一站式生成图片、视频和音频的客户端" 5 | authors = ["henjicc"] 6 | license = "Apache-2.0" 7 | repository = "https://github.com/henjicc/Henji-AI" 8 | edition = "2021" 9 | rust-version = "1.70" 10 | 11 | [dependencies] 12 | tauri = { version = "2.0.0", features = ["protocol-asset", "devtools"] } 13 | tauri-plugin-fs = "2.0.0" 14 | tauri-plugin-dialog = "2.0.0" 15 | tauri-plugin-http = "2.0.0" 16 | tauri-plugin-shell = "2.0.0" 17 | tauri-plugin-clipboard-manager = "2.0.0" 18 | serde = { version = "1.0", features = ["derive"] } 19 | serde_json = "1.0" 20 | reqwest = { version = "0.11", features = ["json"] } 21 | base64 = "0.21" 22 | 23 | [build-dependencies] 24 | tauri-build = { version = "2.0.0", features = [] } 25 | -------------------------------------------------------------------------------- /src/models/kie-grok-imagine.ts: -------------------------------------------------------------------------------- 1 | import { ParamDef } from '../types/schema' 2 | 3 | export const kieGrokImagineParams: ParamDef[] = [ 4 | // 宽高比参数(仅比例选择,无分辨率选项) 5 | { 6 | id: 'kieGrokImagineAspectRatio', 7 | type: 'dropdown', 8 | defaultValue: '1:1', 9 | resolutionConfig: { 10 | type: 'aspect_ratio', 11 | smartMatch: false, // 不支持智能匹配(无图片上传) 12 | visualize: true, // 显示可视化预览 13 | extractRatio: (value) => { 14 | const [w, h] = value.split(':').map(Number) 15 | return w / h 16 | } 17 | // 注意:无 qualityOptions 和 qualityKey(不支持分辨率选择) 18 | }, 19 | options: [ 20 | { value: '1:1', label: '1:1' }, 21 | { value: '2:3', label: '2:3' }, 22 | { value: '3:2', label: '3:2' } 23 | ], 24 | className: 'min-w-[100px]' 25 | } 26 | ] 27 | -------------------------------------------------------------------------------- /docs/api/fal/kling/kling-Price.txt: -------------------------------------------------------------------------------- 1 | # 可灵 2.5 Turbo 2 | kling V2.5 Turbo Pro Image To Video: 3 | For 5s video your request will cost $0.35. For every additional second you will be charged $0.07. 4 | 5 | kling V2.5 Turbo Pro Text To Video: 6 | For 5s video your request will cost $0.35. For every aditional second you will be charged $0.07. 7 | 8 | kling V2.5 Turbo Standard Image To Video: 9 | For 5s video your request will cost $0.21. For every additional second you will be charged $0.042. 10 | 11 | # 可灵 01 12 | Kling Video O1 Image To Video & Kling Video O1 Reference To Video: 13 | Your request will cost $0.112 per second. 14 | 15 | Kling Video O1 Video To Video Reference & O1 Video To Video Edit: 16 | Your request will cost $0.168 per second. 17 | 18 | # 可灵图片 01 19 | Kling Image O1: 20 | Your request will cost $0.028 per image. -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | 16 | /* Linting */ 17 | "strict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "noFallthroughCasesInSwitch": true, 21 | 22 | /* JSX */ 23 | "jsx": "react-jsx", 24 | 25 | /* Paths */ 26 | "baseUrl": ".", 27 | "paths": { 28 | "@/*": ["src/*"] 29 | } 30 | }, 31 | "include": ["src"], 32 | "references": [{ "path": "./tsconfig.node.json" }] 33 | } -------------------------------------------------------------------------------- /src/utils/progress.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 计算进度,支持渐近式增长 3 | * @param current 当前消耗(时间或次数) 4 | * @param expected 预期消耗(时间或次数) 5 | * @returns 进度值 (0-99) 6 | */ 7 | export const calculateProgress = (current: number, expected: number): number => { 8 | if (current <= expected) { 9 | // 预期范围内:使用 easeOutQuad 快速到达 95% 10 | const ratio = current / expected 11 | // easeOutQuad: 1 - (1 - t) * (1 - t) 12 | const easeProgress = 1 - (1 - ratio) * (1 - ratio) 13 | return Math.floor(easeProgress * 95) 14 | } else { 15 | // 超过预期:缓慢逼近 99% 16 | // 使用指数衰减 17 | // 假设衰减常数为预期的 50% (即超过预期时间的一半后,差距缩小约 63%) 18 | const extra = current - expected 19 | const decay = expected * 0.5 20 | const extraProgress = 4 * (1 - Math.exp(-extra / decay)) 21 | return Math.min(99, 95 + Math.floor(extraProgress)) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/models/kie-z-image.ts: -------------------------------------------------------------------------------- 1 | import { ParamDef } from '../types/schema' 2 | 3 | export const kieZImageParams: ParamDef[] = [ 4 | // 宽高比参数(仅比例选择,无分辨率选项) 5 | { 6 | id: 'kieZImageAspectRatio', 7 | type: 'dropdown', 8 | defaultValue: '1:1', 9 | resolutionConfig: { 10 | type: 'aspect_ratio', 11 | smartMatch: false, // 不支持智能匹配(无图片上传) 12 | visualize: true, // 显示可视化预览 13 | extractRatio: (value) => { 14 | const [w, h] = value.split(':').map(Number) 15 | return w / h 16 | } 17 | // 注意:无 qualityOptions 和 qualityKey(不支持分辨率选择) 18 | }, 19 | options: [ 20 | { value: '1:1', label: '1:1' }, 21 | { value: '4:3', label: '4:3' }, 22 | { value: '3:4', label: '3:4' }, 23 | { value: '16:9', label: '16:9' }, 24 | { value: '9:16', label: '9:16' } 25 | ], 26 | className: 'min-w-[100px]' 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /src/adapters/_template/config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 供应商适配器配置模板 3 | * 4 | * 使用说明: 5 | * 1. 将所有 'your-provider' 替换为实际的供应商ID 6 | * 2. 修改 BASE_URL 为实际的API地址 7 | * 3. 根据认证方式选择 AUTH_TYPE 8 | * 4. 如果支持异步任务,配置轮询相关参数 9 | */ 10 | 11 | export const CONFIG = { 12 | // 供应商标识 13 | PROVIDER_ID: 'your-provider', // 修改为实际ID (如: 'openai', 'anthropic') 14 | PROVIDER_NAME: 'Your Provider Name', // 修改为实际名称 (如: 'OpenAI') 15 | 16 | // API配置 17 | BASE_URL: 'https://api.example.com', // 修改为实际API基础URL 18 | AUTH_TYPE: 'bearer' as const, // 'bearer' 或 'apikey' 19 | 20 | // 状态查询配置 (如果API支持异步任务轮询) 21 | STATUS_ENDPOINT: '/task/status', // 状态查询端点 22 | POLL_INTERVAL: 3000, // 轮询间隔(毫秒) 23 | MAX_POLL_ATTEMPTS: 120, // 最大轮询次数 24 | 25 | // 超时配置 26 | REQUEST_TIMEOUT: 60000, // 请求超时(毫秒) 27 | } 28 | 29 | // 类型定义 30 | export type AuthType = typeof CONFIG.AUTH_TYPE 31 | -------------------------------------------------------------------------------- /docs/api/fal/vidu-q2/vidu-q2-Price.txt: -------------------------------------------------------------------------------- 1 | Vidu Q2 Reference To Image & Vidu Q2 Text To Image & Fal Ai Vidu Reference To Image: 2 | Your request will cost $0.1 per image. 3 | 4 | Q2 Video Extension Pro: 5 | Each 360 p video will cost 0.15 $, each 520p video will cost 0.22 $. For 720 p each video second will cost 0.075 $. For 1080 p each video will cost 0.28 $ along with 0.075 $ per video second. 6 | 7 | Q2 Image To Video Turbo: 8 | For 720 p each video second will cost 0.05 $. For 1080 p each request will cost 0.2 $ along with 0.05 $ for every video second. 9 | 10 | Q2 Image To Video Pro: 11 | For 720 p your video request would cost 0.1 $ along with a 0.05 $ for every video second. For 1080 p each request will cost 0.3 $ along with 0.1 $ for every video second. 12 | 13 | Vidu Q2 Text To Video: 14 | The model will cost 0.1 $ for every 360p video, 0.2 $ for every 520p video, 0.3 $ for 720 p video. For 1080 p the cost would be 0.2 $ along with 0.1 $ for every video second. -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/基础/获取账户信息.md: -------------------------------------------------------------------------------- 1 | # 获取账户信息 2 | 3 | > 来源: https://ppio.com/docs/models/reference-get-user-info 4 | 5 | 「获取账户信息 API」主要用于查询账户余额等信息。 6 | 7 | **请求方法:** GET 8 | 9 | **请求地址:** `https://api.ppinfra.com/v3/user` 10 | 11 | ## 请求示例 12 | 13 | ```bash 14 | curl --request GET \ 15 | --url https://api.ppinfra.com/v3/user \ 16 | --header 'Authorization: ' \ 17 | --header 'Content-Type: ' 18 | ``` 19 | 20 | ## 响应示例 21 | 22 | ```json 23 | { 24 | "credit_balance": 123 25 | } 26 | ``` 27 | 28 | ## 请求头 29 | 30 | | 参数名 | 类型 | 是否必需 | 说明 | 31 | | :--- | :--- | :--- | :--- | 32 | | `Content-Type` | string | 是 | 固定为 `application/json`。 | 33 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 34 | 35 | ## 响应参数 36 | 37 | | 参数名 | 类型 | 说明 | 38 | | :--- | :--- | :--- | 39 | | `credit_balance` | number | 账户余额信息。 | 40 | 41 | ## 相关链接 42 | * [API 错误码说明](/docs/models/reference-error-code) 43 | * [查询账单](/docs/models/reference-get-bill-pay-as-you-model) -------------------------------------------------------------------------------- /src/adapters/ppio/parsers/videoParser.ts: -------------------------------------------------------------------------------- 1 | import { VideoResult } from '@/adapters/base/BaseAdapter' 2 | import { BaseAdapter } from '@/adapters/base/BaseAdapter' 3 | 4 | /** 5 | * 解析派欧云视频响应 6 | */ 7 | export const parseVideoResponse = async ( 8 | responseData: any, 9 | adapter: BaseAdapter 10 | ): Promise => { 11 | if (responseData.videos && responseData.videos.length > 0) { 12 | const videoUrl = responseData.videos[0].video_url 13 | 14 | // 使用基类的保存方法 15 | try { 16 | const savedResult = await adapter['saveMediaLocally'](videoUrl, 'video') 17 | return { 18 | url: savedResult.url, 19 | filePath: savedResult.filePath, 20 | status: 'TASK_STATUS_SUCCEEDED' 21 | } 22 | } catch (e) { 23 | adapter['log']('视频本地保存失败,回退为远程URL', e) 24 | return { 25 | url: videoUrl, 26 | status: 'TASK_STATUS_SUCCEEDED' 27 | } 28 | } 29 | } 30 | 31 | throw new Error('No video returned from API') 32 | } 33 | -------------------------------------------------------------------------------- /docs/api/fal/base/model-endpoints.md: -------------------------------------------------------------------------------- 1 | # Model Endpoints API | fal.ai Reference 2 | 3 | > Model endpoints are the entry point to interact with the fal API. They are exposed through simple HTTP APIs that can be called from any programming language. 4 | 5 | In the next sections you will learn how to call these endpoints in 3 ways: 6 | 7 | * `https://queue.fal.run` exposes our [Queue](/model-apis/model-endpoints/queue), the recommended way to interact with the fal API 8 | * `https://fal.run` allows [synchronous execution](/model-apis/model-endpoints/synchronous-requests) of models 9 | * `wss://ws.fal.run` allows submitting requests via a [WebSocket connection](/model-apis/model-endpoints/websockets) 10 | 11 | We also offer [clients](/model-apis/clients) for some of the popular programming languages used by our community. 12 | 13 | 14 | **There is no api.fal.ai domain** 15 | 16 | Note that the fal API does not use the `api.fal.ai` domain. Please refer to the 3 options above. 17 | 18 | -------------------------------------------------------------------------------- /src/components/ui/TextInput.tsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | type TextInputProps = { 4 | label?: string 5 | value: string 6 | onChange: (next: string) => void 7 | placeholder?: string 8 | className?: string 9 | inputClassName?: string 10 | } 11 | 12 | export default function TextInput(props: TextInputProps) { 13 | const { label, value, onChange, placeholder, className, inputClassName } = props 14 | return ( 15 |
16 | {label ? : null} 17 | onChange(e.target.value)} 20 | placeholder={placeholder} 21 | className={`bg-zinc-800/70 border border-zinc-700/50 rounded-lg px-3 py-2 h-[38px] text-sm outline-none focus:outline-none appearance-none focus:ring-inset focus:ring-2 focus:ring-[#007eff]/60 focus:ring-offset-0 focus:ring-offset-transparent focus:border-[#007eff] transition-shadow duration-300 ease-out ${inputClassName || 'w-full'}`} 22 | /> 23 |
24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /src/adapters/_template/parsers/videoParser.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 视频响应解析器模板 3 | */ 4 | 5 | import { ResponseParser } from '../types' 6 | import { VideoResult } from '../../base/BaseAdapter' 7 | 8 | export const videoParser: ResponseParser = { 9 | async parse(responseData: any, adapter: any): Promise { 10 | // 示例: 同步返回视频URL 11 | if (responseData.video_url) { 12 | const videoUrl = responseData.video_url 13 | 14 | // 使用适配器基类的保存方法保存到本地 15 | try { 16 | const savedResult = await adapter.saveMediaLocally(videoUrl, 'video') 17 | return { 18 | url: savedResult.url, 19 | status: 'completed' 20 | } 21 | } catch (e) { 22 | adapter.log('视频保存失败,使用远程URL', e) 23 | return { 24 | url: videoUrl, 25 | status: 'completed' 26 | } 27 | } 28 | } 29 | 30 | throw new Error('No video found in response') 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /docs/api/fal/bytedance/Seedance-Price.txt: -------------------------------------------------------------------------------- 1 | Pro Fast Text To Video: 2 | Each 1080p 5 second video costs roughly $0.245. For other resolutions, 1 million video tokens costs $1. tokens(video) = (height x width x FPS x duration) / 1024. 3 | 4 | Pro Fast Image To Video: 5 | Each 1080p 5 second video costs roughly $0.243. For other resolutions, 1 million video tokens costs $1.0. tokens(video) = (height x width x FPS x duration) / 1024. 6 | 7 | Lite Reference To Video: 8 | Each 720p 5 second video costs $0.18. For other resolutions, 1 million video tokens costs $1.8. tokens(video) = (height x width x FPS x duration) / 1024. Image tokens costs will be included. 9 | 10 | Pro Image To Video & Pro Text To Video: 11 | Each 1080p 5 second video costs roughly $0.62. For other resolutions, 1 million video tokens costs $2.5. tokens(video) = (height x width x FPS x duration) / 1024. 12 | 13 | Lite Image To Video & Lite Text To Video: 14 | Each 720p 5 second video costs $0.18. For other resolutions, 1 million video tokens costs $1.8. tokens(video) = (height x width x FPS x duration) / 1024. 15 | 16 | -------------------------------------------------------------------------------- /src/adapters/kie/models/z-image.ts: -------------------------------------------------------------------------------- 1 | import { GenerateImageParams } from '@/adapters/base/BaseAdapter' 2 | 3 | export interface KIEModelRoute { 4 | matches: (modelId: string) => boolean 5 | buildImageRequest?: (params: GenerateImageParams) => { 6 | requestData: any 7 | } 8 | } 9 | 10 | export const kieZImageRoute: KIEModelRoute = { 11 | matches: (modelId: string) => 12 | modelId === 'kie-z-image' || 13 | modelId === 'z-image-kie', 14 | 15 | buildImageRequest: (params: GenerateImageParams) => { 16 | const prompt = params.prompt || '' 17 | 18 | // 构建请求数据 19 | const requestData: any = { 20 | model: 'z-image', 21 | input: { 22 | prompt: prompt 23 | } 24 | } 25 | 26 | // 添加可选参数:aspect_ratio 27 | if (params.aspect_ratio !== undefined && 28 | params.aspect_ratio !== 'smart' && 29 | params.aspect_ratio !== 'auto') { 30 | requestData.input.aspect_ratio = params.aspect_ratio 31 | } 32 | 33 | // 注意:Z-Image 不支持图片输入,仅支持文本生成图片 34 | // 不需要处理 images 参数 35 | 36 | return { requestData } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/adapters/modelscope/parsers/imageParser.ts: -------------------------------------------------------------------------------- 1 | import { ImageResult } from '@/adapters/base/BaseAdapter' 2 | 3 | export const parseImageResponse = (responseData: any): ImageResult => { 4 | // 魔搭API异步模式返回 task_id 5 | if (responseData.task_id) { 6 | return { 7 | taskId: responseData.task_id, 8 | url: '' 9 | } 10 | } 11 | 12 | // 同步模式返回图片URL(新格式:images 数组) 13 | if (responseData.images && Array.isArray(responseData.images)) { 14 | // images 数组中每个元素是 { url: "..." } 格式 15 | const urls = responseData.images.map((img: any) => img.url) 16 | return { 17 | url: urls.length > 1 ? urls.join('|||') : urls[0], 18 | status: 'completed' 19 | } 20 | } 21 | 22 | // 同步模式返回图片URL(旧格式:output_images 数组,兼容) 23 | if (responseData.output_images && Array.isArray(responseData.output_images)) { 24 | const urls = responseData.output_images 25 | return { 26 | url: urls.length > 1 ? urls.join('|||') : urls[0], 27 | status: 'completed' 28 | } 29 | } 30 | 31 | throw new Error('No image or task_id returned from ModelScope API') 32 | } 33 | -------------------------------------------------------------------------------- /src/adapters/fal/parsers/videoParser.ts: -------------------------------------------------------------------------------- 1 | import { VideoResult } from '@/adapters/base/BaseAdapter' 2 | import { BaseAdapter } from '@/adapters/base/BaseAdapter' 3 | 4 | /** 5 | * 解析 Fal 视频响应 6 | */ 7 | export const parseVideoResponse = async ( 8 | responseData: any, 9 | adapter: BaseAdapter 10 | ): Promise => { 11 | // 官方 SDK 返回的结构:{ data: { video: { url: "..." } }, requestId: "..." } 12 | // 或旧的队列 API 结构:{ video: { url: "..." } } 13 | 14 | // 优先检查官方 SDK 格式 15 | const data = responseData.data || responseData 16 | 17 | if (data.video) { 18 | const videoUrl = data.video.url 19 | let result: VideoResult = { 20 | url: videoUrl, 21 | status: 'COMPLETED' 22 | } 23 | 24 | // 使用基类的保存方法 25 | try { 26 | const savedResult = await adapter['saveMediaLocally'](videoUrl, 'video') 27 | result.url = savedResult.url 28 | ; (result as any).filePath = savedResult.filePath 29 | } catch (e) { 30 | adapter['log']('视频本地保存失败,回退为远程URL', e) 31 | } 32 | 33 | return result 34 | } 35 | 36 | throw new Error('No video returned from queue') 37 | } 38 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 痕迹AI 8 | 17 | 30 | 31 | 32 |
33 | 34 | 35 | -------------------------------------------------------------------------------- /src/adapters/_template/types.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 供应商适配器类型定义 3 | */ 4 | 5 | import { GenerateImageParams, GenerateVideoParams, GenerateAudioParams } from '../base/BaseAdapter' 6 | 7 | /** 8 | * 模型路由接口 9 | * 每个模型对应一个路由,负责构建该模型的API请求 10 | */ 11 | export interface ModelRoute { 12 | /** 13 | * 判断是否匹配该模型 14 | * @param modelId 模型ID 15 | * @returns 是否匹配 16 | */ 17 | matches(modelId: string): boolean 18 | 19 | /** 20 | * 构建API请求 21 | * @param params 生成参数 22 | * @returns 端点和请求数据 23 | */ 24 | buildRequest(params: GenerateImageParams | GenerateVideoParams | GenerateAudioParams): { 25 | endpoint: string 26 | requestData: any 27 | } 28 | 29 | /** 30 | * 可选: 自定义响应处理 31 | * 如果不提供,使用默认解析器 32 | */ 33 | parseResponse?(response: any): any 34 | } 35 | 36 | /** 37 | * 响应解析器接口 38 | */ 39 | export interface ResponseParser { 40 | /** 41 | * 解析API响应 42 | * @param responseData API响应数据 43 | * @param adapter 适配器实例 (用于调用通用方法如saveMediaLocally) 44 | * @returns 解析后的结果 45 | */ 46 | parse(responseData: any, adapter: any): Promise 47 | } 48 | -------------------------------------------------------------------------------- /src/adapters/index.ts: -------------------------------------------------------------------------------- 1 | import { MediaGeneratorAdapter } from './base/BaseAdapter' 2 | import { PPIOAdapter } from './ppio/PPIOAdapter' 3 | import { FalAdapter } from './fal/FalAdapter' 4 | import { ModelscopeAdapter } from './modelscope/ModelscopeAdapter' 5 | import { KIEAdapter } from './kie/KIEAdapter' 6 | 7 | export type AdapterType = 'ppio' | 'fal' | 'modelscope' | 'kie' | 'openai' | 'stability' | 'midjourney' 8 | 9 | export interface AdapterConfig { 10 | type: AdapterType 11 | apiKey: string 12 | modelName: string 13 | falApiKey?: string // 用于文件上传(魔搭等需要 URL 的适配器) 14 | } 15 | 16 | export class AdapterFactory { 17 | static createAdapter(config: AdapterConfig): MediaGeneratorAdapter { 18 | switch (config.type) { 19 | case 'ppio': 20 | return new PPIOAdapter(config.apiKey) 21 | case 'fal': 22 | return new FalAdapter(config.apiKey) 23 | case 'modelscope': 24 | return new ModelscopeAdapter(config.apiKey, config.falApiKey) 25 | case 'kie': 26 | return new KIEAdapter(config.apiKey) 27 | default: 28 | throw new Error(`Unsupported adapter type: ${config.type}`) 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/components/ui/Toggle.tsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | type ToggleProps = { 4 | label?: string 5 | checked: boolean 6 | onChange: (next: boolean) => void 7 | onText?: string 8 | offText?: string 9 | className?: string 10 | disabled?: boolean 11 | } 12 | 13 | export default function Toggle(props: ToggleProps) { 14 | const { label, checked, onChange, onText = '开启', offText = '关闭', className, disabled = false } = props 15 | return ( 16 |
17 | {label ? : null} 18 | 31 |
32 | ) 33 | } 34 | -------------------------------------------------------------------------------- /src/adapters/kie/models/index.ts: -------------------------------------------------------------------------------- 1 | import { kieNanoBananaProRoute, KIEModelRoute } from './nano-banana-pro' 2 | import { kieGrokImagineRoute } from './grok-imagine' 3 | import { kieGrokImagineVideoRoute } from './grok-imagine-video' 4 | import { kieSeedream45Route } from './seedream-4.5' 5 | import { kieSeedream40Route } from './seedream-4.0' 6 | import { kieZImageRoute } from './z-image' 7 | import { kieKlingV26Route } from './kling-v2-6' 8 | import { kieHailuo23Route } from './hailuo-2-3' 9 | import { kieHailuo02Route } from './hailuo-02' 10 | import { kieSeedanceV3Route } from './seedance-v3' 11 | import { kieSora2Route } from './sora2' 12 | 13 | export type { KIEModelRoute } 14 | 15 | export const kieModelRoutes: KIEModelRoute[] = [ 16 | kieNanoBananaProRoute, 17 | kieSeedream45Route, 18 | kieSeedream40Route, 19 | kieGrokImagineRoute, 20 | kieZImageRoute, 21 | kieGrokImagineVideoRoute, 22 | kieKlingV26Route, 23 | kieHailuo23Route, 24 | kieHailuo02Route, 25 | kieSeedanceV3Route, 26 | kieSora2Route 27 | ] 28 | 29 | export const findRoute = (modelId: string): KIEModelRoute | undefined => { 30 | return kieModelRoutes.find(route => route.matches(modelId)) 31 | } 32 | -------------------------------------------------------------------------------- /docs/api/fal/veo3.1/veo3.1_价格.txt: -------------------------------------------------------------------------------- 1 | Veo 3.1 文生视频:For every second of video you generated, you will be charged $0.20 (audio off) or $0.40 (audio on). For example, a 5s video with audio on will cost $2. 2 | Veo 3.1 文生视频快速模式:For every second of video you generated, you will be charged $0.10 (audio off) or $0.15 (audio on). For example, a 5s video with audio on will cost $0.75. 3 | Veo 3.1 图生视频:For every second of video you generated, you will be charged $0.20 (audio off) or $0.40 (audio on). For example, a 5s video with audio on will cost $2. 4 | Veo 3.1 图生视频快速模式:For every second of video you generated, you will be charged $0.10 (audio off) or $0.15 (audio on). For example, a 5s video with audio on will cost $0.75. 5 | Veo 3.1 首尾帧:For every second of video you generated, you will be charged $0.20 (audio off) or $0.40 (audio on). For example, a 5s video with audio on will cost $2. 6 | Veo 3.1 首尾帧快速模式:For every second of video you generated, you will be charged $0.10 (audio off) or $0.15 (audio on). For example, a 5s video with audio on will cost $0.75. 7 | Veo 3.1 参考生视频:For every second of video you generated, you will be charged $0.20 (audio off) or $0.40 (audio on). For example, a 5s video with audio on will cost $2. 8 | 9 | 当前汇率:1 美元 ≈ 7.0936 人民币,转换时保留两位小数,四舍五入 -------------------------------------------------------------------------------- /src/adapters/kie/models/grok-imagine.ts: -------------------------------------------------------------------------------- 1 | import { GenerateImageParams } from '@/adapters/base/BaseAdapter' 2 | 3 | export interface KIEModelRoute { 4 | matches: (modelId: string) => boolean 5 | buildImageRequest?: (params: GenerateImageParams) => { 6 | requestData: any 7 | } 8 | } 9 | 10 | export const kieGrokImagineRoute: KIEModelRoute = { 11 | matches: (modelId: string) => 12 | modelId === 'kie-grok-imagine' || 13 | modelId === 'grok-imagine-kie', 14 | 15 | buildImageRequest: (params: GenerateImageParams) => { 16 | const prompt = params.prompt || '' 17 | 18 | // 构建请求数据 19 | const requestData: any = { 20 | model: 'grok-imagine/text-to-image', 21 | input: { 22 | prompt: prompt 23 | } 24 | } 25 | 26 | // 添加可选参数:aspect_ratio 27 | if (params.aspect_ratio !== undefined && 28 | params.aspect_ratio !== 'smart' && 29 | params.aspect_ratio !== 'auto') { 30 | requestData.input.aspect_ratio = params.aspect_ratio 31 | } 32 | 33 | // 注意:Grok Imagine 不支持图片输入,仅支持文本生成图片 34 | // 不需要处理 images 参数 35 | 36 | // 添加回调 URL(可选,如果需要) 37 | // requestData.callBackUrl = 'https://your-domain.com/api/callback' 38 | 39 | return { requestData } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/其他/文字擦除.md: -------------------------------------------------------------------------------- 1 | # 文字擦除 2 | 3 | 文字擦除 API 能将图片中的文字内容擦除干净。 4 | 5 | **请求端点** 6 | ``` 7 | POST https://api.ppinfra.com/v3/remove-text 8 | ``` 9 | 10 | **cURL 请求示例** 11 | ```bash 12 | curl --request POST \ 13 | --url https://api.ppinfra.com/v3/remove-text \ 14 | --header 'Authorization: ' \ 15 | --header 'Content-Type: ' \ 16 | --data ' 17 | { 18 | "extra": { 19 | "response_image_type": "" 20 | }, 21 | "image_file": "" 22 | } 23 | ' 24 | ``` 25 | 26 | **响应示例** 27 | ```json 28 | { 29 | "image_file": "", 30 | "image_type": "" 31 | } 32 | ``` 33 | 34 | ## 请求头 35 | 36 | **Content-Type** `string` **必需** 37 | * 枚举值:`application/json` 38 | 39 | **Authorization** `string` **必需** 40 | * Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 41 | 42 | ## 请求体 43 | 44 | **image_file** `string` **必需** 45 | * 图片二进制的 base64 内容。 46 | * 图片长和宽均不超过 1024 像素。 47 | * 文件最大不超过 30 Mb。 48 | 49 | **extra** `object` *额外参数* 50 | 51 | * **response_image_type** `string` 52 | * 返回的图片格式,默认为 PNG。 53 | * 枚举值:`png`, `webp`, `jpeg` 54 | 55 | ## 响应参数 56 | 57 | **image_file** `string` 58 | * 图片结果的 Base64 编码内容。 59 | 60 | **image_type** `string` 61 | * 图片格式。 62 | * 枚举值:`png`, `webp`, `jpeg` -------------------------------------------------------------------------------- /src/adapters/kie/parsers/videoParser.ts: -------------------------------------------------------------------------------- 1 | import { VideoResult } from '@/adapters/base/BaseAdapter' 2 | import type { KIEAdapter } from '../KIEAdapter' 3 | 4 | /** 5 | * 解析 KIE 视频响应 6 | * @param responseData - KIE API 返回的 resultJson 解析后的数据 7 | * @param adapter - KIEAdapter 实例 8 | */ 9 | export const parseVideoResponse = async ( 10 | responseData: any, 11 | adapter: KIEAdapter 12 | ): Promise => { 13 | // KIE 返回格式: { resultUrls: ["url1"] } 14 | if (responseData.resultUrls && Array.isArray(responseData.resultUrls)) { 15 | const urls = responseData.resultUrls 16 | 17 | if (urls.length === 0) { 18 | throw new Error('API 未返回任何视频') 19 | } 20 | 21 | // 保存视频到本地 22 | try { 23 | const videoUrl = urls[0] // Grok Imagine 视频只返回一个视频 24 | const savedResult = await adapter['saveMediaLocally'](videoUrl, 'video') 25 | 26 | return { 27 | url: savedResult.url, 28 | filePath: savedResult.filePath, 29 | status: 'completed' 30 | } 31 | } catch (e) { 32 | adapter['log']('视频本地保存失败,回退为远程 URL', e) 33 | 34 | // 回退:使用远程 URL 35 | return { 36 | url: urls[0], 37 | status: 'completed' 38 | } 39 | } 40 | } 41 | 42 | throw new Error('API 未返回视频 URL') 43 | } 44 | -------------------------------------------------------------------------------- /src/adapters/ppio/models/seedream.ts: -------------------------------------------------------------------------------- 1 | import { GenerateImageParams } from '@/adapters/base/BaseAdapter' 2 | 3 | /** 4 | * 即梦 4.0 模型路由 5 | */ 6 | export const seedream40Route = { 7 | // 模型ID识别 8 | matches: (modelId: string) => modelId.includes('seedream'), 9 | 10 | // 构建图片生成请求 11 | buildImageRequest: (params: GenerateImageParams) => { 12 | const endpoint = '/seedream-4.0' 13 | 14 | const requestData: any = { 15 | prompt: params.prompt, 16 | watermark: false // 默认不添加水印 17 | } 18 | 19 | // 处理上传的图片 20 | if (params.images && params.images.length > 0) { 21 | requestData.images = params.images 22 | } 23 | 24 | // 处理分辨率设置 25 | if (params.size) { 26 | requestData.size = params.size 27 | } 28 | 29 | // 处理即梦图片生成4.0的特定参数 30 | if (params.model === 'seedream-4.0') { 31 | if (params.sequential_image_generation !== undefined) { 32 | requestData.sequential_image_generation = params.sequential_image_generation 33 | } 34 | 35 | if (params.max_images !== undefined) { 36 | requestData.max_images = params.max_images 37 | } 38 | 39 | if (params.watermark !== undefined) { 40 | requestData.watermark = params.watermark 41 | } 42 | } 43 | 44 | return { endpoint, requestData } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/图像/背景移除.md: -------------------------------------------------------------------------------- 1 | # 背景移除 2 | 3 | 背景移除 API 能移除图片中的背景内容。 4 | 5 | ## 请求 6 | 7 | **端点** 8 | ``` 9 | POST https://api.ppinfra.com/v3/remove-background 10 | ``` 11 | 12 | **cURL 示例** 13 | ```bash 14 | curl --request POST \ 15 | --url https://api.ppinfra.com/v3/remove-background \ 16 | --header 'Authorization: ' \ 17 | --header 'Content-Type: ' \ 18 | --data ' 19 | { 20 | "extra": { 21 | "response_image_type": "" 22 | }, 23 | "image_file": "" 24 | } 25 | ' 26 | ``` 27 | 28 | ## 请求头 29 | 30 | | 参数 | 类型 | 是否必需 | 描述 | 31 | | :--- | :--- | :--- | :--- | 32 | | `Content-Type` | string | 是 | 枚举值: `application/json` | 33 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 34 | 35 | ## 请求体 36 | 37 | | 参数 | 类型 | 是否必需 | 描述 | 38 | | :--- | :--- | :--- | :--- | 39 | | `image_file` | string | 是 | 图片二进制的 base64 内容,图片长和宽均不超过 1024 像素,文件最大不超过 30 Mb。 | 40 | | `extra` | object | 否 | 额外参数。 | 41 | | `extra.response_image_type` | string | 否 | 返回的图片格式,默认为 PNG。枚举值: `png`, `webp`, `jpeg` | 42 | 43 | ## 响应参数 44 | 45 | **响应示例** 46 | ```json 47 | { 48 | "image_file": "", 49 | "image_type": "" 50 | } 51 | ``` 52 | 53 | | 参数 | 类型 | 描述 | 54 | | :--- | :--- | :--- | 55 | | `image_file` | string | 图片结果的 Base64 编码内容。 | 56 | | `image_type` | string | 图片格式。枚举值: `png`, `webp`, `jpeg` | -------------------------------------------------------------------------------- /src/adapters/_template/parsers/imageParser.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 图片响应解析器模板 3 | * 4 | * 使用说明: 5 | * 根据API的实际响应格式调整解析逻辑 6 | */ 7 | 8 | import { ResponseParser } from '../types' 9 | import { ImageResult } from '../../base/BaseAdapter' 10 | 11 | export const imageParser: ResponseParser = { 12 | async parse(responseData: any, _adapter: any): Promise { 13 | // 示例1: 直接返回图片URL 14 | if (responseData.image_url) { 15 | return { 16 | url: responseData.image_url, 17 | createdAt: new Date() 18 | } 19 | } 20 | 21 | // 示例2: 返回图片数组 22 | if (responseData.images && Array.isArray(responseData.images)) { 23 | // 如果是多张图片,用分隔符连接 24 | const urls = responseData.images.map((img: any) => img.url || img.image_url) 25 | return { 26 | url: urls.join('|||'), 27 | createdAt: new Date() 28 | } 29 | } 30 | 31 | // 示例3: Base64图片 32 | if (responseData.base64_image) { 33 | return { 34 | url: `data:image/png;base64,${responseData.base64_image}`, 35 | base64Data: responseData.base64_image, 36 | createdAt: new Date() 37 | } 38 | } 39 | 40 | throw new Error('No image found in response') 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/adapters/ppio/models/index.ts: -------------------------------------------------------------------------------- 1 | import { seedream40Route } from './seedream' 2 | import { klingTurbo25Route } from './kling-2.5-turbo' 3 | import { minimaxHailuo23Route } from './minimax-hailuo-2.3' 4 | import { minimaxHailuo02Route } from './minimax-hailuo-02' 5 | import { viduQ1Route } from './vidu' 6 | import { pixverseV45Route } from './pixverse' 7 | import { wan25PreviewRoute } from './wan' 8 | import { seedanceV1Route } from './seedance' 9 | import { minimaxSpeech26Route } from './minimax-speech-2.6' 10 | 11 | /** 12 | * 模型路由接口 13 | */ 14 | export interface ModelRoute { 15 | matches: (modelId: string) => boolean 16 | buildImageRequest?: (params: any) => { endpoint: string; requestData: any } 17 | buildVideoRequest?: (params: any) => { endpoint: string; requestData: any } 18 | buildAudioRequest?: (params: any) => { endpoint: string; requestData: any } 19 | } 20 | 21 | /** 22 | * 所有派欧云模型路由 23 | */ 24 | export const ppioModelRoutes: ModelRoute[] = [ 25 | seedream40Route, 26 | klingTurbo25Route, 27 | minimaxHailuo23Route, 28 | minimaxHailuo02Route, 29 | viduQ1Route, 30 | pixverseV45Route, 31 | wan25PreviewRoute, 32 | seedanceV1Route, 33 | minimaxSpeech26Route 34 | ] 35 | 36 | /** 37 | * 按模型ID查找路由 38 | */ 39 | export const findRoute = (modelId: string): ModelRoute | undefined => { 40 | return ppioModelRoutes.find(route => route.matches(modelId)) 41 | } 42 | -------------------------------------------------------------------------------- /src/components/ui/ProgressBar.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | interface ProgressBarProps { 4 | progress: number 5 | className?: string 6 | color?: string 7 | height?: string 8 | showPercentage?: boolean 9 | duration?: number // 动画持续时间(毫秒) 10 | } 11 | 12 | export const ProgressBar: React.FC = ({ 13 | progress, 14 | className = '', 15 | color = '#007eff', 16 | height = 'h-2', 17 | showPercentage = true, 18 | duration = 2800 // 默认 2800ms,提供丝滑的动画效果 19 | }) => { 20 | const normalizedProgress = Math.min(100, Math.max(0, progress)) 21 | 22 | return ( 23 |
24 |
25 |
33 |
34 | {showPercentage && ( 35 |
36 | {Math.floor(normalizedProgress)}% 37 |
38 | )} 39 |
40 | ) 41 | } 42 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/图像/图像背景移除.md: -------------------------------------------------------------------------------- 1 | # 图像背景移除 2 | 3 | 基于 AI 的图像背景移除服务,支持智能识别并移除图像背景,提供高质量的图像处理能力:开箱即用的 REST 推理 API,最佳性能,无冷启动,价格实惠。 4 | 5 | 这是一个**异步**API,只会返回异步任务的 `task_id`。您应该使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来检索视频生成结果。 6 | 7 | ## 接口信息 8 | 9 | * **请求方法**: POST 10 | * **请求地址**: `https://api.ppinfra.com/v3/async/image-remove-background` 11 | 12 | ## 请求头 13 | 14 | | 参数 | 类型 | 是否必需 | 说明 | 15 | | :--- | :--- | :--- | :--- | 16 | | `Content-Type` | string | 是 | 必须为 `application/json`。 | 17 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 18 | 19 | ## 请求体 20 | 21 | | 参数 | 类型 | 是否必需 | 说明 | 22 | | :--- | :--- | :--- | :--- | 23 | | `image` | string | 是 | 要移除背景的图像的 URL。 | 24 | 25 | ## 响应 26 | 27 | | 参数 | 类型 | 是否必需 | 说明 | 28 | | :--- | :--- | :--- | :--- | 29 | | `task_id` | string | 是 | 异步任务的 ID。您应该使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果。 | 30 | 31 | ## 调用示例 32 | 33 | **请求示例** 34 | 35 | ```bash 36 | curl --request POST \ 37 | --url https://api.ppinfra.com/v3/async/image-remove-background \ 38 | --header 'Authorization: Bearer ' \ 39 | --header 'Content-Type: application/json' \ 40 | --data ' 41 | { 42 | "image": "https://example.com/your-image.jpg" 43 | } 44 | ' 45 | ``` 46 | 47 | **响应示例** 48 | 49 | ```json 50 | { 51 | "task_id": "your_task_id_here" 52 | } 53 | ``` -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/其他/背景替换.md: -------------------------------------------------------------------------------- 1 | # 背景替换 2 | 3 | 背景替换 API 通过提示词来控制将图片中的背景替换成指定内容。 4 | 5 | ## 请求示例 6 | 7 | **cURL** 8 | 9 | ```bash 10 | curl --request POST \ 11 | --url https://api.ppinfra.com/v3/replace-background \ 12 | --header 'Authorization: ' \ 13 | --header 'Content-Type: application/json' \ 14 | --data ' 15 | { 16 | "extra": { 17 | "response_image_type": "" 18 | }, 19 | "image_file": "", 20 | "prompt": "" 21 | } 22 | ' 23 | ``` 24 | 25 | **API 端点** 26 | ``` 27 | POST https://api.ppinfra.com/v3/replace-background 28 | ``` 29 | 30 | ## 请求头 31 | 32 | | 参数 | 类型 | 必填 | 说明 | 33 | | :--- | :--- | :--- | :--- | 34 | | `Content-Type` | string | 是 | 必须为 `application/json`。 | 35 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 36 | 37 | ## 请求体 38 | 39 | | 参数 | 类型 | 必填 | 说明 | 40 | | :--- | :--- | :--- | :--- | 41 | | `image_file` | string | 是 | 原始图片的 base64 编码内容。支持的最大分辨率为 2048 * 2048,文件最大不超过 30 Mb。 | 42 | | `prompt` | string | 是 | 用于描述图像背景的提示词。文本长度范围为 [1, 1024]。 | 43 | | `extra` | object | 否 | 额外参数。 | 44 | | `extra.response_image_type` | string | 否 | 返回的图片格式,默认为 `png`。可选值:`png`, `webp`, `jpeg`。 | 45 | 46 | ## 响应参数 47 | 48 | | 参数 | 类型 | 说明 | 49 | | :--- | :--- | :--- | 50 | | `image_file` | string | 处理后的图片结果的 Base64 编码内容。 | 51 | | `image_type` | string | 返回的图片格式。枚举值:`png`, `webp`, `jpeg`。 | 52 | 53 | **响应示例** 54 | ```json 55 | { 56 | "image_file": "", 57 | "image_type": "" 58 | } 59 | ``` -------------------------------------------------------------------------------- /src/models/kling-2.5-turbo.ts: -------------------------------------------------------------------------------- 1 | import { ParamDef } from '../types/schema' 2 | 3 | /** 4 | * 可灵 2.5 Turbo 模型参数定义 5 | */ 6 | export const klingTurbo25Params: ParamDef[] = [ 7 | { 8 | id: 'ppioKling25VideoDuration', 9 | type: 'dropdown', 10 | label: '时长', 11 | defaultValue: 5, // Kling 默认 5 秒 12 | options: [ 13 | { value: 5, label: '5s' }, 14 | { value: 10, label: '10s' } 15 | ] 16 | }, 17 | { 18 | id: 'ppioKling25VideoAspectRatio', 19 | type: 'dropdown', 20 | defaultValue: '16:9', 21 | // 分辨率配置:启用可视化 22 | resolutionConfig: { 23 | type: 'aspect_ratio', 24 | smartMatch: false, 25 | visualize: true, 26 | extractRatio: (value) => { 27 | const [w, h] = value.split(':').map(Number) 28 | return w / h 29 | } 30 | }, 31 | options: [ 32 | { value: '16:9', label: '16:9' }, 33 | { value: '9:16', label: '9:16' }, 34 | { value: '1:1', label: '1:1' } 35 | ], 36 | // 图生视频时隐藏比例参数(API 不支持) 37 | hidden: (values) => values.uploadedImages && values.uploadedImages.length > 0 38 | }, 39 | { 40 | id: 'ppioKling25CfgScale', 41 | type: 'number', 42 | label: 'CFG Scale', 43 | min: 0, 44 | max: 1, 45 | step: 0.01, 46 | precision: 2, 47 | widthClassName: 'w-24' 48 | } 49 | ] 50 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/图像/对象擦除.md: -------------------------------------------------------------------------------- 1 | # 对象擦除 2 | 3 | 对象擦除 API 能将图片中的指定区域擦除干净。 4 | 5 | **请求示例** 6 | 7 | ```bash 8 | curl --request POST \ 9 | --url https://api.ppinfra.com/v3/cleanup \ 10 | --header 'Authorization: ' \ 11 | --header 'Content-Type: ' \ 12 | --data ' 13 | { 14 | "extra": { 15 | "response_image_type": "" 16 | }, 17 | "image_file": "", 18 | "mask_file": "" 19 | } 20 | ' 21 | ``` 22 | 23 | **响应示例** 24 | 25 | ```json 26 | { 27 | "image_file": "", 28 | "image_type": "" 29 | } 30 | ``` 31 | 32 | ## 请求头 33 | 34 | ### Content-Type 35 | * **类型**: `string` 36 | * **必需**: 是 37 | * **枚举值**: `application/json` 38 | 39 | ### Authorization 40 | * **类型**: `string` 41 | * **必需**: 是 42 | * **描述**: Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 43 | 44 | ## 请求体 45 | 46 | ### image_file 47 | * **类型**: `string` 48 | * **必需**: 是 49 | * **描述**: 原始图片的 base64 编码内容,支持的最大分辨率小于 16 megapixels,文件最大不超过 30 Mb。 50 | 51 | ### mask_file 52 | * **类型**: `string` 53 | * **必需**: 是 54 | * **描述**: 遮罩图片的 base64 编码内容,支持的最大分辨率小于 16 megapixels,文件最大不超过 30 Mb。 55 | 56 | ### extra 57 | * **类型**: `object` 58 | * **描述**: 额外参数。 59 | 60 | #### extra.response_image_type 61 | * **类型**: `string` 62 | * **描述**: 返回的图片格式,默认为 PNG。 63 | * **枚举值**: `png`, `webp`, `jpeg` 64 | 65 | ## 响应参数 66 | 67 | ### image_file 68 | * **类型**: `string` 69 | * **描述**: 图片结果的 Base64 编码内容。 70 | 71 | ### image_type 72 | * **类型**: `string` 73 | * **描述**: 图片格式。 74 | * **枚举值**: `png`, `webp`, `jpeg` -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/图像/人脸融合.md: -------------------------------------------------------------------------------- 1 | # 人脸融合 2 | 3 | 人脸融合 API 用于将图片中的人脸特征融合到模板图片中的人物上。 4 | 5 | ## 接口信息 6 | 7 | * **请求方法**: POST 8 | * **请求地址**: `https://api.ppinfra.com/v3/merge-face` 9 | 10 | ## 请求示例 11 | 12 | ```bash 13 | curl --request POST \ 14 | --url https://api.ppinfra.com/v3/merge-face \ 15 | --header 'Authorization: ' \ 16 | --header 'Content-Type: application/json' \ 17 | --data ' 18 | { 19 | "extra": { 20 | "response_image_type": "" 21 | }, 22 | "face_image_file": "", 23 | "image_file": "" 24 | } 25 | ' 26 | ``` 27 | 28 | ## 响应示例 29 | 30 | ```json 31 | { 32 | "image_file": "", 33 | "image_type": "" 34 | } 35 | ``` 36 | 37 | ## 请求头 38 | 39 | | 参数 | 类型 | 是否必填 | 说明 | 40 | | :--- | :--- | :--- | :--- | 41 | | `Content-Type` | string | 是 | 固定为 `application/json`。 | 42 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 43 | 44 | ## 请求体 45 | 46 | | 参数 | 类型 | 是否必填 | 说明 | 47 | | :--- | :--- | :--- | :--- | 48 | | `face_image_file` | string | 是 | 包含人脸特征的图片的 base64 编码内容。支持的最大分辨率为 2048 * 2048,文件最大不超过 30 MB。**该图片中必须包含人脸信息。** | 49 | | `image_file` | string | 是 | 模板图片的 base64 编码内容。支持的最大分辨率为 2048 * 2048,文件最大不超过 30 MB。**该图片中必须包含人脸信息。** | 50 | | `extra` | object | 否 | 额外参数。 | 51 | | `extra.response_image_type` | string | 否 | 返回的图片格式,默认为 `png`。
可选值:`png`, `webp`, `jpeg` | 52 | 53 | ## 响应参数 54 | 55 | | 参数 | 类型 | 说明 | 56 | | :--- | :--- | :--- | 57 | | `image_file` | string | 融合后图片结果的 Base64 编码内容。 | 58 | | `image_type` | string | 返回图片的格式。
可选值:`png`, `webp`, `jpeg` | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/图像/图像高清化.md: -------------------------------------------------------------------------------- 1 | # 图像高清化 2 | 3 | 基于 AI 的图像高清化服务,支持将低分辨率图像提升到更高分辨率,提供高质量的图像处理能力:开箱即用的 REST 推理 API,最佳性能,无冷启动,价格实惠。 4 | 5 | 这是一个**异步**API,只会返回异步任务的 `task_id`。您应该使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来检索图像高清化结果。 6 | 7 | ## 请求 8 | 9 | **端点** 10 | ``` 11 | POST https://api.ppinfra.com/v3/async/image-upscaler 12 | ``` 13 | 14 | **cURL 示例** 15 | ```bash 16 | curl --request POST \ 17 | --url https://api.ppinfra.com/v3/async/image-upscaler \ 18 | --header 'Authorization: ' \ 19 | --header 'Content-Type: ' \ 20 | --data ' 21 | { 22 | "image": "", 23 | "resolution": "", 24 | "output_format": "" 25 | } 26 | ' 27 | ``` 28 | 29 | ## 请求头 30 | 31 | | 参数 | 类型 | 是否必需 | 描述 | 32 | | :--- | :--- | :--- | :--- | 33 | | `Content-Type` | string | 是 | 必须为 `application/json`。 | 34 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 35 | 36 | ## 请求体 37 | 38 | | 参数 | 类型 | 默认值 | 是否必需 | 描述 | 39 | | :--- | :--- | :--- | :--- | :--- | 40 | | `image` | string | - | 是 | 要进行高清化处理的原始图像的 URL。 | 41 | | `resolution` | string | `"4k"` | 否 | 高清化后的目标分辨率。可选值:`2k`, `4k`, `8k`。 | 42 | | `output_format` | string | `"jpeg"` | 否 | 输出图像的格式。可选值:`jpeg`, `png`, `webp`。 | 43 | 44 | ## 响应 45 | 46 | **响应示例** 47 | ```json 48 | { 49 | "task_id": "" 50 | } 51 | ``` 52 | 53 | **响应参数** 54 | 55 | | 参数 | 类型 | 是否必需 | 描述 | 56 | | :--- | :--- | :--- | :--- | 57 | | `task_id` | string | 是 | 异步任务的 ID。您应该使用该 ID 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果。 | -------------------------------------------------------------------------------- /src/adapters/kie/models/nano-banana-pro.ts: -------------------------------------------------------------------------------- 1 | import { GenerateImageParams, GenerateVideoParams } from '@/adapters/base/BaseAdapter' 2 | 3 | export interface KIEModelRoute { 4 | matches: (modelId: string) => boolean 5 | buildImageRequest?: (params: GenerateImageParams) => { 6 | requestData: any 7 | } 8 | buildVideoRequest?: (params: GenerateVideoParams) => { 9 | requestData: any 10 | } 11 | } 12 | 13 | export const kieNanoBananaProRoute: KIEModelRoute = { 14 | matches: (modelId: string) => 15 | modelId === 'kie-nano-banana-pro' || 16 | modelId === 'nano-banana-pro', 17 | 18 | buildImageRequest: (params: GenerateImageParams) => { 19 | const images = params.images || [] 20 | const prompt = params.prompt || '' 21 | 22 | // 构建请求数据 23 | const requestData: any = { 24 | model: 'nano-banana-pro', 25 | input: { 26 | prompt: prompt 27 | } 28 | } 29 | 30 | // 添加可选参数 31 | if (params.aspect_ratio !== undefined && 32 | params.aspect_ratio !== 'smart' && 33 | params.aspect_ratio !== 'auto') { 34 | requestData.input.aspect_ratio = params.aspect_ratio 35 | } 36 | 37 | if (params.resolution !== undefined) { 38 | requestData.input.resolution = params.resolution 39 | } 40 | 41 | // 如果有图片,添加到 image_input(KIE 已上传的 URL) 42 | if (images.length > 0) { 43 | requestData.input.image_input = images 44 | } 45 | 46 | // 添加回调 URL(可选,如果需要) 47 | // requestData.callBackUrl = 'https://your-domain.com/api/callback' 48 | 49 | return { requestData } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/models/kie-nano-banana-pro.ts: -------------------------------------------------------------------------------- 1 | import { ParamDef } from '../types/schema' 2 | 3 | export const kieNanoBananaProParams: ParamDef[] = [ 4 | // 宽高比参数(带智能匹配和分辨率选择) 5 | { 6 | id: 'kieNanoBananaAspectRatio', 7 | type: 'dropdown', 8 | defaultValue: '1:1', 9 | resolutionConfig: { 10 | type: 'aspect_ratio', 11 | smartMatch: true, 12 | visualize: true, 13 | extractRatio: (value) => { 14 | if (value === 'smart') return null 15 | const [w, h] = value.split(':').map(Number) 16 | return w / h 17 | }, 18 | qualityOptions: [ 19 | { value: '1K', label: '1K' }, 20 | { value: '2K', label: '2K' }, 21 | { value: '4K', label: '4K' } 22 | ], 23 | qualityKey: 'kieNanoBananaResolution' 24 | }, 25 | // 当上传图片时自动切换到智能选项 26 | autoSwitch: { 27 | condition: (values) => values.uploadedImages && values.uploadedImages.length > 0, 28 | value: 'smart', 29 | watchKeys: ['uploadedImages'] // 只监听图片数量变化,避免用户手动选择比例时被强制切换 30 | }, 31 | options: [ 32 | { value: 'smart', label: '智能' }, 33 | { value: '1:1', label: '1:1' }, 34 | { value: '2:3', label: '2:3' }, 35 | { value: '3:2', label: '3:2' }, 36 | { value: '3:4', label: '3:4' }, 37 | { value: '4:3', label: '4:3' }, 38 | { value: '4:5', label: '4:5' }, 39 | { value: '5:4', label: '5:4' }, 40 | { value: '9:16', label: '9:16' }, 41 | { value: '16:9', label: '16:9' }, 42 | { value: '21:9', label: '21:9' } 43 | ], 44 | className: 'min-w-[100px]' 45 | } 46 | ] 47 | -------------------------------------------------------------------------------- /src/styles/scrollbar.css: -------------------------------------------------------------------------------- 1 | /* Disable body scroll to prevent window-level scrollbar overlapping titlebar */ 2 | /* Use a dedicated scroll container below the titlebar instead of window-level scroll */ 3 | .app-scroll-container { 4 | position: fixed; 5 | top: 40px; 6 | left: 0; 7 | right: 0; 8 | bottom: 0; 9 | overflow-y: auto; 10 | scroll-behavior: auto !important; 11 | overflow-anchor: none; 12 | } 13 | 14 | /* Global scrollbar styling for scroll containers */ 15 | .app-scroll-container::-webkit-scrollbar, 16 | .image-strip::-webkit-scrollbar { 17 | width: 7px; 18 | height: 7px; 19 | } 20 | .app-scroll-container::-webkit-scrollbar-button, 21 | .image-strip::-webkit-scrollbar-button { 22 | width: 0; 23 | height: 0; 24 | display: none; 25 | } 26 | .app-scroll-container::-webkit-scrollbar-track, 27 | .image-strip::-webkit-scrollbar-track { 28 | background: transparent; 29 | } 30 | .app-scroll-container::-webkit-scrollbar-thumb, 31 | .image-strip::-webkit-scrollbar-thumb { 32 | background-color: rgba(156, 163, 175, 0.4); /* light zinc with 0.4 opacity */ 33 | border-radius: 4px; 34 | transition: background-color 0.2s ease; 35 | } 36 | .app-scroll-container::-webkit-scrollbar-thumb:hover, 37 | .image-strip::-webkit-scrollbar-thumb:hover { 38 | background-color: rgba(156, 163, 175, 0.7); 39 | } 40 | 41 | /* Firefox */ 42 | .app-scroll-container, 43 | .image-strip { 44 | scrollbar-width: thin; 45 | scrollbar-color: rgba(156, 163, 175, 0.4) transparent; 46 | scrollbar-gutter: stable; 47 | overscroll-behavior: contain; 48 | touch-action: pan-x; 49 | } 50 | -------------------------------------------------------------------------------- /src/models/fal-ai-minimax-hailuo-2.3.ts: -------------------------------------------------------------------------------- 1 | import { ParamDef } from '../types/schema' 2 | 3 | /** 4 | * Fal.ai MiniMax Hailuo 2.3 模型参数定义 5 | * UI 显示分辨率(768P/1080P),实际映射到 standard/pro 6 | */ 7 | export const falAiMinimaxHailuo23Params: ParamDef[] = [ 8 | { 9 | id: 'falHailuo23Duration', 10 | type: 'dropdown', 11 | label: '时长', 12 | defaultValue: '6', 13 | options: [ 14 | { value: '6', label: '6s' }, 15 | { value: '10', label: '10s' } 16 | ] 17 | }, 18 | { 19 | id: 'falHailuo23Resolution', 20 | type: 'dropdown', 21 | label: '分辨率', 22 | defaultValue: '768P', 23 | // 分辨率配置:使用面板显示 24 | resolutionConfig: { 25 | type: 'resolution', 26 | smartMatch: false, 27 | visualize: false 28 | }, 29 | // 自动切换规则:当时长为10秒且分辨率为1080P时,自动切换到768P 30 | autoSwitch: { 31 | condition: (values) => { 32 | return values.falHailuo23Duration === '10' && values.falHailuo23Resolution === '1080P' 33 | }, 34 | value: () => '768P' 35 | }, 36 | options: (values) => [ 37 | { value: '768P', label: '768P' }, 38 | { value: '1080P', label: '1080P', disabled: values.falHailuo23Duration !== '6' } 39 | ] 40 | }, 41 | { 42 | id: 'falHailuo23FastMode', 43 | type: 'toggle', 44 | label: '快速模式', 45 | defaultValue: true, 46 | // 仅在上传图片时显示(图生视频才支持快速模式) 47 | hidden: (values) => !values.uploadedImages || values.uploadedImages.length === 0 48 | }, 49 | { 50 | id: 'falHailuo23PromptOptimizer', 51 | type: 'toggle', 52 | label: '提示词优化', 53 | defaultValue: true 54 | } 55 | ] 56 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/大语言/检索模型.md: -------------------------------------------------------------------------------- 1 | # 检索模型 2 | 3 | 检索模型实例,并提供相关模型的基本信息。该 Endpoint 与 OpenAI API 兼容。 4 | 5 | ## 接口定义 6 | 7 | **请求方法**: `GET` 8 | **请求路径**: `https://api.ppinfra.com/openai/v1/models/{model}` 9 | 10 | ## 请求示例 11 | 12 | ```bash 13 | curl --request GET \ 14 | --url https://api.ppinfra.com/openai/v1/models/{model} \ 15 | --header 'Authorization: ' \ 16 | --header 'Content-Type: ' 17 | ``` 18 | 19 | ## 响应示例 20 | 21 | ```json 22 | { 23 | "id": "", 24 | "created": 123, 25 | "object": "", 26 | "input_token_price_per_m": 123, 27 | "output_token_price_per_m": 123, 28 | "title": "", 29 | "description": "", 30 | "context_size": 123 31 | } 32 | ``` 33 | 34 | ## 请求头 35 | 36 | | 参数名 | 类型 | 是否必需 | 说明 | 37 | | :--- | :--- | :--- | :--- | 38 | | `Content-Type` | string | 是 | 固定为 `application/json`。 | 39 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 40 | 41 | ## 路径参数 42 | 43 | | 参数名 | 类型 | 是否必需 | 说明 | 44 | | :--- | :--- | :--- | :--- | 45 | | `model` | string | 是 | 用于此请求的模型 ID。 | 46 | 47 | ## 响应参数 48 | 49 | | 参数名 | 类型 | 是否必需 | 说明 | 50 | | :--- | :--- | :--- | :--- | 51 | | `id` | string | 是 | 模型 ID,用于标识模型。可以在 API Endpoints 中引用。 | 52 | | `created` | integer | 是 | 模型创建时的 Unix 时间戳(以秒为单位)。 | 53 | | `object` | string | 是 | 对象类型。取值固定为 `model`。 | 54 | | `input_token_price_per_m` | integer | 是 | 输入价格(每百万 Token)。 | 55 | | `output_token_price_per_m` | integer | 是 | 输出价格(每百万 Token)。 | 56 | | `title` | string | 是 | 模型名称。 | 57 | | `description` | string | 是 | 模型描述。 | 58 | | `context_size` | integer | 是 | 模型允许的最大上下文长度。 | -------------------------------------------------------------------------------- /src/models/kie-hailuo-2-3.ts: -------------------------------------------------------------------------------- 1 | import { ParamDef } from '../types/schema' 2 | 3 | /** 4 | * KIE Hailuo 2.3 模型参数定义 5 | * 6 | * 特点: 7 | * - 图生视频模型(必须上传图片) 8 | * - 支持标准和专业两种模式 9 | * - 1080P 分辨率不支持 10 秒时长 10 | */ 11 | export const kieHailuo23Params: ParamDef[] = [ 12 | { 13 | id: 'kieHailuo23Mode', 14 | type: 'dropdown', 15 | label: '模式', 16 | defaultValue: 'standard', 17 | options: [ 18 | { value: 'standard', label: '标准' }, 19 | { value: 'pro', label: '专业' } 20 | ], 21 | className: 'min-w-[50px]' 22 | }, 23 | { 24 | id: 'kieHailuo23Duration', 25 | type: 'dropdown', 26 | label: '时长', 27 | defaultValue: 6, 28 | options: [ 29 | { value: 6, label: '6s' }, 30 | { value: 10, label: '10s' } 31 | ], 32 | className: 'min-w-[50px]' 33 | }, 34 | { 35 | id: 'kieHailuo23Resolution', 36 | type: 'dropdown', 37 | label: '分辨率', 38 | defaultValue: '768P', 39 | // 分辨率配置:使用面板显示 40 | resolutionConfig: { 41 | type: 'resolution', 42 | smartMatch: false, 43 | visualize: false 44 | }, 45 | // 自动切换规则:当时长为10秒且分辨率为1080P时,自动切换到768P 46 | autoSwitch: { 47 | condition: (values) => { 48 | return values.kieHailuo23Duration === 10 && values.kieHailuo23Resolution === '1080P' 49 | }, 50 | value: () => '768P' 51 | }, 52 | // 动态选项:当时长为10秒时,禁用1080P选项 53 | options: (values) => [ 54 | { value: '768P', label: '768P' }, 55 | { value: '1080P', label: '1080P', disabled: values.kieHailuo23Duration === 10 } 56 | ], 57 | className: 'min-w-[100px]' 58 | } 59 | ] 60 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/图像/Qwen-Image_图像编辑.md: -------------------------------------------------------------------------------- 1 | # Qwen-Image 图像编辑 2 | 3 | Qwen-Image 图像编辑是一个用于下一代图像编辑生成的20B MMDiT模型。基于20B Qwen-Image,它在保留风格的同时,提供精确的双语文本编辑(中文和英文),并支持语义和外观级别的编辑。 4 | 5 | 这是一个**异步**API,调用后只会返回异步任务的 `task_id`。您需要使用该 `task_id` 调用 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来检索生成结果。 6 | 7 | ## 请求示例 8 | 9 | **请求方法:** `POST` 10 | 11 | **请求地址:** `https://api.ppinfra.com/v3/async/qwen-image-edit` 12 | 13 | **cURL 示例:** 14 | ```bash 15 | curl --request POST \ 16 | --url https://api.ppinfra.com/v3/async/qwen-image-edit \ 17 | --header 'Authorization: ' \ 18 | --header 'Content-Type: application/json' \ 19 | --data ' 20 | { 21 | "prompt": "", 22 | "image": "", 23 | "seed": 123, 24 | "output_format": "" 25 | } 26 | ' 27 | ``` 28 | 29 | **响应示例:** 30 | ```json 31 | { 32 | "task_id": "" 33 | } 34 | ``` 35 | 36 | ## 请求头 37 | 38 | | 参数名 | 类型 | 是否必需 | 描述 | 39 | | :--- | :--- | :--- | :--- | 40 | | `Content-Type` | string | 是 | 必须为 `application/json`。 | 41 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 42 | 43 | ## 请求体 44 | 45 | | 参数名 | 类型 | 是否必需 | 描述 | 46 | | :--- | :--- | :--- | :--- | 47 | | `prompt` | string | 是 | 用于指导图像生成的文本提示。 | 48 | | `image` | string | 是 | 用于编辑的原始图像。 | 49 | | `seed` | integer | 否 | 用于生成的随机种子。范围:`-1` ~ `2147483647`。`-1` 表示使用随机种子。默认值为 `-1`。 | 50 | | `output_format` | string | 否 | 输出图像的格式。枚举值:`jpeg`, `png`, `webp`。默认值为 `jpeg`。 | 51 | 52 | ## 响应参数 53 | 54 | | 参数名 | 类型 | 是否必需 | 描述 | 55 | | :--- | :--- | :--- | :--- | 56 | | `task_id` | string | 是 | 异步任务的唯一标识符。用于查询 [任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果。 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/图像/图像擦除.md: -------------------------------------------------------------------------------- 1 | # 图像擦除 2 | 3 | 基于 AI 的图像擦除服务,支持通过遮罩图像和文本提示智能移除图像中的对象,提供高质量的图像处理能力:开箱即用的 REST 推理 API,最佳性能,无冷启动,价格实惠。 4 | 5 | 这是一个**异步**API,只会返回异步任务的 `task_id`。您应该使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来检索图像生成结果。 6 | 7 | ## 请求 8 | 9 | **端点** 10 | ``` 11 | POST https://api.ppinfra.com/v3/async/image-eraser 12 | ``` 13 | 14 | **cURL 示例** 15 | ```bash 16 | curl --request POST \ 17 | --url https://api.ppinfra.com/v3/async/image-eraser \ 18 | --header 'Authorization: ' \ 19 | --header 'Content-Type: application/json' \ 20 | --data ' 21 | { 22 | "mask": "", 23 | "image": "", 24 | "prompt": "", 25 | "output_format": "" 26 | } 27 | ' 28 | ``` 29 | 30 | **响应示例** 31 | ```json 32 | { 33 | "task_id": "" 34 | } 35 | ``` 36 | 37 | ## 请求头 38 | 39 | | 参数 | 类型 | 是否必需 | 描述 | 40 | | :--- | :--- | :--- | :--- | 41 | | `Content-Type` | string | 是 | 必须为 `application/json`。 | 42 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 43 | 44 | ## 请求体 45 | 46 | | 参数 | 类型 | 是否必需 | 默认值 | 描述 | 47 | | :--- | :--- | :--- | :--- | :--- | 48 | | `mask` | string | 否 | - | 遮罩图像,用于指示要擦除的区域。要擦除的区域应为白色,要保留的区域应为黑色。 | 49 | | `image` | string | 是 | - | 要生成图像的原始图像。 | 50 | | `prompt` | string | 否 | - | 用于指定要从图像中移除的对象或区域的文本提示。例如:`dog` 或 `hat`。 | 51 | | `output_format` | string | 否 | `"jpeg"` | 输出图像的格式。可选值:`jpeg`, `png`, `webp`。 | 52 | 53 | ## 响应 54 | 55 | | 参数 | 类型 | 是否必需 | 描述 | 56 | | :--- | :--- | :--- | :--- | 57 | | `task_id` | string | 是 | 异步任务的 `task_id`。您应该使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果。 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/图像/Hunyuan_Image_3.md: -------------------------------------------------------------------------------- 1 | # Hunyuan Image 3 2 | 3 | Hunyuan Image 3 是一款先进的文生图模型。只需提供文字描述,即可生成高质量、富有情感和故事性的图片,助力您的创意表达与艺术创作。 4 | 5 | 本接口支持个人认证及企业认证用户调用。请参见 [实名认证](/docs/support/identity-verification),完成个人用户认证或企业用户认证,以确保可以正常使用本功能。 6 | 7 | 这是一个**异步**API,只会返回异步任务的 task\_id。您应该使用该 task\_id 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来检索生成结果。 8 | 9 | ## 请求示例 10 | 11 | ```bash 12 | curl --request POST \ 13 | --url https://api.ppinfra.com/v3/async/hunyuan-image-3 \ 14 | --header 'Authorization: ' \ 15 | --header 'Content-Type: application/json' \ 16 | --data ' 17 | { 18 | "prompt": "", 19 | "size": "", 20 | "seed": 123 21 | } 22 | ' 23 | ``` 24 | 25 | ## 响应示例 26 | 27 | ```json 28 | { 29 | "task_id": "" 30 | } 31 | ``` 32 | 33 | ## 请求头 34 | 35 | ### Content-Type 36 | * **类型**: string 37 | * **必需**: 是 38 | * **枚举值**: `application/json` 39 | 40 | ### Authorization 41 | * **类型**: string 42 | * **必需**: 是 43 | * **说明**: Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 44 | 45 | ## 请求体 46 | 47 | ### prompt 48 | * **类型**: string 49 | * **必需**: 是 50 | * **说明**: 正向提示词,用于指导图片生成内容。 51 | 52 | ### size 53 | * **类型**: string 54 | * **必需**: 否 55 | * **说明**: 生成图片的尺寸,像素为宽\*高。每个维度范围 [256 ~ 1536]。 56 | * **默认值**: `1024*1024` 57 | 58 | ### seed 59 | * **类型**: integer 60 | * **必需**: 否 61 | * **说明**: 随机种子。取值为 -1 时表示随机种子。 62 | * **取值范围**: [-1 ~ 2147483647] 63 | * **默认值**: `-1` 64 | 65 | ## 返回结果 66 | 67 | ### task_id 68 | * **类型**: string 69 | * **必需**: 是 70 | * **说明**: 异步任务的 task\_id。您应该使用该 task\_id 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果。 -------------------------------------------------------------------------------- /src/models/pixverse-v4.5.ts: -------------------------------------------------------------------------------- 1 | import { ParamDef } from '../types/schema' 2 | 3 | /** 4 | * PixVerse V4.5 模型参数定义 5 | */ 6 | export const pixverseV45Params: ParamDef[] = [ 7 | { 8 | id: 'ppioPixverse45VideoAspectRatio', 9 | type: 'dropdown', 10 | label: '分辨率', 11 | defaultValue: '16:9', 12 | // 分辨率配置:不启用智能匹配,将分辨率作为质量选项 13 | resolutionConfig: { 14 | type: 'aspect_ratio', 15 | smartMatch: false, 16 | visualize: true, 17 | extractRatio: (value) => { 18 | const [w, h] = value.split(':').map(Number) 19 | return w / h 20 | }, 21 | // 指定分辨率参数的key 22 | qualityKey: 'ppioPixverse45VideoResolution', 23 | // 分辨率选项(作为质量选项显示) 24 | qualityOptions: (values: any) => [ 25 | { value: '360p', label: '360P' }, 26 | { value: '540p', label: '540P' }, 27 | { value: '720p', label: '720P' }, 28 | { value: '1080p', label: '1080P', disabled: values.ppioPixverse45FastMode } 29 | ] 30 | }, 31 | options: (values) => { 32 | // 图生视频时不显示比例选项(比例由图片决定) 33 | if (values.uploadedImages.length > 0) { 34 | return [] 35 | } 36 | return [ 37 | { value: '16:9', label: '16:9' }, 38 | { value: '9:16', label: '9:16' }, 39 | { value: '1:1', label: '1:1' } 40 | ] 41 | } 42 | }, 43 | { 44 | id: 'ppioPixverse45FastMode', 45 | type: 'toggle', 46 | label: '快速模式' 47 | } 48 | ] 49 | -------------------------------------------------------------------------------- /src/models/minimax-hailuo-2.3.ts: -------------------------------------------------------------------------------- 1 | import { ParamDef } from '../types/schema' 2 | 3 | /** 4 | * Minimax 海螺 2.3 模型参数定义 5 | */ 6 | export const minimaxHailuo23Params: ParamDef[] = [ 7 | { 8 | id: 'ppioHailuo23VideoDuration', 9 | type: 'dropdown', 10 | label: '时长', 11 | defaultValue: 6, // Hailuo 默认 6 秒 12 | options: [ 13 | { value: 6, label: '6s' }, 14 | { value: 10, label: '10s' } 15 | ] 16 | }, 17 | { 18 | id: 'ppioHailuo23VideoResolution', 19 | type: 'dropdown', 20 | defaultValue: '768P', // Hailuo 默认 768P 21 | // 分辨率配置:使用面板显示 22 | resolutionConfig: { 23 | type: 'resolution', 24 | smartMatch: false, 25 | visualize: false 26 | }, 27 | // 自动切换规则:当时长为10秒且分辨率为1080P时,自动切换到768P 28 | autoSwitch: { 29 | condition: (values) => { 30 | return values.ppioHailuo23VideoDuration === 10 && values.ppioHailuo23VideoResolution === '1080P' 31 | }, 32 | value: () => '768P' 33 | }, 34 | options: (values) => [ 35 | { value: '768P', label: '768P' }, 36 | { value: '1080P', label: '1080P', disabled: values.ppioHailuo23VideoDuration !== 6 } 37 | ] 38 | }, 39 | { 40 | id: 'ppioHailuo23FastMode', 41 | type: 'toggle', 42 | label: '快速模式', 43 | hidden: (values) => { 44 | // Show only if model is 'minimax-hailuo-2.3' AND images are uploaded 45 | return !(values.selectedModel === 'minimax-hailuo-2.3' && values.uploadedImages.length > 0) 46 | } 47 | } 48 | ] 49 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/视频/Minimax_Video-01.md: -------------------------------------------------------------------------------- 1 | # Minimax Video-01 2 | 3 | Minimax Video-01(又名海螺)是一款 AI 视频生成模型,可生成 6 秒、720p 分辨率、25 帧/秒的视频。支持文本生成视频(文生视频)和图片生成视频(图生视频)两种模式。 4 | 5 | 这是一个**异步**API,只会返回异步任务的 task\_id。您应该使用该 task\_id 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来检索视频生成结果。 6 | 7 | ## 请求示例 8 | 9 | **请求方法**: `POST` 10 | 11 | **请求地址**: `https://api.ppinfra.com/v3/async/minimax-video-01` 12 | 13 | ```bash 14 | curl --request POST \ 15 | --url https://api.ppinfra.com/v3/async/minimax-video-01 \ 16 | --header 'Authorization: ' \ 17 | --header 'Content-Type: application/json' \ 18 | --data ' 19 | { 20 | "prompt": "", 21 | "image_url": "", 22 | "enable_prompt_expansion": true 23 | } 24 | ' 25 | ``` 26 | 27 | **响应示例**: 28 | ```json 29 | { 30 | "task_id": "" 31 | } 32 | ``` 33 | 34 | ## 请求头 35 | 36 | ### Content-Type 37 | * **类型**: `string` 38 | * **是否必需**: 是 39 | * **枚举值**: `application/json` 40 | 41 | ### Authorization 42 | * **类型**: `string` 43 | * **是否必需**: 是 44 | * **说明**: Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 45 | 46 | ## 请求体 47 | 48 | ### prompt 49 | * **类型**: `string` 50 | * **是否必需**: 是 51 | * **说明**: 指导生成所需的提示词文本。 52 | * **取值范围**: `1 <= x <= 2000` 53 | 54 | ### image_url 55 | * **类型**: `string` 56 | * **是否必需**: 否 57 | * **说明**: 用于视频生成的首帧图片的 URL。 58 | 59 | ### enable_prompt_expansion 60 | * **类型**: `boolean` 61 | * **是否必需**: 否 62 | * **说明**: 是否启用提示词优化。 63 | * **默认值**: `true` 64 | 65 | ## 响应 66 | 67 | ### task_id 68 | * **类型**: `string` 69 | * **是否必需**: 是 70 | * **说明**: 异步任务的 task\_id。您应该使用该 task\_id 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果。 -------------------------------------------------------------------------------- /src/models/kie-seedream-4.5.ts: -------------------------------------------------------------------------------- 1 | import { ParamDef } from '../types/schema' 2 | 3 | /** 4 | * KIE Seedream 4.5 模型参数定义 5 | * 6 | * 特点: 7 | * - 不传递具体分辨率数值,只传递宽高比和质量 8 | * - 质量选项:2K (basic) / 4K (high) 9 | * - 根据图片数量自动切换端点(文生图/图片编辑) 10 | * - 最多支持 14 张图片 11 | * - 隐藏参数:seed, negative_prompt 12 | */ 13 | export const kieSeedream45Params: ParamDef[] = [ 14 | // 宽高比参数(带智能匹配和质量选择) 15 | { 16 | id: 'kieSeedreamAspectRatio', 17 | type: 'dropdown', 18 | defaultValue: '1:1', 19 | resolutionConfig: { 20 | type: 'aspect_ratio', 21 | smartMatch: true, 22 | visualize: true, 23 | extractRatio: (value) => { 24 | if (value === 'smart') return null 25 | const [w, h] = value.split(':').map(Number) 26 | return w / h 27 | }, 28 | qualityOptions: [ 29 | { value: '2K', label: '高清 2K' }, 30 | { value: '4K', label: '超清 4K' } 31 | ], 32 | qualityKey: 'kieSeedreamQuality' 33 | }, 34 | // 自动切换:上传图片时切换到智能,删除图片时恢复为 1:1 35 | autoSwitch: { 36 | condition: (values) => values.uploadedImages && values.uploadedImages.length > 0, 37 | value: 'smart', 38 | watchKeys: ['uploadedImages'] // 只监听图片数量变化,避免用户手动选择比例时被强制切换 39 | }, 40 | options: [ 41 | { value: 'smart', label: '智能' }, 42 | { value: '1:1', label: '1:1' }, 43 | { value: '4:3', label: '4:3' }, 44 | { value: '3:4', label: '3:4' }, 45 | { value: '16:9', label: '16:9' }, 46 | { value: '9:16', label: '9:16' }, 47 | { value: '2:3', label: '2:3' }, 48 | { value: '3:2', label: '3:2' }, 49 | { value: '21:9', label: '21:9' } 50 | ], 51 | className: 'min-w-[100px]' 52 | } 53 | ] 54 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/视频/Kling-o1_图生视频.md: -------------------------------------------------------------------------------- 1 | # Kling-o1 图生视频 2 | 3 | Kling Omni Video O1 图像转视频工具利用 MVL(多模态视觉语言)技术,将静态图像转换为动态的电影级视频。它在保持主体一致性的同时,还能添加自然运动、物理模拟和流畅的场景动态效果。 4 | 5 | 这是一个**异步**API,只会返回异步任务的 task_id。您应该使用该 task_id 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来检索视频生成结果。 6 | 7 | ## 接口调用 8 | 9 | **请求方法**: POST 10 | **端点**: `https://api.ppinfra.com/v3/async/kling-o1-i2v` 11 | 12 | ### 请求示例 (cURL) 13 | 14 | ```bash 15 | curl --request POST \ 16 | --url https://api.ppinfra.com/v3/async/kling-o1-i2v \ 17 | --header 'Authorization: ' \ 18 | --header 'Content-Type: application/json' \ 19 | --data ' 20 | { 21 | "image": "", 22 | "prompt": "", 23 | "duration": 123, 24 | "last_image": "", 25 | "aspect_ratio": "" 26 | } 27 | ' 28 | ``` 29 | 30 | ### 响应示例 31 | 32 | ```json 33 | { 34 | "task_id": "" 35 | } 36 | ``` 37 | 38 | ## 请求头 39 | 40 | | 参数 | 类型 | 是否必需 | 描述 | 41 | | :--- | :--- | :--- | :--- | 42 | | `Content-Type` | string | 是 | 必须为 `application/json`。 | 43 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 44 | 45 | ## 请求体 46 | 47 | | 参数 | 类型 | 是否必需 | 默认值 | 描述 | 48 | | :--- | :--- | :--- | :--- | :--- | 49 | | `image` | string | 是 | - | 首帧图像。 | 50 | | `prompt` | string | 是 | - | 生成视频的正向提示词。 | 51 | | `duration` | integer | 否 | `5` | 生成视频的持续时间(秒)。可选值:`5`, `10`。 | 52 | | `last_image` | string | 否 | - | 末帧图像。 | 53 | | `aspect_ratio` | string | 否 | `"16:9"` | 生成视频的宽高比。可选值:`16:9`, `9:16`, `1:1`。 | 54 | 55 | ## 响应 56 | 57 | | 参数 | 类型 | 是否必需 | 描述 | 58 | | :--- | :--- | :--- | :--- | 59 | | `task_id` | string | 是 | 异步任务的唯一标识符。您需要使用此 task_id 调用 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来获取最终生成结果。 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/视频/Kling-o1_文生视频.md: -------------------------------------------------------------------------------- 1 | # Kling-o1 文生视频 2 | 3 | Kling Omni Video O1 是快手首款采用 MVL(多模态视觉语言)技术的统一多模态视频模型。其文本转视频模式可根据文本提示生成电影级视频,并保持主题一致性、自然物理模拟和精准语义理解。 4 | 5 | 这是一个**异步**API,只会返回异步任务的 `task_id`。您应该使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来检索视频生成结果。 6 | 7 | ## 请求 8 | 9 | **端点** 10 | ``` 11 | POST https://api.ppinfra.com/v3/async/kling-o1-t2v 12 | ``` 13 | 14 | **cURL 示例** 15 | ```bash 16 | curl --request POST \ 17 | --url https://api.ppinfra.com/v3/async/kling-o1-t2v \ 18 | --header 'Authorization: ' \ 19 | --header 'Content-Type: application/json' \ 20 | --data ' 21 | { 22 | "prompt": "", 23 | "duration": 123, 24 | "aspect_ratio": "" 25 | } 26 | ' 27 | ``` 28 | 29 | ## 请求头 30 | 31 | | 参数 | 类型 | 是否必需 | 描述 | 32 | | :--- | :--- | :--- | :--- | 33 | | `Content-Type` | string | 是 | 必须为 `application/json`。 | 34 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 35 | 36 | ## 请求体 37 | 38 | | 参数 | 类型 | 是否必需 | 默认值 | 描述 | 可选值 | 39 | | :--- | :--- | :--- | :--- | :--- | :--- | 40 | | `prompt` | string | 是 | - | 生成视频的正向提示词。 | - | 41 | | `duration` | integer | 否 | `5` | 生成视频的持续时间(秒)。 | `5`, `10` | 42 | | `aspect_ratio` | string | 否 | `"16:9"` | 生成视频的宽高比。 | `16:9`, `9:16`, `1:1` | 43 | 44 | ## 响应 45 | 46 | **响应示例** 47 | ```json 48 | { 49 | "task_id": "" 50 | } 51 | ``` 52 | 53 | **响应参数** 54 | 55 | | 参数 | 类型 | 是否必需 | 描述 | 56 | | :--- | :--- | :--- | :--- | 57 | | `task_id` | string | 是 | 异步任务的 ID。您应使用此 ID 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果。 | 58 | 59 | --- 60 | [Kling-o1 参考生视频](/docs/models/reference-kling-o1-ref2v) | [Kling-o1 视频编辑](/docs/models/reference-kling-o1-video-edit) -------------------------------------------------------------------------------- /src/adapters/kie/models/hailuo-2-3.ts: -------------------------------------------------------------------------------- 1 | import { GenerateVideoParams } from '@/adapters/base/BaseAdapter' 2 | 3 | export interface KIEModelRoute { 4 | matches: (modelId: string) => boolean 5 | buildImageRequest?: (params: any) => { 6 | requestData: any 7 | } 8 | buildVideoRequest?: (params: GenerateVideoParams) => { 9 | requestData: any 10 | } 11 | } 12 | 13 | /** 14 | * KIE Hailuo 2.3 图生视频模型路由 15 | * 16 | * 特点: 17 | * - 图生视频模型(必须上传图片) 18 | * - 支持标准和专业两种模式 19 | * - 标准模式:hailuo/2-3-image-to-video-standard 20 | * - 专业模式:hailuo/2-3-image-to-video-pro 21 | * - 1080P 分辨率不支持 10 秒时长 22 | */ 23 | export const kieHailuo23Route: KIEModelRoute = { 24 | matches: (modelId: string) => 25 | modelId === 'kie-hailuo-2-3' || 26 | modelId === 'hailuo-2-3-kie', 27 | 28 | buildVideoRequest: (params: GenerateVideoParams) => { 29 | const images = params.images || [] 30 | const prompt = params.prompt || '' 31 | 32 | // 获取模式参数(standard 或 pro) 33 | const mode = (params as any).mode || 'standard' 34 | 35 | // 根据模式选择端点 36 | const model = mode === 'pro' 37 | ? 'hailuo/2-3-image-to-video-pro' 38 | : 'hailuo/2-3-image-to-video-standard' 39 | 40 | // 获取时长和分辨率参数 41 | const duration = params.duration || 6 42 | const resolution = params.resolution || '768P' 43 | 44 | // 构建请求数据 45 | const requestData: any = { 46 | model: model, 47 | input: { 48 | prompt: prompt, 49 | // 图片 URL(必须,取第一张图片) 50 | image_url: images.length > 0 ? images[0] : '', 51 | // 时长(转换为字符串) 52 | duration: String(duration), 53 | // 分辨率 54 | resolution: resolution 55 | } 56 | } 57 | 58 | return { requestData } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/utils/modelConfig.ts: -------------------------------------------------------------------------------- 1 | import { providers } from '@/config/providers' 2 | 3 | /** 4 | * 进度配置类型 5 | */ 6 | export interface ProgressConfig { 7 | /** 进度类型 */ 8 | type: 'polling' | 'time' | 'none' 9 | /** 预期轮询次数(仅 polling 类型) */ 10 | expectedPolls?: number 11 | /** 预期耗时(毫秒,仅 time 类型) */ 12 | expectedDuration?: number 13 | } 14 | 15 | /** 16 | * 获取指定模型的进度配置 17 | * 18 | * @param modelId 模型ID 19 | * @returns 进度配置对象 20 | * 21 | * @example 22 | * ```typescript 23 | * const config = getProgressConfig('vidu-q1') 24 | * // { type: 'polling', expectedPolls: 60 } 25 | * 26 | * const config2 = getProgressConfig('seedream-4.0') 27 | * // { type: 'time', expectedDuration: 20000 } 28 | * ``` 29 | */ 30 | export function getProgressConfig(modelId: string): ProgressConfig { 31 | for (const provider of providers) { 32 | const model = provider.models.find(m => m.id === modelId) 33 | if (model && (model as any).progressConfig) { 34 | return (model as any).progressConfig 35 | } 36 | } 37 | 38 | // 默认配置:使用轮询,预期40次 39 | return { 40 | type: 'polling', 41 | expectedPolls: 40 42 | } 43 | } 44 | 45 | /** 46 | * 获取预期轮询次数(仅用于轮询类型) 47 | * 48 | * @param modelId 模型ID 49 | * @returns 预期轮询次数 50 | */ 51 | export function getExpectedPolls(modelId: string): number { 52 | const config = getProgressConfig(modelId) 53 | return config.expectedPolls || 40 54 | } 55 | 56 | /** 57 | * 获取预期耗时(仅用于时间类型) 58 | * 59 | * @param modelId 模型ID 60 | * @returns 预期耗时(毫秒) 61 | */ 62 | export function getExpectedDuration(modelId: string): number { 63 | const config = getProgressConfig(modelId) 64 | return config.expectedDuration || 20000 65 | } 66 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/视频/KLING_V1.6_文生视频.md: -------------------------------------------------------------------------------- 1 | # KLING V1.6 文生视频 2 | 3 | KLING V1.6 文生视频是快手 AI 团队开发的 AI 文本生成视频模型。它可将文本描述转化为动态的 5 秒 720p 视频,具备高质量视觉输出、增强的运动与语义理解能力。 4 | 5 | 这是一个**异步**API,只会返回异步任务的 `task_id`。您应该使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来检索视频生成结果。 6 | 7 | ## 请求示例 8 | 9 | **请求** 10 | 11 | ```bash 12 | curl --request POST \ 13 | --url https://api.ppinfra.com/v3/async/kling-v1.6-t2v \ 14 | --header 'Authorization: ' \ 15 | --header 'Content-Type: application/json' \ 16 | --data ' 17 | { 18 | "mode": "", 19 | "prompt": "", 20 | "negative_prompt": "", 21 | "duration": 123, 22 | "guidance_scale": 123 23 | } 24 | ' 25 | ``` 26 | 27 | **响应** 28 | 29 | ```json 30 | { 31 | "task_id": "" 32 | } 33 | ``` 34 | 35 | ## 请求头 36 | 37 | | 参数名 | 类型 | 是否必需 | 说明 | 38 | | :--- | :--- | :--- | :--- | 39 | | `Content-Type` | string | 是 | 必须为 `application/json`。 | 40 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 41 | 42 | ## 请求体 43 | 44 | | 参数名 | 类型 | 是否必需 | 说明 | 45 | | :--- | :--- | :--- | :--- | 46 | | `mode` | string | 否 | 视频生成模式。支持:
• `Standard`:快速生成,成本较低,生成 720p 视频。
默认值:`Standard`。 | 47 | | `prompt` | string | 是 | 指导生成所需的提示词文本。取值范围:`1 <= x <= 2000`。 | 48 | | `negative_prompt` | string | 否 | 负面提示词,用于指示模型应避免生成的内容。取值范围:`0 <= x <= 2000`。 | 49 | | `duration` | integer | 否 | 生成视频的时长(秒)。默认值:`5`。
可选值:`5`、`10`。 | 50 | | `guidance_scale` | float | 否 | 指导强度参数,控制生成内容与提示词的贴合程度。取值范围:`0 <= x <= 1`。默认值:`0.5`。 | 51 | 52 | ## 响应 53 | 54 | | 参数名 | 类型 | 是否必需 | 说明 | 55 | | :--- | :--- | :--- | :--- | 56 | | `task_id` | string | 是 | 异步任务的 task_id。您应该使用该 task_id 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果。 | -------------------------------------------------------------------------------- /src/adapters/fal/models/fal-ai-nano-banana-pro.ts: -------------------------------------------------------------------------------- 1 | import { GenerateImageParams } from '@/adapters/base/BaseAdapter' 2 | 3 | /** 4 | * Fal.ai Nano Banana Pro 模型路由 5 | */ 6 | export const falAiNanoBananaProRoute = { 7 | // 模型ID识别 8 | matches: (modelId: string) => modelId === 'fal-ai/nano-banana-pro' || modelId === 'nano-banana-pro' || modelId === 'fal-ai-nano-banana-pro', 9 | 10 | // 构建图片生成请求 11 | buildImageRequest: (params: GenerateImageParams) => { 12 | const hasImages = params.images && params.images.length > 0 13 | 14 | // submitPath: 提交请求的完整路径(包含subpath如/edit) 15 | // modelId: 查询状态/结果时使用的model_id(不含subpath) 16 | const submitPath = hasImages ? 'fal-ai/nano-banana-pro/edit' : 'fal-ai/nano-banana-pro' 17 | const modelId = 'fal-ai/nano-banana-pro' 18 | 19 | const requestData: any = { 20 | prompt: params.prompt 21 | } 22 | 23 | // 添加可选参数 24 | if (params.falNanoBananaNumImages !== undefined) { 25 | requestData.num_images = params.falNanoBananaNumImages 26 | } 27 | 28 | // aspect_ratio: 不发送 'auto' 或 'smart' 29 | if (params.aspect_ratio !== undefined && 30 | params.aspect_ratio !== 'auto' && 31 | params.aspect_ratio !== 'smart') { 32 | requestData.aspect_ratio = params.aspect_ratio 33 | } 34 | 35 | // 添加 resolution 参数(仅 nano-banana-pro) 36 | const resolution = params.falNanoBananaProResolution ?? params.resolution 37 | if (resolution !== undefined) { 38 | requestData.resolution = resolution 39 | } 40 | 41 | // 处理图生图:添加 image_urls 42 | // 注意:FalAdapter 已经将图片上传到 fal CDN,这里直接使用 URL 43 | if (hasImages) { 44 | requestData.image_urls = params.images 45 | } 46 | 47 | return { submitPath, modelId, requestData } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/models/kie-grok-imagine-video.ts: -------------------------------------------------------------------------------- 1 | import { ParamDef } from '../types/schema' 2 | 3 | /** 4 | * KIE Grok Imagine 视频模型参数定义 5 | */ 6 | export const kieGrokImagineVideoParams: ParamDef[] = [ 7 | // 宽高比参数(仅文生视频支持) 8 | { 9 | id: 'kieGrokImagineVideoAspectRatio', 10 | type: 'dropdown', 11 | defaultValue: '2:3', 12 | resolutionConfig: { 13 | type: 'aspect_ratio', 14 | smartMatch: false, // Grok Imagine 视频不支持智能匹配 15 | visualize: true, 16 | extractRatio: (value) => { 17 | const [w, h] = value.split(':').map(Number) 18 | return w / h 19 | } 20 | // 注意:没有 qualityOptions,因为 Grok Imagine 视频不支持分辨率选择 21 | }, 22 | options: [ 23 | { value: '2:3', label: '2:3' }, 24 | { value: '3:2', label: '3:2' }, 25 | { value: '1:1', label: '1:1' } 26 | ], 27 | // 图生视频时隐藏比例参数(API 不支持) 28 | hidden: (values) => values.uploadedImages && values.uploadedImages.length > 0, 29 | className: 'min-w-[100px]' 30 | }, 31 | // 模式参数 32 | { 33 | id: 'kieGrokImagineVideoMode', 34 | type: 'dropdown', 35 | label: '模式', 36 | defaultValue: 'normal', 37 | // 动态选项:图生视频时不显示 spicy(外部图像不支持) 38 | options: (values) => { 39 | const hasImages = values.uploadedImages && values.uploadedImages.length > 0 40 | 41 | if (hasImages) { 42 | // 图生视频:不支持 spicy 43 | return [ 44 | { value: 'fun', label: 'Fun' }, 45 | { value: 'normal', label: 'Normal' } 46 | ] 47 | } 48 | 49 | // 文生视频:支持所有模式 50 | return [ 51 | { value: 'fun', label: 'Fun' }, 52 | { value: 'normal', label: 'Normal' }, 53 | { value: 'spicy', label: 'Spicy' } 54 | ] 55 | }, 56 | className: 'min-w-[100px]' 57 | } 58 | ] 59 | -------------------------------------------------------------------------------- /src/models/qwen-image-edit-2509.ts: -------------------------------------------------------------------------------- 1 | import { ParamDef } from '../types/schema' 2 | 3 | // Qwen-Image-Edit-2509 参数 4 | // 支持上传最多3张图片进行编辑 5 | export const qwenImageEdit2509Params: ParamDef[] = [ 6 | { 7 | id: 'modelscopeImageSize', 8 | type: 'dropdown', 9 | label: '分辨率', 10 | defaultValue: 'smart', // 默认为智能模式 11 | resolutionConfig: { 12 | type: 'aspect_ratio', 13 | smartMatch: true, // 启用智能匹配 14 | visualize: true, 15 | customInput: true, 16 | // ⚠️ 不使用基数系统,每个比例自动计算最佳值 17 | baseSizeEditable: false, // 禁用基数编辑 18 | useQwenCalculator: true, // 使用 Qwen 专用计算器 19 | extractRatio: (value) => { 20 | if (value === 'smart') return null 21 | if (value.includes(':')) { 22 | const [w, h] = value.split(':').map(Number) 23 | return w / h 24 | } 25 | return null 26 | } 27 | }, 28 | options: (_values: any) => { 29 | const baseOptions = [ 30 | { value: '21:9', label: '21:9' }, 31 | { value: '16:9', label: '16:9' }, 32 | { value: '3:2', label: '3:2' }, 33 | { value: '4:3', label: '4:3' }, 34 | { value: '1:1', label: '1:1' }, 35 | { value: '3:4', label: '3:4' }, 36 | { value: '2:3', label: '2:3' }, 37 | { value: '9:16', label: '9:16' }, 38 | { value: '9:21', label: '9:21' } 39 | ] 40 | 41 | // 智能选项始终显示 42 | return [{ value: 'smart', label: '智能' }, ...baseOptions] 43 | } 44 | }, 45 | { 46 | id: 'steps', 47 | type: 'number', 48 | label: '采样步数', 49 | min: 1, 50 | max: 100, 51 | step: 1, 52 | defaultValue: 30, 53 | widthClassName: 'w-24', 54 | tooltip: '采样步数越多,生成的图像越精细,但耗时也越长。建议值:20-50', 55 | tooltipDelay: 500 56 | } 57 | ] 58 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/大语言/列出模型.md: -------------------------------------------------------------------------------- 1 | # 列出模型 2 | 3 | 列出当前可用的 LLM 模型,并提供每个模型的基本信息。该接口与 OpenAI API 兼容。 4 | 5 | **来源:** https://ppio.com/docs/models/reference-llm-list-models 6 | 7 | ## 接口信息 8 | 9 | * **方法:** `GET` 10 | * **端点:** `https://api.ppinfra.com/openai/v1/models` 11 | 12 | ## 请求示例 13 | 14 | ```bash 15 | curl --request GET \ 16 | --url https://api.ppinfra.com/openai/v1/models \ 17 | --header 'Authorization: ' \ 18 | --header 'Content-Type: ' 19 | ``` 20 | 21 | ## 响应示例 22 | 23 | ```json 24 | { 25 | "data": [ 26 | { 27 | "id": "", 28 | "created": 123, 29 | "object": "", 30 | "input_token_price_per_m": 123, 31 | "output_token_price_per_m": 123, 32 | "title": "", 33 | "description": "", 34 | "context_size": 123 35 | } 36 | ] 37 | } 38 | ``` 39 | 40 | ## 请求头 41 | 42 | | 参数 | 类型 | 是否必需 | 描述 | 43 | | :--- | :--- | :--- | :--- | 44 | | `Content-Type` | `string` | 是 | 必须为 `application/json`。 | 45 | | `Authorization` | `string` | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 46 | 47 | ## 响应参数 48 | 49 | | 参数 | 类型 | 是否必需 | 描述 | 50 | | :--- | :--- | :--- | :--- | 51 | | `data` | `array` | 是 | 包含以下属性的模型对象数组。 | 52 | 53 | **`data` 数组中的对象属性:** 54 | 55 | | 参数 | 类型 | 是否必需 | 描述 | 56 | | :--- | :--- | :--- | :--- | 57 | | `id` | `string` | 是 | 模型 ID,用于标识模型。可以在 API Endpoints 中引用。 | 58 | | `created` | `integer` | 是 | 模型创建时的 Unix 时间戳(以秒为单位)。 | 59 | | `object` | `string` | 是 | 对象类型。取值固定为 `model`。 | 60 | | `input_token_price_per_m` | `integer` | 是 | 输入价格(每百万 Token)。 | 61 | | `output_token_price_per_m` | `integer` | 是 | 输出价格(每百万 Token)。 | 62 | | `title` | `string` | 是 | 模型名称。 | 63 | | `description` | `string` | 是 | 模型描述。 | 64 | | `context_size` | `integer` | 是 | 模型允许的最大上下文长度。 | -------------------------------------------------------------------------------- /src/adapters/fal/models/fal-ai-bytedance-seedream-v4.ts: -------------------------------------------------------------------------------- 1 | import { FalModelRoute } from './index' 2 | 3 | export const falAiBytedanceSeedreamV4Route: FalModelRoute = { 4 | matches: (modelId: string) => modelId === 'bytedance-seedream-v4' || modelId === 'fal-ai-bytedance-seedream-v4', 5 | 6 | buildImageRequest: (params: any) => { 7 | const images = params.images || [] 8 | const prompt = params.prompt || '' 9 | const numImages = params.falSeedream40NumImages || 1 10 | 11 | // 处理imageSize参数,从字符串格式转换为对象格式 12 | let imageSize = { width: 2048, height: 2048 } 13 | if (params.imageSize) { 14 | const [width, height] = params.imageSize.split('*').map(Number) 15 | imageSize = { width, height } 16 | } 17 | 18 | // 注意:bytedance seedream v4 的 model ID 本身就包含完整路径 19 | // 不像其他模型那样有 base model ID + subpath 的结构 20 | // submitPath 和 modelId 使用相同的完整路径 21 | 22 | // 根据输入类型选择端点 23 | if (images.length === 0) { 24 | // 文生图(异步模式,支持进度回调) 25 | const fullPath = 'fal-ai/bytedance/seedream/v4/text-to-image' 26 | return { 27 | submitPath: fullPath, 28 | modelId: fullPath, 29 | requestData: { 30 | prompt, 31 | image_size: imageSize, 32 | num_images: numImages, 33 | enable_safety_checker: false 34 | } 35 | } 36 | } else { 37 | // 图生图/编辑(异步模式,支持进度回调) 38 | const fullPath = 'fal-ai/bytedance/seedream/v4/edit' 39 | return { 40 | submitPath: fullPath, 41 | modelId: fullPath, 42 | requestData: { 43 | prompt, 44 | image_size: imageSize, 45 | num_images: numImages, 46 | image_urls: images, 47 | enable_safety_checker: false 48 | } 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/视频/Seedance_V1_Pro_文生视频.md: -------------------------------------------------------------------------------- 1 | # Seedance V1 Pro 文生视频 2 | 3 | Seedance V1 Pro 是一个 AI 视频模型,专为生成连贯的多镜头视频而设计,提供流畅的运动和对详细提示的精确遵循。它支持 480p、720p 和 1080p 的分辨率。 4 | 5 | 本接口支持个人认证及企业认证用户调用。请参见 [实名认证](/docs/support/identity-verification),完成个人用户认证或企业用户认证,以确保可以正常使用本功能。 6 | 7 | ## 接口调用示例 8 | 9 | **请求示例** 10 | ```bash 11 | curl --request POST \ 12 | --url https://api.ppinfra.com/v3/async/seedance-v1-pro-t2v \ 13 | --header 'Authorization: ' \ 14 | --header 'Content-Type: application/json' \ 15 | --data ' 16 | { 17 | "prompt": "", 18 | "resolution": "", 19 | "aspect_ratio": "", 20 | "duration": 123, 21 | "camera_fixed": true, 22 | "seed": 123 23 | } 24 | ' 25 | ``` 26 | 27 | **响应示例** 28 | ```json 29 | { 30 | "task_id": "" 31 | } 32 | ``` 33 | 34 | ## 请求头 35 | 36 | | 参数名 | 类型 | 是否必需 | 说明 | 37 | | :--- | :--- | :--- | :--- | 38 | | `Content-Type` | string | 是 | 必须为 `application/json`。 | 39 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 40 | 41 | ## 请求体 42 | 43 | | 参数名 | 类型 | 是否必需 | 默认值 | 说明 | 44 | | :--- | :--- | :--- | :--- | :--- | 45 | | `prompt` | string | 是 | - | 视频生成的文本提示(正面提示);支持中英文,建议不超过500字。 | 46 | | `resolution` | string | 是 | - | 视频质量。可选值:`480p`,`720p`,`1080p`。 | 47 | | `aspect_ratio` | string | 否 | `"16:9"` | 生成视频的长宽比。可选值:`21:9`, `16:9`, `4:3`, `1:1`, `3:4`, `9:16`, `9:21`。 | 48 | | `duration` | integer | 是 | `5` | 指定生成视频的长度(以秒为单位)。可选值:`5`,`10`。 | 49 | | `camera_fixed` | boolean | 否 | `false` | 确定相机位置是否应保持固定。 | 50 | | `seed` | integer | 否 | `-1` | 用于生成的随机种子。`-1` 表示将使用随机种子。 | 51 | 52 | ## 响应 53 | 54 | | 参数名 | 类型 | 是否必需 | 说明 | 55 | | :--- | :--- | :--- | :--- | 56 | | `task_id` | string | 是 | 异步任务的 ID。您需要使用此 `task_id` 调用 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果。 | -------------------------------------------------------------------------------- /src/adapters/fal/models/fal-ai-bytedance-seedream-v4.5.ts: -------------------------------------------------------------------------------- 1 | import { FalModelRoute } from './index' 2 | 3 | export const falAiBytedanceSeedreamV45Route: FalModelRoute = { 4 | matches: (modelId: string) => modelId === 'bytedance-seedream-v4.5' || modelId === 'fal-ai-bytedance-seedream-v4.5', 5 | 6 | buildImageRequest: (params: any) => { 7 | const images = params.images || [] 8 | const prompt = params.prompt || '' 9 | const numImages = params.falSeedream40NumImages || 1 10 | 11 | // 处理imageSize参数,从字符串格式转换为对象格式 12 | let imageSize = { width: 2048, height: 2048 } 13 | if (params.imageSize) { 14 | const [width, height] = params.imageSize.split('*').map(Number) 15 | imageSize = { width, height } 16 | } 17 | 18 | // 注意:bytedance seedream v4.5 的 model ID 本身就包含完整路径 19 | // 不像其他模型那样有 base model ID + subpath 的结构 20 | // submitPath 和 modelId 使用相同的完整路径 21 | 22 | // 根据输入类型选择端点 23 | if (images.length === 0) { 24 | // 文生图(异步模式,支持进度回调) 25 | const fullPath = 'fal-ai/bytedance/seedream/v4.5/text-to-image' 26 | return { 27 | submitPath: fullPath, 28 | modelId: fullPath, 29 | requestData: { 30 | prompt, 31 | image_size: imageSize, 32 | num_images: numImages, 33 | enable_safety_checker: false 34 | } 35 | } 36 | } else { 37 | // 图生图/编辑(异步模式,支持进度回调) 38 | const fullPath = 'fal-ai/bytedance/seedream/v4.5/edit' 39 | return { 40 | submitPath: fullPath, 41 | modelId: fullPath, 42 | requestData: { 43 | prompt, 44 | image_size: imageSize, 45 | num_images: numImages, 46 | image_urls: images, 47 | enable_safety_checker: false 48 | } 49 | } 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/视频/Seedance_V1_Lite_文生视频.md: -------------------------------------------------------------------------------- 1 | # Seedance V1 Lite 文生视频 2 | 3 | Seedance V1 Lite 是一款 AI 视频模型,专为生成连贯的多镜头视频而设计,提供流畅的运动和对详细提示的精确遵循。它支持 480p、720p 和 1080p 的分辨率。 4 | 5 | 本接口支持个人认证及企业认证用户调用。请参见 [实名认证](/docs/support/identity-verification),完成个人用户认证或企业用户认证,以确保可以正常使用本功能。 6 | 7 | ## 接口调用示例 8 | 9 | **请求示例** 10 | ```bash 11 | curl --request POST \ 12 | --url https://api.ppinfra.com/v3/async/seedance-v1-lite-t2v \ 13 | --header 'Authorization: ' \ 14 | --header 'Content-Type: application/json' \ 15 | --data ' 16 | { 17 | "prompt": "", 18 | "resolution": "", 19 | "aspect_ratio": "", 20 | "duration": 123, 21 | "camera_fixed": true, 22 | "seed": 123 23 | } 24 | ' 25 | ``` 26 | 27 | **响应示例** 28 | ```json 29 | { 30 | "task_id": "" 31 | } 32 | ``` 33 | 34 | ## 请求头 35 | 36 | | 参数 | 类型 | 是否必需 | 描述 | 37 | | :--- | :--- | :--- | :--- | 38 | | `Content-Type` | string | 是 | 必须为 `application/json`。 | 39 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 40 | 41 | ## 请求体 42 | 43 | | 参数 | 类型 | 是否必需 | 默认值 | 描述 | 44 | | :--- | :--- | :--- | :--- | :--- | 45 | | `prompt` | string | 是 | - | 视频生成的文本提示(正面提示);支持中英文,建议不超过500字。 | 46 | | `resolution` | string | 是 | - | 视频质量。可接受的值:`480p`,`720p`,`1080p`。 | 47 | | `aspect_ratio` | string | 否 | `"16:9"` | 生成视频的长宽比。可接受的值:`21:9`,`16:9`,`4:3`,`1:1`,`3:4`,`9:16`,`9:21`。 | 48 | | `duration` | integer | 是 | `5` | 指定生成视频的长度(以秒为单位)。可用选项:`5`,`10`。 | 49 | | `camera_fixed` | boolean | 否 | `false` | 确定相机位置是否应保持固定。 | 50 | | `seed` | integer | 否 | `-1` | 用于生成的随机种子。`-1` 表示将使用随机种子。 | 51 | 52 | ## 响应 53 | 54 | | 参数 | 类型 | 是否必需 | 描述 | 55 | | :--- | :--- | :--- | :--- | 56 | | `task_id` | string | 是 | 异步任务的 `task_id`。您应该使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果。 | -------------------------------------------------------------------------------- /src/adapters/kie/models/seedream-4.5.ts: -------------------------------------------------------------------------------- 1 | import { GenerateImageParams } from '@/adapters/base/BaseAdapter' 2 | 3 | export interface KIEModelRoute { 4 | matches: (modelId: string) => boolean 5 | buildImageRequest?: (params: GenerateImageParams) => { 6 | requestData: any 7 | } 8 | } 9 | 10 | export const kieSeedream45Route: KIEModelRoute = { 11 | matches: (modelId: string) => 12 | modelId === 'kie-seedream-4.5' || 13 | modelId === 'seedream-4.5-kie', 14 | 15 | buildImageRequest: (params: GenerateImageParams) => { 16 | const images = params.images || [] 17 | const prompt = params.prompt || '' 18 | 19 | // 根据图片数量自动选择模型端点 20 | // 无图片:文生图 (seedream/4.5-text-to-image) 21 | // 有图片:图片编辑 (seedream/4.5-edit) 22 | const modelName = images.length === 0 23 | ? 'seedream/4.5-text-to-image' 24 | : 'seedream/4.5-edit' 25 | 26 | // 构建请求数据 27 | const requestData: any = { 28 | model: modelName, 29 | input: { 30 | prompt: prompt 31 | } 32 | } 33 | 34 | // 添加宽高比参数(必填,过滤掉 'smart' 和 'auto') 35 | if (params.aspect_ratio !== undefined && 36 | params.aspect_ratio !== 'smart' && 37 | params.aspect_ratio !== 'auto') { 38 | requestData.input.aspect_ratio = params.aspect_ratio 39 | } 40 | 41 | // 添加质量参数(必填) 42 | // 注意:quality 已经在 OptionsBuilder 中通过 transform 转换为 'basic'/'high' 43 | if (params.quality !== undefined) { 44 | requestData.input.quality = params.quality 45 | } 46 | 47 | // 如果有图片,添加到 image_urls(KIE 已上传的 URL) 48 | // 图片编辑端点使用 image_urls 参数 49 | if (images.length > 0) { 50 | requestData.input.image_urls = images 51 | } 52 | 53 | // 注意:seed 和 negative_prompt 参数不传递给 API 54 | // 这些参数在 UI 中隐藏,也不会出现在 params 中 55 | 56 | return { requestData } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/models/fal-ai-kling-image-o1.ts: -------------------------------------------------------------------------------- 1 | import { ParamDef } from '../types/schema' 2 | 3 | /** 4 | * Kling Image O1 模型参数定义 5 | * 特点:必须有图片输入,融合 aspect_ratio 和 resolution 6 | */ 7 | export const falAiKlingImageO1Params: ParamDef[] = [ 8 | { 9 | id: 'falKlingImageO1Num_images', 10 | type: 'number', 11 | label: '数量', 12 | min: 1, 13 | max: 9, 14 | step: 1, 15 | widthClassName: 'w-20' 16 | }, 17 | { 18 | id: 'falKlingImageO1AspectRatio', 19 | type: 'dropdown', 20 | defaultValue: '1:1', // 无图时默认 1:1 21 | // 分辨率配置:启用智能匹配、可视化和质量选项 22 | resolutionConfig: { 23 | type: 'aspect_ratio', 24 | smartMatch: true, 25 | visualize: true, 26 | extractRatio: (value) => { 27 | if (value === 'auto') return null 28 | const [w, h] = value.split(':').map(Number) 29 | return w / h 30 | }, 31 | qualityOptions: [ 32 | { value: '1K', label: '1K' }, 33 | { value: '2K', label: '2K' } 34 | ], 35 | qualityKey: 'resolution', // Kling O1 使用 'resolution' 作为质量参数 36 | defaultQuality: '2K' // 默认 2K 37 | }, 38 | // 当上传图片时自动切换到 auto 39 | autoSwitch: { 40 | condition: (values) => values.uploadedImages && values.uploadedImages.length > 0, 41 | value: 'auto', 42 | watchKeys: ['uploadedImages'] // 只监听图片数量变化,避免用户手动选择比例时被强制切换 43 | }, 44 | options: [ 45 | { value: 'auto', label: '智能' }, 46 | { value: '1:1', label: '1:1' }, 47 | { value: '16:9', label: '16:9' }, 48 | { value: '9:16', label: '9:16' }, 49 | { value: '4:3', label: '4:3' }, 50 | { value: '3:4', label: '3:4' }, 51 | { value: '3:2', label: '3:2' }, 52 | { value: '2:3', label: '2:3' }, 53 | { value: '21:9', label: '21:9' } 54 | ], 55 | className: 'min-w-[100px]' 56 | } 57 | ] 58 | -------------------------------------------------------------------------------- /src/adapters/fal/models/fal-ai-nano-banana.ts: -------------------------------------------------------------------------------- 1 | import { GenerateImageParams } from '@/adapters/base/BaseAdapter' 2 | import { logInfo } from '../../../utils/errorLogger' 3 | 4 | /** 5 | * Fal.ai Nano Banana 模型路由 6 | */ 7 | export const falAiNanoBananaRoute = { 8 | // 模型ID识别 9 | matches: (modelId: string) => modelId === 'fal-ai/nano-banana' || modelId === 'nano-banana' || modelId === 'fal-ai-nano-banana', 10 | 11 | // 构建图片生成请求 12 | buildImageRequest: (params: GenerateImageParams) => { 13 | const hasImages = params.images && params.images.length > 0 14 | 15 | // submitPath: 提交请求的完整路径(包含subpath如/edit) 16 | // modelId: 查询状态/结果时使用的model_id(不含subpath) 17 | const submitPath = hasImages ? 'fal-ai/nano-banana/edit' : 'fal-ai/nano-banana' 18 | const modelId = 'fal-ai/nano-banana' 19 | 20 | const requestData: any = { 21 | prompt: params.prompt 22 | } 23 | 24 | // 添加可选参数 25 | if (params.falNanoBananaNumImages !== undefined) { 26 | requestData.num_images = params.falNanoBananaNumImages 27 | } 28 | 29 | // aspect_ratio: 不发送 'auto' 或 'smart' 30 | logInfo('[fal-ai-nano-banana] params.aspect_ratio:', params.aspect_ratio) 31 | if (params.aspect_ratio !== undefined && 32 | params.aspect_ratio !== 'auto' && 33 | params.aspect_ratio !== 'smart') { 34 | logInfo('[fal-ai-nano-banana] Adding aspect_ratio to request:', params.aspect_ratio) 35 | requestData.aspect_ratio = params.aspect_ratio 36 | } else { 37 | logInfo('[fal-ai-nano-banana] Skipping aspect_ratio (undefined, auto, or smart)', {}) 38 | } 39 | 40 | // 处理图生图:添加 image_urls 41 | // 注意:FalAdapter 已经将图片上传到 fal CDN,这里直接使用 URL 42 | if (hasImages) { 43 | requestData.image_urls = params.images 44 | } 45 | 46 | return { submitPath, modelId, requestData } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/视频/Kling-o1_视频编辑.md: -------------------------------------------------------------------------------- 1 | # Kling-o1 视频编辑 2 | 3 | Kling Omni Video O1 视频编辑器支持通过自然语言命令进行对话式视频编辑。只需简单的文本指令,例如”移除行人”或”将白天改为黄昏”,即可移除物体、更换背景、修改样式、调整天气/光照以及转换场景。 4 | 5 | 这是一个**异步**API,调用后会返回异步任务的 `task_id`。您需要使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来获取最终的视频生成结果。 6 | 7 | ## 请求示例 8 | 9 | **请求端点** 10 | ``` 11 | POST https://api.ppinfra.com/v3/async/kling-o1-video-edit 12 | ``` 13 | 14 | **cURL 示例** 15 | ```bash 16 | curl --request POST \ 17 | --url https://api.ppinfra.com/v3/async/kling-o1-video-edit \ 18 | --header 'Authorization: ' \ 19 | --header 'Content-Type: application/json' \ 20 | --data ' 21 | { 22 | "video": "", 23 | "images": [ 24 | {} 25 | ], 26 | "prompt": "", 27 | "fast_mode": true, 28 | "aspect_ratio": "", 29 | "keep_original_sound": true 30 | } 31 | ' 32 | ``` 33 | 34 | **响应示例** 35 | ```json 36 | { 37 | "task_id": "" 38 | } 39 | ``` 40 | 41 | ## 请求头 42 | 43 | | 参数名 | 类型 | 是否必需 | 描述 | 44 | | :--- | :--- | :--- | :--- | 45 | | `Content-Type` | string | 是 | 必须为 `application/json`。 | 46 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 47 | 48 | ## 请求体 49 | 50 | | 参数名 | 类型 | 是否必需 | 默认值 | 描述 | 51 | | :--- | :--- | :--- | :--- | :--- | 52 | | `video` | string | 是 | - | 待编辑视频的 URL。 | 53 | | `images` | array | 否 | `[]` | 包含元素、场景、风格等参考图片的数组。最多可包含 4 张图片。 | 54 | | `prompt` | string | 是 | - | 描述编辑需求的自然语言提示词。 | 55 | | `fast_mode` | boolean | 否 | `false` | 是否使用快速生成模式。 | 56 | | `aspect_ratio` | string | 否 | - | 生成视频的宽高比。可选值:`16:9`, `9:16`, `1:1`。 | 57 | | `keep_original_sound` | boolean | 否 | `true` | 是否保留原始视频的声音。 | 58 | 59 | ## 响应 60 | 61 | | 参数名 | 类型 | 是否必需 | 描述 | 62 | | :--- | :--- | :--- | :--- | 63 | | `task_id` | string | 是 | 异步任务的 ID。用于向 [查询任务结果 API](/docs/models/reference-get-async-task-result) 请求获取生成结果。 | -------------------------------------------------------------------------------- /src/models/kie-hailuo-02.ts: -------------------------------------------------------------------------------- 1 | import { ParamDef } from '../types/schema' 2 | 3 | /** 4 | * KIE Hailuo 02 模型参数定义 5 | * 6 | * 特点: 7 | * - 支持文生视频和图生视频(根据图片数量自动切换) 8 | * - 当选择 6s + 1080P 时,自动使用 Pro 端点(固定配置,不传递参数) 9 | * - 其他情况使用 Standard 端点(传递 duration 和 resolution 参数) 10 | * - 1080P 只支持 6 秒时长 11 | * - 最多支持 2 张图片(第二张作为 end_image_url) 12 | */ 13 | export const kieHailuo02Params: ParamDef[] = [ 14 | { 15 | id: 'kieHailuo02Duration', 16 | type: 'dropdown', 17 | label: '时长', 18 | defaultValue: 6, 19 | // 动态选项:当分辨率为1080P时,只显示6s选项 20 | options: (values) => { 21 | if (values.kieHailuo02Resolution === '1080P') { 22 | return [{ value: 6, label: '6s' }] 23 | } 24 | return [ 25 | { value: 6, label: '6s' }, 26 | { value: 10, label: '10s' } 27 | ] 28 | }, 29 | className: 'min-w-[50px]' 30 | }, 31 | { 32 | id: 'kieHailuo02Resolution', 33 | type: 'dropdown', 34 | label: '分辨率', 35 | defaultValue: '768P', 36 | // 分辨率配置:使用面板显示 37 | resolutionConfig: { 38 | type: 'resolution', 39 | smartMatch: false, 40 | visualize: false 41 | }, 42 | // 自动切换规则:当选择1080P时,自动将时长设置为6s 43 | autoSwitch: { 44 | condition: (values) => { 45 | return values.kieHailuo02Resolution === '1080P' && values.kieHailuo02Duration !== 6 46 | }, 47 | value: () => 6 48 | }, 49 | // 动态选项:当时长为10秒时,禁用1080P选项 50 | options: (values) => [ 51 | { value: '512P', label: '512P' }, 52 | { value: '768P', label: '768P' }, 53 | { value: '1080P', label: '1080P', disabled: values.kieHailuo02Duration === 10 } 54 | ], 55 | className: 'min-w-[100px]' 56 | }, 57 | { 58 | id: 'kieHailuo02PromptOptimizer', 59 | type: 'toggle', 60 | label: '提示词优化', 61 | defaultValue: true, 62 | className: 'w-auto' 63 | } 64 | ] 65 | -------------------------------------------------------------------------------- /src/models/kie-kling-v2-6.ts: -------------------------------------------------------------------------------- 1 | import { ParamDef } from '../types/schema' 2 | 3 | /** 4 | * KIE Kling V2.6 视频模型参数定义 5 | */ 6 | export const kieKlingV26Params: ParamDef[] = [ 7 | // 宽高比参数(仅文生视频支持,图生视频时隐藏) 8 | { 9 | id: 'kieKlingV26AspectRatio', 10 | type: 'dropdown', 11 | defaultValue: '16:9', 12 | resolutionConfig: { 13 | type: 'aspect_ratio', 14 | smartMatch: false, // Kling V2.6 不支持智能匹配 15 | visualize: true, 16 | extractRatio: (value) => { 17 | const [w, h] = value.split(':').map(Number) 18 | return w / h 19 | } 20 | // 注意:没有 qualityOptions,因为 Kling V2.6 不支持分辨率选择 21 | }, 22 | options: [ 23 | { value: '16:9', label: '16:9' }, 24 | { value: '9:16', label: '9:16' }, 25 | { value: '1:1', label: '1:1' } 26 | ], 27 | // 图生视频时隐藏比例参数(API 不支持) 28 | hidden: (values) => values.uploadedImages && values.uploadedImages.length > 0, 29 | className: 'min-w-[100px]' 30 | }, 31 | // 时长参数 32 | { 33 | id: 'kieKlingV26Duration', 34 | type: 'dropdown', 35 | label: '时长', 36 | defaultValue: '5', 37 | options: [ 38 | { value: '5', label: '5秒' }, 39 | { value: '10', label: '10秒' } 40 | ], 41 | className: 'min-w-[50px]' 42 | }, 43 | // 音频生成开关 44 | { 45 | id: 'kieKlingV26EnableAudio', 46 | type: 'toggle', 47 | label: '生成音频', 48 | defaultValue: false 49 | }, 50 | // 以下参数不显示在UI中,但需要定义以防止意外显示 51 | { 52 | id: 'kieKlingV26Seed', 53 | type: 'number', 54 | label: '随机种子', 55 | hidden: () => true // 始终隐藏 56 | }, 57 | { 58 | id: 'kieKlingV26NegativePrompt', 59 | type: 'text', 60 | label: '负面提示词', 61 | hidden: () => true // 始终隐藏 62 | }, 63 | { 64 | id: 'kieKlingV26CfgScale', 65 | type: 'number', 66 | label: 'CFG Scale', 67 | hidden: () => true // 始终隐藏 68 | } 69 | ] 70 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/视频/Minimax_Hailuo_2.3_Fast_图生视频.md: -------------------------------------------------------------------------------- 1 | # Minimax Hailuo 2.3 Fast 图生视频 2 | 3 | Minimax Hailuo 2.3 Fast 在保持优异画质与表现力的同时,大幅提升了生成速度,具备更高性价比。 4 | 5 | 这是一个**异步**API,调用后会返回异步任务的 `task_id`。您需要使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来获取视频生成结果。 6 | 7 | ## 请求示例 8 | 9 | **请求方法:** POST 10 | **请求地址:** `https://api.ppinfra.com/v3/async/minimax-hailuo-2.3-fast-i2v` 11 | 12 | **cURL 示例:** 13 | ```bash 14 | curl --request POST \ 15 | --url https://api.ppinfra.com/v3/async/minimax-hailuo-2.3-fast-i2v \ 16 | --header 'Authorization: ' \ 17 | --header 'Content-Type: application/json' \ 18 | --data ' 19 | { 20 | "prompt": "", 21 | "image": "", 22 | "duration": 123, 23 | "resolution": "", 24 | "enable_prompt_expansion": true 25 | } 26 | ' 27 | ``` 28 | 29 | **响应示例:** 30 | ```json 31 | { 32 | "task_id": "" 33 | } 34 | ``` 35 | 36 | ## 请求头 37 | 38 | | 参数名 | 类型 | 是否必需 | 说明 | 39 | | :--- | :--- | :--- | :--- | 40 | | `Content-Type` | string | 是 | 固定为 `application/json`。 | 41 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 42 | 43 | ## 请求体 44 | 45 | | 参数名 | 类型 | 是否必需 | 说明 | 46 | | :--- | :--- | :--- | :--- | 47 | | `prompt` | string | 是 | 指导生成所需的提示词文本。范围: `1 <= x <= 2000`。 | 48 | | `image` | string | 是 | 用于视频生成的图片。支持公网 URL 或 Base64 编码(如 `data:image/jpeg;base64,...`)。 | 49 | | `duration` | integer | 否 | 生成视频的时长(秒)。
**默认值:** `6`
**可选值:** `6`、`10` | 50 | | `resolution` | string | 否 | 生成视频的分辨率。
**默认值:** `768P`
**注意:**
- 6 秒视频支持:`768P`、`1080P`
- 10 秒视频仅支持:`768P` | 51 | | `enable_prompt_expansion` | boolean | 否 | 是否启用提示词优化。
**默认值:** `true`。 | 52 | 53 | ## 响应 54 | 55 | | 参数名 | 类型 | 是否必需 | 说明 | 56 | | :--- | :--- | :--- | :--- | 57 | | `task_id` | string | 是 | 异步任务的 ID。您需要使用此 ID 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果。 | -------------------------------------------------------------------------------- /src/adapters/kie/parsers/imageParser.ts: -------------------------------------------------------------------------------- 1 | import { ImageResult } from '@/adapters/base/BaseAdapter' 2 | import type { KIEAdapter } from '../KIEAdapter' 3 | 4 | /** 5 | * 解析 KIE 图片响应 6 | * @param responseData - KIE API 返回的 resultJson 解析后的数据 7 | * @param adapter - KIEAdapter 实例 8 | */ 9 | export const parseImageResponse = async ( 10 | responseData: any, 11 | adapter: KIEAdapter 12 | ): Promise => { 13 | // KIE 返回格式: { resultUrls: ["url1", "url2", ...] } 14 | if (responseData.resultUrls && Array.isArray(responseData.resultUrls)) { 15 | const urls = responseData.resultUrls 16 | 17 | if (urls.length === 0) { 18 | throw new Error('API 未返回任何图片') 19 | } 20 | 21 | // 保存所有图片到本地 22 | try { 23 | const savedResults = await Promise.all( 24 | urls.map((url: string) => adapter['saveMediaLocally'](url, 'image')) 25 | ) 26 | 27 | // 如果是单图,返回单个结果 28 | if (savedResults.length === 1) { 29 | return { 30 | url: savedResults[0].url, 31 | filePath: savedResults[0].filePath, 32 | status: 'completed' 33 | } 34 | } 35 | 36 | // 如果是多图,用 ||| 分隔 URL 和 filePath 37 | const combinedUrls = savedResults.map(r => r.url).join('|||') 38 | const combinedPaths = savedResults.map(r => r.filePath).join('|||') 39 | 40 | return { 41 | url: combinedUrls, 42 | filePath: combinedPaths, 43 | status: 'completed' 44 | } 45 | } catch (e) { 46 | adapter['log']('图片本地保存失败,回退为远程 URL', e) 47 | 48 | // 回退:使用远程 URL 49 | if (urls.length === 1) { 50 | return { 51 | url: urls[0], 52 | status: 'completed' 53 | } 54 | } 55 | 56 | return { 57 | url: urls.join('|||'), 58 | status: 'completed' 59 | } 60 | } 61 | } 62 | 63 | throw new Error('API 未返回图片 URL') 64 | } 65 | -------------------------------------------------------------------------------- /src/adapters/ppio/models/wan.ts: -------------------------------------------------------------------------------- 1 | import { GenerateVideoParams } from '@/adapters/base/BaseAdapter' 2 | 3 | /** 4 | * Wan 2.5 Preview 模型路由 5 | */ 6 | export const wan25PreviewRoute = { 7 | // 模型ID识别 8 | matches: (modelId: string) => modelId === 'wan-2.5-preview', 9 | 10 | // 构建视频生成请求 11 | buildVideoRequest: (params: GenerateVideoParams) => { 12 | const images = params.images || [] 13 | const duration = params.duration || 5 14 | const prompt_extend = params.promptExtend === undefined ? true : params.promptExtend 15 | const audio = params.audio === undefined ? true : params.audio 16 | 17 | let endpoint: string 18 | let requestData: any 19 | 20 | if (images.length > 0) { 21 | // 图生视频 22 | endpoint = '/async/wan-2.5-i2v-preview' 23 | const img0 = images[0] 24 | const imgUrl = typeof img0 === 'string' 25 | ? (img0.startsWith('data:') ? img0 : `data:image/jpeg;base64,${img0}`) 26 | : img0 27 | requestData = { 28 | input: { 29 | prompt: params.prompt, 30 | negative_prompt: params.negativePrompt, 31 | img_url: imgUrl 32 | }, 33 | parameters: { 34 | resolution: (params.resolution || '1080P'), 35 | duration, 36 | prompt_extend, 37 | watermark: false, 38 | audio 39 | } 40 | } 41 | } else { 42 | // 文生视频 43 | endpoint = '/async/wan-2.5-t2v-preview' 44 | requestData = { 45 | input: { 46 | prompt: params.prompt, 47 | negative_prompt: params.negativePrompt 48 | }, 49 | parameters: { 50 | size: params.size || '1920*1080', 51 | duration, 52 | prompt_extend, 53 | watermark: false, 54 | audio 55 | } 56 | } 57 | } 58 | 59 | return { endpoint, requestData } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/models/fal-ai-nano-banana.ts: -------------------------------------------------------------------------------- 1 | import { ParamDef } from '../types/schema' 2 | 3 | /** 4 | * Fal.ai Nano Banana 模型参数定义 5 | */ 6 | export const falAiNanoBananaParams: ParamDef[] = [ 7 | { 8 | id: 'falNanoBananaNum_images', 9 | type: 'number', 10 | label: '数量', 11 | min: 1, 12 | max: 4, 13 | step: 1, 14 | widthClassName: 'w-20' 15 | }, 16 | { 17 | id: 'falNanoBananaAspectRatio', 18 | type: 'dropdown', 19 | label: '分辨率', 20 | defaultValue: '1:1', // 文生图默认 1:1 21 | // 分辨率配置:启用智能匹配和可视化 22 | resolutionConfig: { 23 | type: 'aspect_ratio', 24 | smartMatch: true, 25 | visualize: true, 26 | extractRatio: (value) => { 27 | if (value === 'smart') return null 28 | const [w, h] = value.split(':').map(Number) 29 | return w / h 30 | } 31 | }, 32 | // 当上传图片时自动切换到智能选项 33 | autoSwitch: { 34 | condition: (values) => values.uploadedImages && values.uploadedImages.length > 0, 35 | value: 'smart', 36 | watchKeys: ['uploadedImages'] // 只监听图片数量变化,避免用户手动选择比例时被强制切换 37 | }, 38 | // 始终显示智能选项 39 | options: [ 40 | { value: 'smart', label: '智能' }, 41 | { value: '1:1', label: '1:1' }, 42 | { value: '16:9', label: '16:9' }, 43 | { value: '9:16', label: '9:16' }, 44 | { value: '21:9', label: '21:9' }, 45 | { value: '3:2', label: '3:2' }, 46 | { value: '2:3', label: '2:3' }, 47 | { value: '4:3', label: '4:3' }, 48 | { value: '3:4', label: '3:4' }, 49 | { value: '5:4', label: '5:4' }, 50 | { value: '4:5', label: '4:5' } 51 | ], 52 | className: 'min-w-[100px]' 53 | } 54 | ] 55 | -------------------------------------------------------------------------------- /src/adapters/ppio/models/pixverse.ts: -------------------------------------------------------------------------------- 1 | import { GenerateVideoParams } from '@/adapters/base/BaseAdapter' 2 | 3 | /** 4 | * 规范化 PixVerse 分辨率 5 | */ 6 | function normalizePixverseResolution(resolution?: string): string { 7 | const s = (resolution || '').toLowerCase() 8 | const allowed = ['360p', '540p', '720p', '1080p'] 9 | return allowed.includes(s) ? s : '540p' 10 | } 11 | 12 | /** 13 | * PixVerse V4.5 模型路由 14 | */ 15 | export const pixverseV45Route = { 16 | // 模型ID识别 17 | matches: (modelId: string) => modelId === 'pixverse-v4.5', 18 | 19 | // 构建视频生成请求 20 | buildVideoRequest: (params: GenerateVideoParams) => { 21 | const images = params.images || [] 22 | const res = normalizePixverseResolution(params.resolution) 23 | const ar = params.aspectRatio || '16:9' 24 | const fast = params.fastMode || false 25 | 26 | let endpoint: string 27 | let requestData: any 28 | 29 | if (images.length > 0) { 30 | // 图生视频 31 | endpoint = '/async/pixverse-v4.5-i2v' 32 | const img0 = images[0] 33 | const base64 = typeof img0 === 'string' && img0.startsWith('data:') ? img0.split(',')[1] : img0 34 | // fast_mode 不支持 1080p 35 | const finalRes = fast && res === '1080p' ? '720p' : res 36 | requestData = { 37 | prompt: params.prompt, 38 | image: base64, 39 | resolution: finalRes, 40 | negative_prompt: params.negativePrompt, 41 | fast_mode: fast 42 | } 43 | } else { 44 | // 文生视频 45 | endpoint = '/async/pixverse-v4.5-t2v' 46 | const finalRes = fast && res === '1080p' ? '720p' : res 47 | requestData = { 48 | prompt: params.prompt, 49 | aspect_ratio: ar, 50 | resolution: finalRes, 51 | negative_prompt: params.negativePrompt, 52 | fast_mode: fast 53 | } 54 | } 55 | 56 | return { endpoint, requestData } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/models/fal-ai-kling-video-v2.6-pro.ts: -------------------------------------------------------------------------------- 1 | import { ParamDef } from '../types/schema' 2 | 3 | /** 4 | * Kling Video v2.6 Pro 参数定义 5 | * 支持文生视频和图生视频两种模式 6 | * 特性:原生音频生成、CFG Scale 调节 7 | */ 8 | export const falAiKlingVideoV26ProParams: ParamDef[] = [ 9 | // 时长 10 | { 11 | id: 'falKlingV26ProVideoDuration', 12 | type: 'dropdown', 13 | label: '时长', 14 | defaultValue: 5, 15 | options: [ 16 | { value: 5, label: '5s' }, 17 | { value: 10, label: '10s' } 18 | ] 19 | }, 20 | 21 | // 宽高比(仅文生视频显示) 22 | { 23 | id: 'falKlingV26ProAspectRatio', 24 | type: 'dropdown', 25 | label: '比例', 26 | defaultValue: '16:9', 27 | resolutionConfig: { 28 | type: 'aspect_ratio', 29 | smartMatch: false, // 无需智能选型 30 | visualize: true, 31 | extractRatio: (value) => { 32 | const [w, h] = value.split(':').map(Number) 33 | return w / h 34 | } 35 | }, 36 | options: [ 37 | { value: '16:9', label: '16:9' }, 38 | { value: '9:16', label: '9:16' }, 39 | { value: '1:1', label: '1:1' } 40 | ], 41 | hidden: (values) => { 42 | // 图生视频模式不支持宽高比参数(由输入图片决定) 43 | return values.uploadedImages && values.uploadedImages.length > 0 44 | } 45 | }, 46 | 47 | // CFG Scale(仅文生视频显示) 48 | { 49 | id: 'falKlingV26ProCfgScale', 50 | type: 'number', 51 | label: 'CFG Scale', 52 | defaultValue: 0.5, 53 | min: 0, 54 | max: 1, 55 | step: 0.1, 56 | precision: 1, 57 | description: '控制模型对提示词的遵循程度', 58 | hidden: (values) => { 59 | // 图生视频模式不支持 CFG Scale 60 | return values.uploadedImages && values.uploadedImages.length > 0 61 | } 62 | }, 63 | 64 | // 音频生成 65 | { 66 | id: 'falKlingV26ProGenerateAudio', 67 | type: 'toggle', 68 | label: '生成音频', 69 | defaultValue: true, 70 | description: '支持中英文语音输出,其他语言自动翻译为英文' 71 | } 72 | ] 73 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/视频/Kling_V2.5_Turbo_文生视频.md: -------------------------------------------------------------------------------- 1 | # Kling V2.5 Turbo 文生视频 2 | 3 | Kling 2.5 Turbo 是一款先进的文本生成视频模型,能够生成超流畅的动作、电影级画面,并高度贴合提示词内容。 4 | 5 | 这是一个**异步**API,只会返回异步任务的 `task_id`。您应该使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来检索视频生成结果。 6 | 7 | ## 请求 8 | 9 | **端点** 10 | ``` 11 | POST https://api.ppinfra.com/v3/async/kling-2.5-turbo-t2v 12 | ``` 13 | 14 | **cURL 示例** 15 | ```bash 16 | curl --request POST \ 17 | --url https://api.ppinfra.com/v3/async/kling-2.5-turbo-t2v \ 18 | --header 'Authorization: ' \ 19 | --header 'Content-Type: application/json' \ 20 | --data ' 21 | { 22 | "prompt": "", 23 | "duration": "", 24 | "aspect_ratio": "", 25 | "cfg_scale": 123, 26 | "mode": "", 27 | "negative_prompt": "" 28 | } 29 | ' 30 | ``` 31 | 32 | ## 请求头 33 | 34 | | 参数名 | 类型 | 必填 | 说明 | 35 | | :--- | :--- | :--- | :--- | 36 | | `Content-Type` | string | 是 | 固定为 `application/json`。 | 37 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 38 | 39 | ## 请求体 40 | 41 | | 参数名 | 类型 | 必填 | 默认值 | 说明 | 42 | | :--- | :--- | :--- | :--- | :--- | 43 | | `prompt` | string | 是 | - | 指导生成的正向文本提示词。长度不超过 2500 字符。 | 44 | | `duration` | string | 否 | `"5"` | 生成视频的时长(秒)。可选值:`"5"`, `"10"`。 | 45 | | `aspect_ratio` | string | 否 | `"16:9"` | 输出视频的宽高比。可选值:`"16:9"`, `"9:16"`, `"1:1"`。 | 46 | | `cfg_scale` | number | 否 | `0.5` | 控制视频生成的灵活性,数值越高,模型生成内容对提示词的贴合度越高,创意自由度越低。取值范围:0 到 1。 | 47 | | `mode` | string | 否 | `"pro"` | 视频生成模式。当前可选值:`"pro"`(专业模式)。 | 48 | | `negative_prompt` | string | 否 | - | 反向提示词,用于规避不希望出现的内容;长度不超过 2500 字符。 | 49 | 50 | ## 响应 51 | 52 | **响应示例** 53 | ```json 54 | { 55 | "task_id": "" 56 | } 57 | ``` 58 | 59 | | 参数名 | 类型 | 必填 | 说明 | 60 | | :--- | :--- | :--- | :--- | 61 | | `task_id` | string | 是 | 异步任务的 ID。您应该使用该 ID 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果。 | -------------------------------------------------------------------------------- /src/adapters/ppio/models/kling-2.5-turbo.ts: -------------------------------------------------------------------------------- 1 | import { GenerateVideoParams } from '@/adapters/base/BaseAdapter' 2 | 3 | /** 4 | * 可灵 2.5 Turbo 模型路由 5 | */ 6 | export const klingTurbo25Route = { 7 | // 模型ID识别 8 | matches: (modelId: string) => modelId === 'kling-2.5-turbo', 9 | 10 | // 构建视频生成请求 11 | buildVideoRequest: (params: GenerateVideoParams) => { 12 | const images = params.images || [] 13 | const cfgScale = typeof params.cfgScale === 'number' ? Math.max(0, Math.min(1, params.cfgScale)) : 0.5 14 | const duration = params.duration === 10 ? 10 : 5 15 | const prompt = (params.prompt || '').slice(0, 2500) 16 | const negative_prompt = params.negativePrompt ? params.negativePrompt.slice(0, 2500) : undefined 17 | const ar = ['16:9', '9:16', '1:1'].includes(params.aspectRatio || '') ? (params.aspectRatio as string) : '16:9' 18 | 19 | if (!prompt || prompt.trim() === '') { 20 | throw new Error('Kling 文生视频需要提供非空的 prompt') 21 | } 22 | 23 | let endpoint: string 24 | let requestData: any 25 | 26 | if (images.length > 0) { 27 | // 图生视频 28 | endpoint = '/async/kling-2.5-turbo-i2v' 29 | const img0 = images[0] 30 | const base64 = typeof img0 === 'string' && img0.startsWith('data:') ? img0.split(',')[1] : img0 31 | requestData = { 32 | image: base64, 33 | prompt, 34 | duration: String(duration), 35 | cfg_scale: cfgScale, 36 | mode: params.mode || 'pro', 37 | negative_prompt 38 | } 39 | } else { 40 | // 文生视频 41 | endpoint = '/async/kling-2.5-turbo-t2v' 42 | requestData = { 43 | prompt, 44 | duration: String(duration), 45 | aspect_ratio: ar, 46 | cfg_scale: cfgScale, 47 | mode: params.mode || 'pro', 48 | negative_prompt 49 | } 50 | } 51 | 52 | return { endpoint, requestData } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .qoder/ 2 | .trae/ 3 | .claude/ 4 | .cargo/ 5 | docs/GITHUB_ACTIONS_GUIDE.md 6 | # Dependencies 7 | node_modules/ 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | 12 | # Build outputs 13 | dist/ 14 | build/ 15 | .vite/ 16 | *.tgz 17 | *.tar.gz 18 | 19 | # Environment variables 20 | .env 21 | .env.local 22 | .env.development.local 23 | .env.test.local 24 | .env.production.local 25 | 26 | # IDE and editor files 27 | .vscode/ 28 | .idea/ 29 | *.swp 30 | *.swo 31 | *~ 32 | 33 | # OS generated files 34 | .DS_Store 35 | .DS_Store? 36 | ._* 37 | .Spotlight-V100 38 | .Trashes 39 | ehthumbs.db 40 | Thumbs.db 41 | 42 | # Logs 43 | logs 44 | *.log 45 | 46 | # Runtime data 47 | pids 48 | *.pid 49 | *.seed 50 | *.pid.lock 51 | 52 | # Coverage directory used by tools like istanbul 53 | coverage/ 54 | .nyc_output/ 55 | 56 | # Dependency directories 57 | jspm_packages/ 58 | 59 | # Optional npm cache directory 60 | .npm 61 | 62 | # Optional eslint cache 63 | .eslintcache 64 | 65 | # Microbundle cache 66 | .rpt2_cache/ 67 | .rts2_cache_cjs/ 68 | .rts2_cache_es/ 69 | .rts2_cache_umd/ 70 | 71 | # Optional REPL history 72 | .node_repl_history 73 | 74 | # Output of 'npm pack' 75 | *.tgz 76 | *.tar.gz 77 | 78 | # Yarn Integrity file 79 | .yarn-integrity 80 | 81 | # parcel-bundler cache (https://parceljs.org/) 82 | .cache 83 | .parcel-cache 84 | 85 | # next.js build output 86 | .next 87 | 88 | # nuxt.js build output 89 | .nuxt 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | 106 | # Vite specific 107 | *.local 108 | 109 | # TypeScript cache 110 | *.tsbuildinfo 111 | src-tauri/target/ 112 | src-tauri/gen/ 113 | nul 114 | -------------------------------------------------------------------------------- /src-tauri/src/main.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(target_os = "windows", windows_subsystem = "windows")] 2 | 3 | mod modelscope; 4 | mod clipboard_files; 5 | 6 | use tauri::Manager; 7 | 8 | /// 切换开发者工具的显示状态 9 | #[tauri::command] 10 | fn toggle_devtools(app: tauri::AppHandle) { 11 | if let Some(window) = app.get_webview_window("main") { 12 | // Tauri v2 中直接调用 open_devtools() 13 | // 如果已经打开,再次调用会关闭(toggle 行为) 14 | window.open_devtools(); 15 | } 16 | } 17 | 18 | #[cfg_attr(mobile, tauri::mobile_entry_point)] 19 | pub fn run() { 20 | tauri::Builder::default() 21 | .plugin(tauri_plugin_fs::init()) 22 | .plugin(tauri_plugin_dialog::init()) 23 | .plugin(tauri_plugin_http::init()) 24 | .plugin(tauri_plugin_shell::init()) 25 | .plugin(tauri_plugin_clipboard_manager::init()) 26 | .invoke_handler(tauri::generate_handler![ 27 | modelscope::modelscope_submit_task, 28 | modelscope::modelscope_check_status, 29 | toggle_devtools, 30 | clipboard_files::read_clipboard_files 31 | ]) 32 | .setup(|app| { 33 | let app_local = app.path().app_local_data_dir().expect("get app local data dir"); 34 | let media_dir = app_local.join("Henji-AI").join("Media"); 35 | if let Err(e) = std::fs::create_dir_all(&media_dir) { 36 | eprintln!("failed to create media dir: {}", e); 37 | } 38 | 39 | if let Some(win) = app.get_webview_window("main") { 40 | // 先最大化窗口,然后显示,避免看到小窗口 41 | let _ = win.maximize(); 42 | 43 | // 延迟显示窗口,确保内容加载完成 44 | let window = win.clone(); 45 | std::thread::spawn(move || { 46 | std::thread::sleep(std::time::Duration::from_millis(100)); 47 | let _ = window.show(); 48 | }); 49 | } 50 | 51 | Ok(()) 52 | }) 53 | .run(tauri::generate_context!()) 54 | .expect("error while running tauri application"); 55 | } 56 | 57 | fn main() { 58 | run(); 59 | } 60 | -------------------------------------------------------------------------------- /src/adapters/ppio/models/minimax-hailuo-2.3.ts: -------------------------------------------------------------------------------- 1 | import { GenerateVideoParams } from '@/adapters/base/BaseAdapter' 2 | 3 | /** 4 | * 规范化海螺参数 5 | */ 6 | function normalizeHailuo(duration?: number, resolution?: string): { duration: number; resolution: string } { 7 | const d = duration === 10 ? 10 : 6 8 | const rInput = (resolution || '').toUpperCase() 9 | const r = d === 10 ? '768P' : (rInput === '1080P' ? '1080P' : '768P') 10 | return { duration: d, resolution: r } 11 | } 12 | 13 | /** 14 | * 海螺 2.3 模型路由 15 | */ 16 | export const minimaxHailuo23Route = { 17 | // 模型ID识别 18 | matches: (modelId: string) => 19 | modelId === 'minimax-hailuo-2.3' || 20 | modelId === 'minimax-hailuo-2.3-fast', 21 | 22 | // 构建视频生成请求 23 | buildVideoRequest: (params: GenerateVideoParams) => { 24 | const images = params.images || [] 25 | const { duration: baseDuration, resolution: baseResolution } = normalizeHailuo(params.duration, params.resolution) 26 | const enable = params.promptExtend === undefined ? true : params.promptExtend 27 | 28 | const isFast = (params.model === 'minimax-hailuo-2.3-fast') || (!!(params as any).hailuoFast && images.length > 0) 29 | 30 | let endpoint: string 31 | let requestData: any 32 | 33 | if (images.length > 0) { 34 | endpoint = isFast ? '/async/minimax-hailuo-2.3-fast-i2v' : '/async/minimax-hailuo-2.3-i2v' 35 | requestData = { 36 | prompt: params.prompt, 37 | image: images[0], 38 | duration: baseDuration, 39 | resolution: baseResolution, 40 | enable_prompt_expansion: enable 41 | } 42 | } else { 43 | endpoint = '/async/minimax-hailuo-2.3-t2v' 44 | requestData = { 45 | prompt: params.prompt, 46 | duration: baseDuration, 47 | resolution: baseResolution, 48 | enable_prompt_expansion: enable 49 | } 50 | } 51 | 52 | return { endpoint, requestData } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/视频/Kling_V2.5_Turbo_图生视频.md: -------------------------------------------------------------------------------- 1 | # Kling V2.5 Turbo 图生视频 2 | 3 | Kling 2.5 Turbo 图生视频可以将单张图片和提示词生成具有电影感的视频,动作流畅、内容高度贴合所需意图。全新的文本-时序引擎、增强的运动表现和更快的推理速度。 4 | 5 | 这是一个**异步**API,只会返回异步任务的 `task_id`。您应该使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来检索视频生成结果。 6 | 7 | ## 接口调用 8 | 9 | **请求方法**: POST 10 | **请求地址**: `https://api.ppinfra.com/v3/async/kling-2.5-turbo-i2v` 11 | 12 | ### 请求示例 13 | 14 | ```bash 15 | curl --request POST \ 16 | --url https://api.ppinfra.com/v3/async/kling-2.5-turbo-i2v \ 17 | --header 'Authorization: ' \ 18 | --header 'Content-Type: ' \ 19 | --data ' 20 | { 21 | "image": "", 22 | "prompt": "", 23 | "duration": "", 24 | "cfg_scale": 123, 25 | "mode": "", 26 | "negative_prompt": "" 27 | } 28 | ' 29 | ``` 30 | 31 | ### 响应示例 32 | 33 | ```json 34 | { 35 | "task_id": "" 36 | } 37 | ``` 38 | 39 | ## 请求头 40 | 41 | | 参数名 | 类型 | 必填 | 说明 | 42 | | :--- | :--- | :--- | :--- | 43 | | `Content-Type` | string | 是 | 固定为 `application/json`。 | 44 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 45 | 46 | ## 请求体 47 | 48 | | 参数名 | 类型 | 必填 | 默认值 | 说明 | 49 | | :--- | :--- | :--- | :--- | :--- | 50 | | `image` | string | 是 | - | 视频的首帧图片。支持的图片格式包括 `.jpg`、`.jpeg`、`.png`;图片文件大小不得超过 10MB,分辨率不小于 300*300 像素。 | 51 | | `prompt` | string | 是 | - | 生成视频的正向提示词文本;不可超过 2500 个字符。 | 52 | | `duration` | string | 否 | `"5"` | 生成视频的时长(单位:秒)。可选值:`5`、`10` | 53 | | `cfg_scale` | number | 否 | 0.5 | 控制视频生成的灵活性,数值越高,模型生成内容对提示词的贴合度越高,创意自由度越低。取值范围:0 到 1。 | 54 | | `mode` | string | 否 | `"pro"` | 视频生成模式。当前可选值:`pro`(专业模式)。 | 55 | | `negative_prompt` | string | 否 | - | 反向提示词,用于规避不希望出现的内容;长度不超过 2500 字符。 | 56 | 57 | ## 响应 58 | 59 | | 参数名 | 类型 | 必填 | 说明 | 60 | | :--- | :--- | :--- | :--- | 61 | | `task_id` | string | 是 | 异步任务的 `task_id`。您应该使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果。 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/基础/API_错误码说明.md: -------------------------------------------------------------------------------- 1 | # API 错误码说明 2 | 3 | ## 图片 / 视频 / 音频 4 | 5 | | 错误名称 | 状态码 | 说明 | 6 | | --- | --- | --- | 7 | | INVALID_REQUEST_BODY | 400 | 请求参数校验失败 | 8 | | IMAGE_FILE_EXCEEDS_MAX_SIZE | 400 | 图片大小超出限制 | 9 | | INVALID_IMAGE_FORMAT | 400 | 图片格式与要求不符 | 10 | | IMAGE_EXCEEDS_MAX_RESOLUTION | 400 | 图片分辨率超出限制 | 11 | | INVALID_IMAGE_SIZE | 400 | 图片长或宽超出限制 | 12 | | IMAGE_NO_FACE_DETECTED | 400 | 未检测到人脸 | 13 | | INVALID_CUSTOM_OUTPUT_PATH | 400 | OSS 路径不合法 | 14 | | ILLEGAL_PROMPT | 400 | Prompt 含不适宜内容 | 15 | | ILLEGAL_IMAGE_CONTENT | 400 | 图片含不适宜内容 | 16 | | INVALID_AUDIO_FILE | 400 | 输入音频不合法 | 17 | | API_NOT_FOUND | 404 | API 不存在 | 18 | | MISSING_API_KEY | 400 | 未提供 API Key | 19 | | INVALID_API_KEY | 403 | API Key 校验失败 | 20 | | FEATURE_NOT_ALLOWED | 403 | 没有模型上传权限 | 21 | | API_NOT_ALLOWED | 403 | 无权限使用该 API | 22 | | NEED_REAL_NAME_VERIFY | 403 | 未完成企业认证 | 23 | | RATE_LIMIT_EXCEEDED | 429 | 触发频率控制限制 | 24 | | BILLING_BALANCE_NOT_ENOUGH | 400 | 余额不足 | 25 | | BILLING_AUTH_FAILED | 403 | 计费服务鉴权失败 | 26 | | BILLING_FAILED | 500 | 计费服务异常 | 27 | | CREATE_TASK_FAILED | 500 | 创建任务失败 | 28 | | TASK_NOT_FOUND | 404 | 任务不存在 | 29 | | GET_RESULT_FAILED | 500 | 获取任务结果失败 | 30 | | TASK_FAILED | 500 | 任务执行失败 | 31 | 32 | ## 大语言 33 | 34 | | 错误名称 | 状态码 | 说明 | 35 | | --- | --- | --- | 36 | | INVALID_API_KEY | 403 | 未提供 API Key | 37 | | FAILED_TO_AUTH | 401 | 认证失败 | 38 | | ACCESS_DENY | 403 | 无权限访问 | 39 | | NOT_ENOUGH_BALANCE | 403 | 余额不足 | 40 | | INVALID_REQUEST_BODY | 400 | 请求体格式错误,详见 message | 41 | | MODEL_NOT_FOUND | 404 | 模型不存在 | 42 | | RATE_LIMIT_EXCEEDED | 429 | 请求过快,请稍后重试 | 43 | | TOKEN_LIMIT_EXCEEDED | 429 | Token 数超限,请稍后重试 | 44 | | SERVICE_NOT_AVAILABLE | 503 | 服务不可用 | 45 | 46 | ## 账单 47 | 48 | | 错误名称 | 状态码 | 说明 | 49 | | --- | --- | --- | 50 | | LIST_BILL_TOO_FAST | 429 | 请求过于频繁,请稍后重试 | 51 | | INVALID_PRODUCT_CATEGORY | 400 | productCategory 参数错误 | 52 | | INVALID_BILL_CYCLE | 400 | cycle 参数错误 | 53 | | LIST_BILL_ERROR | 500 | 查询错误,请联系我们 | 54 | | UNKNOWN | 500 | 未知错误,请联系我们 | -------------------------------------------------------------------------------- /src/components/TestModeIndicator.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * 测试模式指示器 3 | * 显示在窗口右上角,提示当前处于测试模式 4 | */ 5 | 6 | import React, { useState, useEffect } from 'react' 7 | import { isTestModeEnabled } from '@/utils/testMode' 8 | 9 | interface TestModeIndicatorProps { 10 | onOpenPanel: () => void 11 | } 12 | 13 | const TestModeIndicator: React.FC = ({ onOpenPanel }) => { 14 | const [enabled, setEnabled] = useState(false) 15 | 16 | useEffect(() => { 17 | // 初始化状态 18 | setEnabled(isTestModeEnabled()) 19 | 20 | // 监听测试模式变化 21 | const handleTestModeChange = (event: CustomEvent) => { 22 | setEnabled(event.detail.enabled) 23 | } 24 | 25 | window.addEventListener('test-mode-changed', handleTestModeChange as EventListener) 26 | 27 | return () => { 28 | window.removeEventListener('test-mode-changed', handleTestModeChange as EventListener) 29 | } 30 | }, []) 31 | 32 | if (!enabled) return null 33 | 34 | return ( 35 |
40 | 47 | 53 | 54 | 测试模式 55 |
56 | ) 57 | } 58 | 59 | export default TestModeIndicator 60 | -------------------------------------------------------------------------------- /src/adapters/ppio/models/minimax-hailuo-02.ts: -------------------------------------------------------------------------------- 1 | import { GenerateVideoParams } from '@/adapters/base/BaseAdapter' 2 | 3 | /** 4 | * 规范化海螺参数 5 | */ 6 | function normalizeHailuo(duration?: number, resolution?: string): { duration: number; resolution: string } { 7 | const d = duration === 10 ? 10 : 6 8 | const rInput = (resolution || '').toUpperCase() 9 | const r = d === 10 ? '768P' : (rInput === '1080P' ? '1080P' : '768P') 10 | return { duration: d, resolution: r } 11 | } 12 | 13 | /** 14 | * 海螺 02 模型路由 15 | */ 16 | export const minimaxHailuo02Route = { 17 | // 模型ID识别 18 | matches: (modelId: string) => modelId === 'minimax-hailuo-02', 19 | 20 | // 构建视频生成请求 21 | buildVideoRequest: (params: GenerateVideoParams) => { 22 | const images = params.images || [] 23 | const { duration: baseDuration, resolution: baseResolution } = normalizeHailuo(params.duration, params.resolution) 24 | const enable = params.promptExtend === undefined ? true : params.promptExtend 25 | 26 | const endpoint = '/async/minimax-hailuo-02' 27 | let requestData: any 28 | 29 | if (images.length >= 2) { 30 | // 首尾帧模式 31 | requestData = { 32 | prompt: params.prompt, 33 | image: images[0], 34 | end_image: images[1], 35 | duration: baseDuration, 36 | resolution: baseResolution, 37 | enable_prompt_expansion: enable 38 | } 39 | } else if (images.length === 1) { 40 | // 单图模式 41 | requestData = { 42 | prompt: params.prompt, 43 | image: images[0], 44 | duration: baseDuration, 45 | resolution: baseResolution, 46 | enable_prompt_expansion: enable 47 | } 48 | } else { 49 | // 文生视频模式 50 | requestData = { 51 | prompt: params.prompt, 52 | duration: baseDuration, 53 | resolution: baseResolution, 54 | enable_prompt_expansion: enable 55 | } 56 | } 57 | 58 | return { endpoint, requestData } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/视频/Kling-o1_参考生视频.md: -------------------------------------------------------------------------------- 1 | # Kling-o1 参考生视频 2 | 3 | Kling Omni Video O1 参考视频生成功能,可利用角色、道具或场景参考,从多个视角生成创意视频。它提取主体特征并创建新的视频内容,同时保持帧与帧之间的一致性。 4 | 5 | 这是一个**异步**API,只会返回异步任务的 `task_id`。您应该使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来检索视频生成结果。 6 | 7 | ## 接口信息 8 | 9 | **请求方法:** POST 10 | **请求地址:** `https://api.ppinfra.com/v3/async/kling-o1-ref2v` 11 | 12 | ## 请求示例 13 | 14 | ```bash 15 | curl --request POST \ 16 | --url https://api.ppinfra.com/v3/async/kling-o1-ref2v \ 17 | --header 'Authorization: ' \ 18 | --header 'Content-Type: application/json' \ 19 | --data ' 20 | { 21 | "video": "", 22 | "images": [ 23 | {} 24 | ], 25 | "prompt": "", 26 | "duration": 123, 27 | "aspect_ratio": "", 28 | "keep_original_sound": true 29 | } 30 | ' 31 | ``` 32 | 33 | ## 响应示例 34 | 35 | ```json 36 | { 37 | "task_id": "" 38 | } 39 | ``` 40 | 41 | ## 请求头 42 | 43 | | 参数 | 类型 | 必填 | 说明 | 44 | | :--- | :--- | :--- | :--- | 45 | | `Content-Type` | string | 是 | 固定值:`application/json` | 46 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}` | 47 | 48 | ## 请求体 49 | 50 | | 参数 | 类型 | 必填 | 默认值 | 说明 | 51 | | :--- | :--- | :--- | :--- | :--- | 52 | | `video` | string | 是 | - | 参考视频的URL | 53 | | `images` | array | 否 | `[]` | 包含元素、场景、风格等的参考图片数组。最多7张,数组长度:0 - 7 | 54 | | `prompt` | string | 是 | - | 正向提示词 | 55 | | `duration` | integer | 否 | `5` | 生成媒体的持续时间(秒)。可选值:`3`, `4`, `5`, `6`, `7`, `8`, `9`, `10` | 56 | | `aspect_ratio` | string | 否 | `"16:9"` | 生成视频的宽高比。可选值:`16:9`, `9:16`, `1:1` | 57 | | `keep_original_sound` | boolean | 否 | `true` | 选择是否通过参数保留视频原始声音 | 58 | 59 | ## 响应参数 60 | 61 | | 参数 | 类型 | 必填 | 说明 | 62 | | :--- | :--- | :--- | :--- | 63 | | `task_id` | string | 是 | 异步任务的 task_id。您应该使用该 task_id 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果 | 64 | 65 | [Kling-o1 图生视频](/docs/models/reference-kling-o1-i2v) [Kling-o1 文生视频](/docs/models/reference-kling-o1-t2v) -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/视频/PixVerse_V4.5_文生视频.md: -------------------------------------------------------------------------------- 1 | # PixVerse V4.5 文生视频 2 | 3 | 使用 PixVerse 最新的 v4.5 模型从文本描述生成高质量视频。支持多种分辨率、纵横比和风格预设,以实现多样化的视频创作。 4 | 5 | 这是一个**异步** API,调用后返回异步任务的 `task_id`。您需要使用该 `task_id` 调用 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来获取视频生成结果。 6 | 7 | ## 请求示例 8 | 9 | **请求** 10 | ```bash 11 | curl --request POST \ 12 | --url https://api.ppinfra.com/v3/async/pixverse-v4.5-t2v \ 13 | --header 'Authorization: ' \ 14 | --header 'Content-Type: application/json' \ 15 | --data ' 16 | { 17 | "prompt": "", 18 | "aspect_ratio": "", 19 | "resolution": "", 20 | "negative_prompt": "", 21 | "fast_mode": true, 22 | "style": "", 23 | "seed": 123 24 | } 25 | ' 26 | ``` 27 | 28 | **响应** 29 | ```json 30 | { 31 | "task_id": "" 32 | } 33 | ``` 34 | 35 | ## 请求头 36 | 37 | | 参数名 | 类型 | 是否必需 | 描述 | 38 | | :--- | :--- | :--- | :--- | 39 | | `Content-Type` | string | 是 | 必须为 `application/json`。 | 40 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 41 | 42 | ## 请求体 43 | 44 | | 参数名 | 类型 | 是否必需 | 描述 | 45 | | :--- | :--- | :--- | :--- | 46 | | `prompt` | string | 是 | 视频生成的文本提示。最大长度:2048 个字符。建议清晰描述所需场景和动作。 | 47 | | `aspect_ratio` | string | 是 | 视频的宽高比。默认值:`16:9`。
可接受的值:`16:9`、`4:3`、`1:1`、`3:4`、`9:16`。 | 48 | | `resolution` | string | 是 | 视频质量。默认值:`540p`。
可接受的值:
- 当 `fast_mode` 为 `false` 时:`360p`、`540p`、`720p`、`1080p`。
- 当 `fast_mode` 为 `true` 时:`360p`、`540p`、`720p`。 | 49 | | `negative_prompt` | string | 否 | 生成的负面提示。最大长度:2048 个字符。 | 50 | | `fast_mode` | boolean | 否 | 是否启用快速模式。该模式将更快地生成视频,但可能降低质量并降低价格。默认值:`false`。 | 51 | | `style` | string | 否 | 风格预设(仅限 v3.5)。
可接受的值:`anime`、`3d_animation`、`clay`、`comic`、`cyberpunk`。 | 52 | | `seed` | integer | 否 | 用于生成的随机种子。 | 53 | 54 | ## 响应 55 | 56 | | 参数名 | 类型 | 是否必需 | 描述 | 57 | | :--- | :--- | :--- | :--- | 58 | | `task_id` | string | 是 | 异步任务的 ID。您应该使用此 ID 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果。 | -------------------------------------------------------------------------------- /src/adapters/ppio/models/seedance.ts: -------------------------------------------------------------------------------- 1 | import { GenerateVideoParams } from '@/adapters/base/BaseAdapter' 2 | 3 | /** 4 | * Seedance V1 模型路由 5 | */ 6 | export const seedanceV1Route = { 7 | // 模型ID识别 8 | matches: (modelId: string) => 9 | modelId === 'seedance-v1-lite' || 10 | modelId === 'seedance-v1-pro' || 11 | modelId === 'seedance-v1', 12 | 13 | // 构建视频生成请求 14 | buildVideoRequest: (params: GenerateVideoParams) => { 15 | const images = params.images || [] 16 | const resolution = params.resolution || '720p' 17 | const aspect = params.aspectRatio || '16:9' 18 | const duration = params.duration || 5 19 | const camera_fixed = params.cameraFixed || false 20 | 21 | let endpoint: string 22 | let requestData: any 23 | 24 | // 确定变体(lite 或 pro) 25 | let variant = 'lite' 26 | if (params.model === 'seedance-v1-pro') { 27 | variant = 'pro' 28 | } else if (params.model === 'seedance-v1' && (params as any).seedanceVariant) { 29 | variant = (params as any).seedanceVariant === 'pro' ? 'pro' : 'lite' 30 | } 31 | 32 | if (images.length > 0) { 33 | // 图生视频 34 | endpoint = `/async/seedance-v1-${variant}-i2v` 35 | requestData = { 36 | prompt: params.prompt, 37 | image: images[0], 38 | resolution, 39 | aspect_ratio: aspect, 40 | camera_fixed, 41 | seed: -1, 42 | duration 43 | } 44 | 45 | // 添加 last_image 参数(如果提供) 46 | if (params.lastImage || (params as any).lastImage) { 47 | requestData.last_image = params.lastImage || (params as any).lastImage 48 | } 49 | } else { 50 | // 文生视频 51 | endpoint = `/async/seedance-v1-${variant}-t2v` 52 | requestData = { 53 | prompt: params.prompt, 54 | resolution, 55 | aspect_ratio: aspect, 56 | duration, 57 | camera_fixed, 58 | seed: -1 59 | } 60 | } 61 | 62 | return { endpoint, requestData } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/视频/KLING_V1.6_图生视频.md: -------------------------------------------------------------------------------- 1 | # KLING V1.6 图生视频 2 | 3 | KLING V1.6 图生视频是快手 AI 团队开发的 AI 图像生成视频模型。它可以将图片转换为动态的 5 秒视频,支持 720p / 1080p 分辨率,具备高质量的视觉输出、增强的运动与语义理解能力。 4 | 5 | 这是一个**异步**API,只会返回异步任务的 `task_id`。您应该使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来检索视频生成结果。 6 | 7 | ## 请求示例 8 | 9 | **请求** 10 | 11 | ```bash 12 | curl --request POST \ 13 | --url https://api.ppinfra.com/v3/async/kling-v1.6-i2v \ 14 | --header 'Authorization: ' \ 15 | --header 'Content-Type: application/json' \ 16 | --data ' 17 | { 18 | "mode": "", 19 | "image_url": "", 20 | "end_image_url": "", 21 | "prompt": "", 22 | "negative_prompt": "", 23 | "duration": 123, 24 | "guidance_scale": 123 25 | } 26 | ' 27 | ``` 28 | 29 | **响应** 30 | 31 | ```json 32 | { 33 | "task_id": "" 34 | } 35 | ``` 36 | 37 | ## 请求头 38 | 39 | | 参数 | 类型 | 必填 | 说明 | 40 | | :--- | :--- | :--- | :--- | 41 | | `Content-Type` | string | 是 | 固定为 `application/json`。 | 42 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 43 | 44 | ## 请求体 45 | 46 | | 参数 | 类型 | 必填 | 说明 | 47 | | :--- | :--- | :--- | :--- | 48 | | `mode` | string | 否 | 视频生成模式。支持:
• `Standard`:快速生成,成本较低,生成 720p 视频。
• `Professional`:高质量,成本较高,生成 1080p 视频,并允许设置结束帧。
默认值:`Standard`。 | 49 | | `image_url` | string | 是 | 用于视频生成的起始帧图片的 URL。 | 50 | | `end_image_url` | string | 否 | 用于视频生成的结束帧图片的 URL。
仅当 `mode` 为 `Professional` 时可用。 | 51 | | `prompt` | string | 是 | 指导生成所需的提示词。取值范围:`1 <= x <= 2000`。 | 52 | | `negative_prompt` | string | 否 | 负面提示词,用于指示模型应避免生成的内容。取值范围:`0 <= x <= 2000`。 | 53 | | `duration` | integer | 否 | 生成视频的时长(秒)。默认值:`5`。
可选值:`5`、`10` | 54 | | `guidance_scale` | float | 否 | 指导强度参数,控制生成内容与提示词的贴合程度。取值范围:`0 <= x <= 1`。默认值:`0.5`。 | 55 | 56 | ## 返回结果 57 | 58 | | 参数 | 类型 | 必填 | 说明 | 59 | | :--- | :--- | :--- | :--- | 60 | | `task_id` | string | 是 | 异步任务的 `task_id`。您应该使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果。 | -------------------------------------------------------------------------------- /src/models/kie-seedream-4.0.ts: -------------------------------------------------------------------------------- 1 | import { ParamDef } from '../types/schema' 2 | 3 | /** 4 | * KIE Seedream 4.0 模型参数定义 5 | * 6 | * 特点: 7 | * - 使用 image_size (描述性格式) 和 image_resolution 8 | * - 质量选项:2K / 4K (不显示 1K) 9 | * - 数量参数:max_images (1-6) 10 | * - 根据图片数量自动切换端点(文生图/图片编辑) 11 | * - 最多支持 10 张输入图片 12 | * - 隐藏参数:seed 13 | */ 14 | export const kieSeedream40Params: ParamDef[] = [ 15 | // 宽高比参数(带智能匹配和质量选择) 16 | { 17 | id: 'kieSeedream40AspectRatio', 18 | type: 'dropdown', 19 | defaultValue: '1:1', 20 | resolutionConfig: { 21 | type: 'aspect_ratio', 22 | smartMatch: true, 23 | visualize: true, 24 | extractRatio: (value) => { 25 | if (value === 'smart') return null 26 | const [w, h] = value.split(':').map(Number) 27 | return w / h 28 | }, 29 | qualityOptions: [ 30 | { value: '2K', label: '高清 2K' }, 31 | { value: '4K', label: '超清 4K' } 32 | ], 33 | qualityKey: 'kieSeedream40Resolution' 34 | }, 35 | // 自动切换:上传图片时切换到智能,删除图片时恢复为 1:1 36 | autoSwitch: { 37 | condition: (values) => values.uploadedImages && values.uploadedImages.length > 0, 38 | value: 'smart', 39 | watchKeys: ['uploadedImages'] // 只监听图片数量变化,避免用户手动选择比例时被强制切换 40 | }, 41 | options: [ 42 | { value: 'smart', label: '智能' }, 43 | { value: '1:1', label: '1:1' }, 44 | { value: '4:3', label: '4:3' }, 45 | { value: '3:4', label: '3:4' }, 46 | { value: '3:2', label: '3:2' }, 47 | { value: '2:3', label: '2:3' }, 48 | { value: '16:9', label: '16:9' }, 49 | { value: '9:16', label: '9:16' }, 50 | { value: '21:9', label: '21:9' } 51 | ], 52 | className: 'min-w-[100px]' 53 | }, 54 | // 数量参数 55 | { 56 | id: 'kieSeedream40MaxImages', 57 | type: 'number', 58 | label: '数量', 59 | defaultValue: 1, 60 | min: 1, 61 | max: 6, 62 | step: 1, 63 | widthClassName: 'w-20', 64 | tooltip: '设置为1时仅生成单张图片;大于1时,会根据该数值生成多张图片。', 65 | tooltipDelay: 500 66 | } 67 | ] 68 | -------------------------------------------------------------------------------- /src/adapters/kie/models/kling-v2-6.ts: -------------------------------------------------------------------------------- 1 | import { GenerateVideoParams } from '@/adapters/base/BaseAdapter' 2 | 3 | export interface KIEModelRoute { 4 | matches: (modelId: string) => boolean 5 | buildImageRequest?: (params: any) => { 6 | requestData: any 7 | } 8 | buildVideoRequest?: (params: GenerateVideoParams) => { 9 | requestData: any 10 | } 11 | } 12 | 13 | /** 14 | * KIE Kling V2.6 视频模型路由 15 | * 16 | * 特点: 17 | * - 根据是否有图片自动切换端点 18 | * - 文生视频:kling-2.6/text-to-video 19 | * - 图生视频:kling-2.6/image-to-video(最多1张图) 20 | * - 图生视频时不支持 aspect_ratio 参数 21 | * - 支持音频生成(enable_audio 映射为 sound 参数) 22 | * - 不传递 negative_prompt、cfg_scale、seed 等参数 23 | */ 24 | export const kieKlingV26Route: KIEModelRoute = { 25 | matches: (modelId: string) => 26 | modelId === 'kie-kling-v2-6' || 27 | modelId === 'kling-v2-6-kie', 28 | 29 | buildVideoRequest: (params: GenerateVideoParams) => { 30 | const images = params.images || [] 31 | const prompt = params.prompt || '' 32 | const hasImages = images.length > 0 33 | 34 | // 根据是否有图片选择端点 35 | const model = hasImages 36 | ? 'kling-2.6/image-to-video' // 图生视频 37 | : 'kling-2.6/text-to-video' // 文生视频 38 | 39 | // 构建请求数据 40 | const requestData: any = { 41 | model: model, 42 | input: { 43 | prompt: prompt 44 | } 45 | } 46 | 47 | // 添加 duration 参数(必填,默认 "5") 48 | requestData.input.duration = params.duration ? String(params.duration) : '5' 49 | 50 | // 添加 sound 参数(必填,默认 false) 51 | // enable_audio 参数映射为 sound 52 | requestData.input.sound = params.enable_audio || false 53 | 54 | // 文生视频:添加 aspect_ratio 参数(必填,默认 "1:1") 55 | if (!hasImages) { 56 | requestData.input.aspect_ratio = params.aspect_ratio || '16:9' 57 | } 58 | 59 | // 图生视频:添加 image_urls 参数(数组格式) 60 | if (hasImages) { 61 | requestData.input.image_urls = images // 注意:API 使用 image_urls(复数,数组) 62 | } 63 | 64 | // 注意:不传递 negative_prompt、cfg_scale、seed 等参数 65 | 66 | return { requestData } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/adapters/kie/models/seedream-4.0.ts: -------------------------------------------------------------------------------- 1 | import { GenerateImageParams } from '@/adapters/base/BaseAdapter' 2 | 3 | export interface KIEModelRoute { 4 | matches: (modelId: string) => boolean 5 | buildImageRequest?: (params: GenerateImageParams) => { 6 | requestData: any 7 | } 8 | } 9 | 10 | export const kieSeedream40Route: KIEModelRoute = { 11 | matches: (modelId: string) => 12 | modelId === 'kie-seedream-4.0' || 13 | modelId === 'seedream-4.0-kie', 14 | 15 | buildImageRequest: (params: GenerateImageParams) => { 16 | const images = params.images || [] 17 | const prompt = params.prompt || '' 18 | 19 | // 根据图片数量自动选择模型端点 20 | // 无图片:文生图 (bytedance/seedream-v4-text-to-image) 21 | // 有图片:图片编辑 (bytedance/seedream-v4-edit) 22 | const modelName = images.length === 0 23 | ? 'bytedance/seedream-v4-text-to-image' 24 | : 'bytedance/seedream-v4-edit' 25 | 26 | // 构建请求数据 27 | const requestData: any = { 28 | model: modelName, 29 | input: { 30 | prompt: prompt 31 | } 32 | } 33 | 34 | // 添加 image_size 参数 35 | // 注意:image_size 已经在 OptionsBuilder 中通过 transform 转换为 API 格式 36 | // 例如:'16:9' → 'landscape_16_9', '1:1' → 'square_hd' 37 | if (params.image_size !== undefined && 38 | params.image_size !== 'smart' && 39 | params.image_size !== 'auto') { 40 | requestData.input.image_size = params.image_size 41 | } 42 | 43 | // 添加 image_resolution 参数 44 | // 直接传递 2K/4K,不需要转换 45 | if (params.image_resolution !== undefined) { 46 | requestData.input.image_resolution = params.image_resolution 47 | } 48 | 49 | // 添加 max_images 参数 50 | if (params.max_images !== undefined) { 51 | requestData.input.max_images = params.max_images 52 | } 53 | 54 | // 如果有图片,添加到 image_urls(KIE 已上传的 URL) 55 | // 图片编辑端点使用 image_urls 参数 56 | if (images.length > 0) { 57 | requestData.input.image_urls = images 58 | } 59 | 60 | // 注意:seed 参数不传递给 API(用户要求隐藏) 61 | 62 | return { requestData } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src-tauri/capabilities/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../gen/schemas/desktop-schema.json", 3 | "identifier": "default", 4 | "description": "Default capabilities for Henji-AI", 5 | "windows": [ 6 | "main" 7 | ], 8 | "permissions": [ 9 | "core:app:default", 10 | "core:window:default", 11 | "core:window:allow-minimize", 12 | "core:window:allow-toggle-maximize", 13 | "core:window:allow-close", 14 | "core:window:allow-start-dragging", 15 | "core:event:default", 16 | "core:path:default", 17 | "core:resources:default", 18 | "core:image:default", 19 | "core:menu:default", 20 | "core:tray:default", 21 | "dialog:default", 22 | "http:default", 23 | { 24 | "identifier": "http:allow-fetch", 25 | "allow": [ 26 | { 27 | "url": "http://*" 28 | }, 29 | { 30 | "url": "https://*" 31 | } 32 | ] 33 | }, 34 | { 35 | "identifier": "http:allow-fetch-read-body", 36 | "allow": [ 37 | { 38 | "url": "http://*" 39 | }, 40 | { 41 | "url": "https://*" 42 | } 43 | ] 44 | }, 45 | { 46 | "identifier": "http:allow-fetch-send", 47 | "allow": [ 48 | { 49 | "url": "http://*" 50 | }, 51 | { 52 | "url": "https://*" 53 | } 54 | ] 55 | }, 56 | "fs:default", 57 | "fs:allow-localdata-read-recursive", 58 | "fs:allow-localdata-write-recursive", 59 | "fs:allow-read-file", 60 | "fs:allow-write-file", 61 | "fs:allow-read-dir", 62 | "fs:allow-copy-file", 63 | "fs:allow-mkdir", 64 | "fs:allow-remove", 65 | "fs:allow-rename", 66 | "fs:allow-exists", 67 | { 68 | "identifier": "fs:scope", 69 | "allow": [ 70 | { 71 | "path": "**" 72 | } 73 | ] 74 | }, 75 | "shell:default", 76 | "shell:allow-open", 77 | "clipboard-manager:default", 78 | "clipboard-manager:allow-read-text", 79 | "clipboard-manager:allow-write-text" 80 | ] 81 | } -------------------------------------------------------------------------------- /src/adapters/kie/models/grok-imagine-video.ts: -------------------------------------------------------------------------------- 1 | import { GenerateVideoParams } from '@/adapters/base/BaseAdapter' 2 | 3 | export interface KIEModelRoute { 4 | matches: (modelId: string) => boolean 5 | buildImageRequest?: (params: any) => { 6 | requestData: any 7 | } 8 | buildVideoRequest?: (params: GenerateVideoParams) => { 9 | requestData: any 10 | } 11 | } 12 | 13 | /** 14 | * KIE Grok Imagine 视频模型路由 15 | * 16 | * 特点: 17 | * - 根据是否有图片自动切换端点 18 | * - 文生视频:grok-imagine/text-to-video 19 | * - 图生视频:grok-imagine/image-to-video(最多1张图) 20 | * - 图生视频时不支持 aspect_ratio 参数 21 | * - 图生视频时不支持 spicy 模式 22 | */ 23 | export const kieGrokImagineVideoRoute: KIEModelRoute = { 24 | matches: (modelId: string) => 25 | modelId === 'kie-grok-imagine-video' || 26 | modelId === 'grok-imagine-video-kie', 27 | 28 | buildVideoRequest: (params: GenerateVideoParams) => { 29 | const images = params.images || [] 30 | const prompt = params.prompt || '' 31 | const hasImages = images.length > 0 32 | 33 | // 根据是否有图片选择端点 34 | const model = hasImages 35 | ? 'grok-imagine/image-to-video' // 图生视频 36 | : 'grok-imagine/text-to-video' // 文生视频 37 | 38 | // 构建请求数据 39 | const requestData: any = { 40 | model: model, 41 | input: { 42 | prompt: prompt 43 | } 44 | } 45 | 46 | // 文生视频:添加 aspect_ratio 参数 47 | if (!hasImages && params.aspect_ratio !== undefined) { 48 | requestData.input.aspect_ratio = params.aspect_ratio 49 | } 50 | 51 | // 图生视频:添加 image_urls 参数(最多1张图) 52 | if (hasImages) { 53 | requestData.input.image_urls = [images[0]] // 只取第一张图片 54 | } 55 | 56 | // 添加 mode 参数(可选) 57 | if (params.mode !== undefined) { 58 | // 图生视频时,如果是 spicy 模式,改为 normal(因为不支持) 59 | if (hasImages && (params as any).mode === 'spicy') { 60 | requestData.input.mode = 'normal' 61 | } else { 62 | requestData.input.mode = params.mode 63 | } 64 | } 65 | 66 | // 注意:不传递 task_id、index、seed、negative_prompt 等参数 67 | 68 | return { requestData } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /docs/api/KIE/veo3/05-获取-1080P-视频.md: -------------------------------------------------------------------------------- 1 | # 获取 1080P 视频 2 | 3 | 获取 Veo3.1 视频生成任务的高清 1080P 版本。 4 | 5 | **注意**:通过托底模式生成的视频无法通过此接口访问,因为它们默认已经是 1080p 分辨率。 6 | 7 | **端点** 8 | ``` 9 | GET /api/v1/veo/get-1080p-video 10 | ``` 11 | 12 | **请求示例** 13 | ```bash 14 | curl --request GET \ 15 | --url https://api.kie.ai/api/v1/veo/get-1080p-video \ 16 | --header 'Authorization: Bearer ' 17 | ``` 18 | 19 | ## 使用说明 20 | 21 | * 仅 16:9 宽高比的视频支持 1080P 高清生成。 22 | * 视频生成任务成功后,系统会自动开始生成 1080P 高清版本。 23 | * 1080P 视频生成需要额外处理时间,建议在原视频生成完成后等待一段时间再调用本接口。 24 | * 如果 1080P 视频尚未准备好,接口可能返回错误信息。 25 | 26 | ## 重要说明 27 | 28 | * 只有成功生成的视频任务才能获取 1080P 的版本。 29 | * 建议在收到视频生成成功回调后等待几分钟再调用本接口。 30 | 31 | ## 认证 32 | 33 | 所有 API 都需要通过 Bearer Token 进行认证。 34 | 35 | **Header 参数** 36 | 37 | | 参数名 | 位置 | 类型 | 必填 | 说明 | 38 | | :--- | :--- | :--- | :--- | :--- | 39 | | `Authorization` | header | string | 是 | Bearer Token。格式:`Bearer YOUR_API_KEY` | 40 | 41 | **获取 API Key** 42 | 1. 访问 [API Key 管理页面](https://kie.ai/api-key) 获取您的 API Key。 43 | 44 | **注意** 45 | * 请妥善保管您的 API Key,不要与他人分享。 46 | * 如果您怀疑 API Key 已泄露,请立即在管理页面重置。 47 | 48 | ## 查询参数 49 | 50 | | 参数名 | 类型 | 必填 | 说明 | 51 | | :--- | :--- | :--- | :--- | 52 | | `taskId` | string | 是 | 任务ID | 53 | | `index` | integer | 否 | 视频索引 | 54 | 55 | ## 响应 56 | 57 | **成功响应示例** 58 | ```json 59 | { 60 | "code": 200, 61 | "msg": "success", 62 | "data": { 63 | "resultUrl": "https://tempfile.aiquickdraw.com/p/42f4f8facbb040c0ade87c27cb2d5e58_1749711595.mp4" 64 | } 65 | } 66 | ``` 67 | 68 | **响应字段说明** 69 | 70 | | 字段 | 类型 | 说明 | 71 | | :--- | :--- | :--- | 72 | | `code` | integer | 响应状态码。 | 73 | | `msg` | string | 响应消息。 | 74 | | `data` | object | 响应数据对象。 | 75 | | `data.resultUrl` | string | 1080P高清视频下载地址。 | 76 | 77 | **状态码说明** 78 | 79 | | 状态码 | 说明 | 80 | | :--- | :--- | 81 | | 200 | 成功 - 请求已成功处理。 | 82 | | 401 | 未授权 - 认证凭据缺失或无效。 | 83 | | 404 | 未找到 - 请求的资源或端点不存在。 | 84 | | 422 | 验证错误 - 请求参数验证失败。可能原因:记录为空、暂时支持14天内的记录、记录结果数据为空、记录状态不是成功、记录结果数据不存在。 | 85 | | 429 | 请求限制 - 已超过该资源的请求限制。 | 86 | | 451 | 无法获取图片。请验证您或您的服务提供商设置的任何访问限制。 | 87 | | 455 | 服务不可用 - 系统正在进行维护。 | 88 | | 500 | 服务器错误 - 处理请求时发生意外错误。 | -------------------------------------------------------------------------------- /src-tauri/tauri.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schema.tauri.app/config/2", 3 | "productName": "痕迹AI", 4 | "version": "0.1.1", 5 | "identifier": "com.henji.ai", 6 | "build": { 7 | "frontendDist": "../dist", 8 | "devUrl": "http://localhost:3000", 9 | "beforeDevCommand": "npm run dev", 10 | "beforeBuildCommand": "npm run build" 11 | }, 12 | "app": { 13 | "security": { 14 | "assetProtocol": { 15 | "enable": true, 16 | "scope": [ 17 | "**" 18 | ] 19 | }, 20 | "csp": "default-src 'self' ipc: http://ipc.localhost data: blob: https: http:; connect-src * data: blob:; img-src 'self' asset: http://asset.localhost data: blob: https: http: *; media-src 'self' asset: http://asset.localhost data: blob: https: http: *; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; font-src 'self' data:; worker-src 'self' blob: data:;" 21 | }, 22 | "windows": [ 23 | { 24 | "label": "main", 25 | "title": "痕迹AI", 26 | "width": 1200, 27 | "height": 800, 28 | "resizable": true, 29 | "decorations": false, 30 | "visible": false, 31 | "center": true, 32 | "transparent": true, 33 | "backgroundColor": "#00000000" 34 | } 35 | ] 36 | }, 37 | "bundle": { 38 | "active": true, 39 | "targets": "all", 40 | "resources": [], 41 | "icon": [ 42 | "icons/32x32.png", 43 | "icons/128x128.png", 44 | "icons/128x128@2x.png", 45 | "icons/icon.icns", 46 | "icons/icon.ico" 47 | ], 48 | "longDescription": "痕迹AI 是一个基于 Tauri 和 React 构建的跨平台桌面应用,聚合派欧云、fal 等多家 AI 供应商,提供图片生成(即梦 4.0、Nano Banana 等)、视频生成(Vidu Q1、可灵 2.5、Hailuo 等)和音频合成(MiniMax Speech 2.6)功能。采用适配器模式统一不同供应商接口,支持 Windows 和 macOS。", 49 | "shortDescription": "聚合多家AI供应商,一站式生成图片、视频和音频的客户端", 50 | "macOS": { 51 | "frameworks": [], 52 | "minimumSystemVersion": "10.13", 53 | "infoPlist": "./Info.plist" 54 | }, 55 | "windows": { 56 | "wix": { 57 | "language": "zh-CN" 58 | } 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/视频/Vidu_Q1_文生视频.md: -------------------------------------------------------------------------------- 1 | # Vidu Q1 文生视频 2 | 3 | 这是一个**异步**API,通过关键帧技术生成流畅无缝、主题风格一致的视频。调用后返回异步任务的 `task_id`,您需要使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来获取视频生成结果。 4 | 5 | ## 请求示例 6 | 7 | **请求** 8 | ```bash 9 | curl --request POST \ 10 | --url https://api.ppinfra.com/v3/async/vidu-q1-text2video \ 11 | --header 'Authorization: ' \ 12 | --header 'Content-Type: application/json' \ 13 | --data ' 14 | { 15 | "prompt": "", 16 | "style": "", 17 | "duration": 123, 18 | "seed": 123, 19 | "aspect_ratio": "", 20 | "resolution": "", 21 | "movement_amplitude": "", 22 | "bgm": true 23 | } 24 | ' 25 | ``` 26 | 27 | **响应** 28 | ```json 29 | { 30 | "task_id": "" 31 | } 32 | ``` 33 | 34 | ## 请求头 35 | 36 | | 参数 | 类型 | 是否必需 | 描述 | 37 | | :--- | :--- | :--- | :--- | 38 | | `Content-Type` | string | 是 | 必须为 `application/json`。 | 39 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 40 | 41 | ## 请求体 42 | 43 | | 参数 | 类型 | 是否必需 | 描述 | 44 | | :--- | :--- | :--- | :--- | 45 | | `prompt` | string | 是 | 视频生成的文本提示词,最大长度为 1500 个字符。 | 46 | | `style` | string | 否 | 输出视频的风格。
**默认值**:`general`
**可选值**:
- `general`:通用风格。允许通过提示词控制风格。
- `anime`:动漫风格。针对动漫美学优化,对动漫相关提示词有更好的表现。 | 47 | | `duration` | integer | 否 | 视频持续时间(秒)。
**默认值**:`5`
**当前仅支持**:`5` | 48 | | `seed` | integer | 否 | 视频生成的随机种子。
- 默认为随机种子数值。
- 手动设置的值将覆盖默认的随机种子。 | 49 | | `aspect_ratio` | string | 否 | 输出视频的宽高比。
**默认值**:`16:9`
**可选值**:`16:9`、`9:16`、`1:1` | 50 | | `resolution` | string | 否 | 输出视频分辨率。
**默认值**:`1080p`
**当前仅支持**:`1080p` | 51 | | `movement_amplitude` | string | 否 | 画面中物体的运动幅度。
**默认值**:`auto`
**可选值**:`auto`、`small`、`medium`、`large` | 52 | | `bgm` | boolean | 否 | 是否为生成的视频添加背景音乐。
**默认值**:`false`
**可选值**:`true`、`false`
当设置为 `true` 时,系统将自动添加合适的 BGM。BGM 无时长限制,系统会自动适配。 | 53 | 54 | ## 响应 55 | 56 | | 参数 | 类型 | 是否必需 | 描述 | 57 | | :--- | :--- | :--- | :--- | 58 | | `task_id` | string | 是 | 异步任务的 `task_id`。您应该使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果。 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "henji-ai", 3 | "private": true, 4 | "version": "0.1.1", 5 | "description": "一个聚合多家AI供应商,一站式生成图片、视频和音频的客户端", 6 | "type": "module", 7 | "license": "Apache-2.0", 8 | "scripts": { 9 | "dev": "vite", 10 | "build": "tsc && vite build", 11 | "preview": "vite preview", 12 | "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0", 13 | "lint:fix": "eslint src --ext ts,tsx --fix", 14 | "tauri:dev": "call \"%ProgramFiles(x86)%\\Microsoft Visual Studio\\2022\\BuildTools\\Common7\\Tools\\VsDevCmd.bat\" -arch=amd64 && set CC=cl.exe&& set CXX=cl.exe&& tauri dev", 15 | "tauri:build": "call \"%ProgramFiles(x86)%\\Microsoft Visual Studio\\2022\\BuildTools\\Common7\\Tools\\VsDevCmd.bat\" -arch=amd64 && set CC=cl.exe&& set CXX=cl.exe&& tauri build", 16 | "tauri:build:ci": "tauri build", 17 | "tauri:dev:mac": "tauri dev", 18 | "tauri:build:mac": "tauri build" 19 | }, 20 | "dependencies": { 21 | "@fal-ai/client": "^1.7.2", 22 | "@tauri-apps/api": "^2.0.0", 23 | "@tauri-apps/plugin-clipboard-manager": "^2.3.2", 24 | "@tauri-apps/plugin-dialog": "^2.4.2", 25 | "@tauri-apps/plugin-fs": "^2.0.0", 26 | "@tauri-apps/plugin-http": "^2.0.0", 27 | "@tauri-apps/plugin-shell": "^2.3.3", 28 | "@types/react-window": "^1.8.8", 29 | "axios": "^1.6.0", 30 | "pica": "^9.0.1", 31 | "react": "^18.2.0", 32 | "react-dom": "^18.2.0", 33 | "react-virtuoso": "^4.15.0", 34 | "react-window": "^2.2.3" 35 | }, 36 | "devDependencies": { 37 | "@tauri-apps/cli": "^2.0.0", 38 | "@types/pica": "^9.0.5", 39 | "@types/react": "^18.2.15", 40 | "@types/react-dom": "^18.2.7", 41 | "@typescript-eslint/eslint-plugin": "^6.0.0", 42 | "@typescript-eslint/parser": "^6.0.0", 43 | "@vitejs/plugin-react": "^4.0.3", 44 | "autoprefixer": "^10.4.16", 45 | "eslint": "^8.45.0", 46 | "eslint-plugin-react-hooks": "^4.6.0", 47 | "eslint-plugin-react-refresh": "^0.4.3", 48 | "postcss": "^8.4.31", 49 | "tailwindcss": "^3.3.3", 50 | "typescript": "^5.0.2", 51 | "vite": "^4.4.5" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/adapters/fal/models/fal-ai-kling-video-v2.6-pro.ts: -------------------------------------------------------------------------------- 1 | import { GenerateVideoParams } from '@/adapters/base/BaseAdapter' 2 | import { FalModelRoute } from './index' 3 | import { logInfo } from '../../../utils/errorLogger' 4 | 5 | /** 6 | * Kling Video v2.6 Pro 模型路由 7 | * 支持 2 种模式: 8 | * - text-to-video: 文生视频 9 | * - image-to-video: 图生视频 10 | * 11 | * 特性: 12 | * - 支持 5 秒和 10 秒时长 13 | * - 支持 16:9、9:16、1:1 宽高比(仅文生视频) 14 | * - 支持原生音频生成(中英文) 15 | * - 支持 CFG Scale 调节(仅文生视频) 16 | */ 17 | export const falAiKlingVideoV26ProRoute: FalModelRoute = { 18 | matches: (modelId: string) => 19 | modelId.includes('kling-video-v2.6-pro') || 20 | modelId.includes('kling-video/v2.6/pro') || 21 | modelId === 'fal-ai-kling-video-v2.6-pro', 22 | 23 | buildVideoRequest: async (params: GenerateVideoParams) => { 24 | const { 25 | prompt = '', 26 | images = [], 27 | duration = 5, 28 | aspectRatio = '16:9', 29 | klingV26GenerateAudio = true, 30 | klingV26CfgScale = 0.5 31 | } = params 32 | 33 | // 根据是否有图片选择端点 34 | const hasImages = images.length > 0 35 | const endpoint = hasImages 36 | ? 'fal-ai/kling-video/v2.6/pro/image-to-video' 37 | : 'fal-ai/kling-video/v2.6/pro/text-to-video' 38 | 39 | const modelId = 'fal-ai/kling-video/v2.6/pro' 40 | 41 | // 构建请求数据 42 | const requestData: any = { 43 | prompt, 44 | duration: `${duration}`, 45 | generate_audio: klingV26GenerateAudio 46 | } 47 | 48 | // 图生视频模式:添加图片 URL 49 | if (hasImages) { 50 | requestData.image_url = images[0] 51 | } else { 52 | // 文生视频模式:添加宽高比和 CFG Scale 53 | if (aspectRatio && aspectRatio !== 'auto') { 54 | requestData.aspect_ratio = aspectRatio 55 | } 56 | 57 | if (klingV26CfgScale !== undefined) { 58 | requestData.cfg_scale = klingV26CfgScale 59 | } 60 | } 61 | 62 | logInfo('[Kling v2.6 Pro] 构建请求:', { 63 | mode: hasImages ? 'image-to-video' : 'text-to-video', 64 | endpoint, 65 | hasImages, 66 | requestData 67 | }) 68 | 69 | return { endpoint, modelId, requestData } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/models/fal-ai-nano-banana-pro.ts: -------------------------------------------------------------------------------- 1 | import { ParamDef } from '../types/schema' 2 | 3 | /** 4 | * Fal.ai Nano Banana Pro 模型参数定义 5 | */ 6 | export const falAiNanoBananaProParams: ParamDef[] = [ 7 | { 8 | id: 'falNanoBananaProNum_images', 9 | type: 'number', 10 | label: '数量', 11 | min: 1, 12 | max: 4, 13 | step: 1, 14 | widthClassName: 'w-20' 15 | }, 16 | { 17 | id: 'falNanoBananaProAspectRatio', 18 | type: 'dropdown', 19 | defaultValue: '1:1', // 文生图默认 1:1 20 | // 分辨率配置:启用智能匹配、可视化和质量选项 21 | resolutionConfig: { 22 | type: 'aspect_ratio', 23 | smartMatch: true, 24 | visualize: true, 25 | extractRatio: (value) => { 26 | if (value === 'smart') return null 27 | const [w, h] = value.split(':').map(Number) 28 | return w / h 29 | }, 30 | qualityOptions: [ 31 | { value: '1K', label: '1K' }, 32 | { value: '2K', label: '2K' }, 33 | { value: '4K', label: '4K' } 34 | ], 35 | qualityKey: 'resolution' // Nano Banana Pro 使用 'resolution' 作为质量参数 36 | }, 37 | // 当上传图片时自动切换到智能选项 38 | autoSwitch: { 39 | condition: (values) => values.uploadedImages && values.uploadedImages.length > 0, 40 | value: 'smart', 41 | watchKeys: ['uploadedImages'] // 只监听图片数量变化,避免用户手动选择比例时被强制切换 42 | }, 43 | options: [ 44 | { value: 'smart', label: '智能' }, 45 | { value: '1:1', label: '1:1' }, 46 | { value: '16:9', label: '16:9' }, 47 | { value: '9:16', label: '9:16' }, 48 | { value: '21:9', label: '21:9' }, 49 | { value: '3:2', label: '3:2' }, 50 | { value: '2:3', label: '2:3' }, 51 | { value: '4:3', label: '4:3' }, 52 | { value: '3:4', label: '3:4' }, 53 | { value: '5:4', label: '5:4' }, 54 | { value: '4:5', label: '4:5' } 55 | ], 56 | className: 'min-w-[100px]' 57 | } 58 | ] 59 | -------------------------------------------------------------------------------- /src/adapters/_template/models/exampleModel.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 示例模型路由 3 | * 4 | * 使用说明: 5 | * 1. 复制此文件并重命名为实际模型名 6 | * 2. 修改 matches 函数中的模型ID 7 | * 3. 根据API文档实现 buildRequest 8 | */ 9 | 10 | import { ModelRoute } from '../types' 11 | import { GenerateImageParams, GenerateVideoParams } from '../../base/BaseAdapter' 12 | 13 | export const exampleModelRoute: ModelRoute = { 14 | /** 15 | * 判断是否匹配该模型 16 | */ 17 | matches: (modelId: string) => { 18 | return modelId === 'example-model-id' // 修改为实际模型ID 19 | }, 20 | 21 | /** 22 | * 构建API请求 23 | */ 24 | buildRequest: (params) => { 25 | // 根据参数类型判断是图片/视频/音频生成 26 | if ('images' in params || params.model.includes('image')) { 27 | // 图片生成示例 28 | const imageParams = params as GenerateImageParams 29 | 30 | return { 31 | endpoint: '/image/generate', // 修改为实际端点 32 | requestData: { 33 | prompt: imageParams.prompt, 34 | // 根据API文档添加其他参数 35 | num_images: imageParams.num_images || 1, 36 | size: imageParams.size, 37 | // ... 38 | } 39 | } 40 | } else if ('duration' in params || params.model.includes('video')) { 41 | // 视频生成示例 42 | const videoParams = params as GenerateVideoParams 43 | 44 | // 检查是否有图片上传 45 | const hasImages = videoParams.images && videoParams.images.length > 0 46 | 47 | return { 48 | endpoint: hasImages ? '/video/image-to-video' : '/video/text-to-video', 49 | requestData: { 50 | prompt: videoParams.prompt, 51 | duration: videoParams.duration || 5, 52 | ...(hasImages && videoParams.images ? { image: videoParams.images[0] } : {}), 53 | // ... 54 | } 55 | } 56 | } 57 | 58 | // 音频生成类似处理 59 | return { 60 | endpoint: '/default', 61 | requestData: { prompt: params.prompt } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/视频/Seedance_V1_Pro_图生视频.md: -------------------------------------------------------------------------------- 1 | # Seedance V1 Pro 图生视频 2 | 3 | Seedance V1 Pro 是一个 AI 视频模型,专为生成连贯的多镜头视频而设计,提供流畅的运动和对详细提示的精确遵循。它支持 480p、720p 和 1080p 的分辨率。 4 | 5 | 本接口支持个人认证及企业认证用户调用。请参见 [实名认证](/docs/support/identity-verification),完成个人用户认证或企业用户认证,以确保可以正常使用本功能。 6 | 7 | ## 接口调用示例 8 | 9 | **请求示例** 10 | ```bash 11 | curl --request POST \ 12 | --url https://api.ppinfra.com/v3/async/seedance-v1-pro-i2v \ 13 | --header 'Authorization: ' \ 14 | --header 'Content-Type: application/json' \ 15 | --data ' 16 | { 17 | "prompt": "", 18 | "image": "", 19 | "last_image": "", 20 | "resolution": "", 21 | "aspect_ratio": "", 22 | "camera_fixed": true, 23 | "seed": 123, 24 | "duration": 123 25 | } 26 | ' 27 | ``` 28 | 29 | **响应示例** 30 | ```json 31 | { 32 | "task_id": "" 33 | } 34 | ``` 35 | 36 | ## 请求头 37 | 38 | | 参数 | 类型 | 必填 | 说明 | 39 | | :--- | :--- | :--- | :--- | 40 | | `Content-Type` | string | 是 | 必须为 `application/json`。 | 41 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 42 | 43 | ## 请求体 44 | 45 | | 参数 | 类型 | 必填 | 默认值 | 说明 | 46 | | :--- | :--- | :--- | :--- | :--- | 47 | | `prompt` | string | 否 | - | 视频生成的文本提示(正面提示)。支持中英文,建议不超过500字。 | 48 | | `image` | string | 是 | - | 输入图像,支持 URL 和 Base64 格式。
• 图片格式:`jpeg`, `png`, `webp`, `bmp`, `tiff`, `gif`。
• 文件大小 ≤ 30MB。
• 短边 > 300 像素,长边 < 6000 像素。
• 宽高比在 0.4 到 2.5 之间。 | 49 | | `last_image` | string | 否 | - | 结束图像,支持 URL 和 Base64 格式。要求与 `image` 参数相同。
传入的首尾帧图片可相同。首尾帧图片的宽高比不一致时,以首帧图片为主,尾帧图片会自动裁剪适配。 | 50 | | `resolution` | string | 是 | - | 视频质量。可选值:`480p`, `720p`, `1080p`。 | 51 | | `aspect_ratio` | string | 否 | `"16:9"` | 生成视频的长宽比。可选值:`21:9`, `16:9`, `4:3`, `1:1`, `3:4`, `9:16`, `9:21`。 | 52 | | `camera_fixed` | boolean | 否 | `false` | 确定相机位置是否应保持固定。 | 53 | | `seed` | integer | 否 | `-1` | 用于生成的随机种子。`-1` 表示使用随机种子。 | 54 | | `duration` | integer | 否 | `5` | 指定生成视频的长度(秒)。可选值:`5`, `10`。 | 55 | 56 | ## 响应 57 | 58 | | 参数 | 类型 | 必填 | 说明 | 59 | | :--- | :--- | :--- | :--- | 60 | | `task_id` | string | 是 | 异步任务的 ID。使用此 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果。 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/视频/Minimax_Hailuo_2.3_图生视频.md: -------------------------------------------------------------------------------- 1 | # Minimax Hailuo 2.3 图生视频 2 | 3 | Minimax Hailuo 2.3 是全新升级的视频生成模型,在肢体动作、物理效果和对指令的理解与执行能力等方面表现更为出色。 4 | 5 | 这是一个**异步**API,只会返回异步任务的 `task_id`。您应该使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来检索视频生成结果。 6 | 7 | ## 请求示例 8 | 9 | **请求** 10 | 11 | ```bash 12 | curl --request POST \ 13 | --url https://api.ppinfra.com/v3/async/minimax-hailuo-2.3-i2v \ 14 | --header 'Authorization: ' \ 15 | --header 'Content-Type: application/json' \ 16 | --data ' 17 | { 18 | "prompt": "", 19 | "image": "", 20 | "duration": 123, 21 | "resolution": "", 22 | "enable_prompt_expansion": true 23 | } 24 | ' 25 | ``` 26 | 27 | **响应** 28 | 29 | ```json 30 | { 31 | "task_id": "" 32 | } 33 | ``` 34 | 35 | ## 请求头 36 | 37 | | 参数 | 类型 | 是否必需 | 说明 | 38 | | :--- | :--- | :--- | :--- | 39 | | `Content-Type` | `string` | 是 | 必须为 `application/json`。 | 40 | | `Authorization` | `string` | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 41 | 42 | ## 请求体 43 | 44 | | 参数 | 类型 | 是否必需 | 说明 | 45 | | :--- | :--- | :--- | :--- | 46 | | `prompt` | `string` | 是 | 指导生成所需的提示词文本。范围: `1 <= x <= 2000`。支持 15 种运镜指令的指令:
• 左右移: `[左移]`, `[右移]`
• 左右摇: `[左摇]`, `[右摇]`
• 推拉: `[推进]`, `[拉远]`
• 升降: `[上升]`, `[下降]`
• 上下摇: `[上摇]`, `[下摇]`
• 变焦: `[变焦推近]`, `[变焦拉远]`
• 其他: `[晃动]`, `[跟随]`, `[固定]`

**使用规则:**
• **组合运镜**: 同一组 `[]` 内的多个指令会同时生效,如 `[左摇,上升]`,建议组合不超过 3 个。
• **顺序运镜**: `prompt` 中前后出现的指令会依次生效,如 `“…[推进], 然后…[拉远]”`。
• **自然语言**: 也支持通过自然语言描述运镜,但使用标准指令能获得更准确的响应。 | 47 | | `image` | `string` | 是 | 用于视频生成的图片。支持公网 URL 或 Base64 编码(如 `data:image/jpeg;base64,...`)。 | 48 | | `duration` | `integer` | 否 | 生成视频的时长(秒)。
**默认值**: `6`
**可选值**: `6`, `10` | 49 | | `resolution` | `string` | 否 | 生成视频的分辨率。
**默认值**: `768P`
• 6 秒视频支持:`768P`、`1080P`
• 10 秒视频仅支持:`768P` | 50 | | `enable_prompt_expansion` | `boolean` | 否 | 是否启用提示词优化。
**默认值**: `true` | 51 | 52 | ## 响应 53 | 54 | | 参数 | 类型 | 是否必需 | 说明 | 55 | | :--- | :--- | :--- | :--- | 56 | | `task_id` | `string` | 是 | 异步任务的 `task_id`。您应该使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果。 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/视频/PixVerse_V4.5_图生视频.md: -------------------------------------------------------------------------------- 1 | # PixVerse V4.5 图生视频 2 | 3 | 使用 PixVerse 最新的 v4.5 模型,根据文本描述和输入图像生成高质量视频。支持多种分辨率、纵横比和运动模式,以实现多样化的视频创作。 4 | 5 | 这是一个**异步** API,调用后仅返回异步任务的 `task_id`。您需要使用该 `task_id` 调用 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来获取视频生成结果。 6 | 7 | ## 请求示例 8 | 9 | **请求 URL** 10 | ``` 11 | POST https://api.ppinfra.com/v3/async/pixverse-v4.5-i2v 12 | ``` 13 | 14 | **cURL 示例** 15 | ```bash 16 | curl --request POST \ 17 | --url https://api.ppinfra.com/v3/async/pixverse-v4.5-i2v \ 18 | --header 'Authorization: ' \ 19 | --header 'Content-Type: application/json' \ 20 | --data ' 21 | { 22 | "prompt": "", 23 | "image": "", 24 | "resolution": "", 25 | "negative_prompt": "", 26 | "fast_mode": true, 27 | "style": "", 28 | "seed": 123 29 | } 30 | ' 31 | ``` 32 | 33 | **响应示例** 34 | ```json 35 | { 36 | "task_id": "" 37 | } 38 | ``` 39 | 40 | ## 请求头 41 | 42 | | 参数名 | 类型 | 是否必需 | 说明 | 43 | | :--- | :--- | :--- | :--- | 44 | | `Content-Type` | string | 是 | 固定为 `application/json`。 | 45 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 46 | 47 | ## 请求体 48 | 49 | | 参数名 | 类型 | 是否必需 | 说明与约束 | 50 | | :--- | :--- | :--- | :--- | 51 | | `prompt` | string | 是 | 视频生成的文本提示。
• 最大长度:2048 个字符。
• 应清晰描述所需场景和动作。 | 52 | | `image` | string | 是 | 视频的第一帧图像。
• 支持格式:`.jpg`/`.jpeg`/`.png`。
• 文件大小:不超过 10MB。
• 分辨率:不小于 300\*300 像素。
• 宽高比:应在 1:2.5 ~ 2.5:1 之间。 | 53 | | `resolution` | string | 是 | 视频分辨率/质量。
• 默认值:`540p`。
• **`fast_mode` 为 `false` 时可选**:`360p`、`540p`、`720p`、`1080p`。
• **`fast_mode` 为 `true` 时可选**:`360p`、`540p`、`720p`。 | 54 | | `negative_prompt` | string | 否 | 生成的负面提示。
• 最大长度:2048 个字符。 | 55 | | `fast_mode` | boolean | 否 | 是否启用快速模式。启用后将更快生成视频,但可能降低质量并减少费用。
• 默认值:`false`。 | 56 | | `style` | string | 否 | 风格预设(仅限 v3.5)。
• 可选值:`anime`、`3d_animation`、`clay`、`comic`、`cyberpunk`。 | 57 | | `seed` | integer | 否 | 用于生成的随机种子。 | 58 | 59 | ## 响应 60 | 61 | | 参数名 | 类型 | 是否必需 | 说明 | 62 | | :--- | :--- | :--- | :--- | 63 | | `task_id` | string | 是 | 异步任务的唯一标识符。用于请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取最终生成结果。 | -------------------------------------------------------------------------------- /src/models/kling-video-o1.ts: -------------------------------------------------------------------------------- 1 | import { ParamDef } from '../types/schema' 2 | 3 | /** 4 | * Kling Video O1 参数定义 5 | * 支持 4 种模式:图生视频、参考生视频、视频编辑、视频参考 6 | */ 7 | export const klingVideoO1Params: ParamDef[] = [ 8 | // 模式选择 9 | { 10 | id: 'falKlingVideoO1Mode', 11 | type: 'dropdown', 12 | label: '模式', 13 | defaultValue: 'image-to-video', 14 | options: [ 15 | { value: 'image-to-video', label: '图生视频' }, 16 | { value: 'reference-to-video', label: '参考生视频' }, 17 | { value: 'video-to-video-edit', label: '视频编辑' }, 18 | { value: 'video-to-video-reference', label: '视频参考' } 19 | ], 20 | className: 'min-w-[120px]' 21 | }, 22 | 23 | // 时长 24 | { 25 | id: 'falKlingVideoO1VideoDuration', 26 | type: 'dropdown', 27 | label: '时长', 28 | defaultValue: 5, 29 | options: [ 30 | { value: 5, label: '5s' }, 31 | { value: 10, label: '10s' } 32 | ] 33 | }, 34 | 35 | // 宽高比(仅部分模式显示) 36 | { 37 | id: 'falKlingVideoO1AspectRatio', 38 | type: 'dropdown', 39 | label: '比例', 40 | defaultValue: '16:9', 41 | options: (values) => { 42 | const mode = values.falKlingVideoO1Mode 43 | // reference-to-video 和 video-to-video-reference 模式支持宽高比 44 | if (mode === 'video-to-video-reference' || mode === 'reference-to-video') { 45 | return [ 46 | { value: 'auto', label: '自动' }, 47 | { value: '16:9', label: '16:9' }, 48 | { value: '9:16', label: '9:16' }, 49 | { value: '1:1', label: '1:1' } 50 | ] 51 | } 52 | return [] 53 | }, 54 | hidden: (values) => { 55 | const mode = values.falKlingVideoO1Mode 56 | // image-to-video 和 video-to-video-edit 模式不支持宽高比参数 57 | return mode === 'image-to-video' || mode === 'video-to-video-edit' 58 | } 59 | }, 60 | 61 | // 保留音频(仅视频模式显示) 62 | { 63 | id: 'falKlingVideoO1KeepAudio', 64 | type: 'toggle', 65 | label: '保留音频', 66 | defaultValue: false, 67 | hidden: (values) => { 68 | const mode = values.falKlingVideoO1Mode 69 | // 只有视频编辑和视频参考模式支持保留音频 70 | return mode === 'image-to-video' || mode === 'reference-to-video' 71 | } 72 | } 73 | ] 74 | -------------------------------------------------------------------------------- /src/models/fal-ai-wan-25-preview.ts: -------------------------------------------------------------------------------- 1 | import { ParamDef } from '../types/schema' 2 | 3 | /** 4 | * Fal.ai Wan 2.5 Preview 模型参数定义 5 | * 6 | * 特点: 7 | * - 根据上传图片数量自动切换端点(0张→文生视频,1张→图生视频) 8 | * - 图生视频时只显示分辨率,文生视频时显示比例+分辨率 9 | * - 支持提示词扩展开关 10 | */ 11 | export const falAiWan25PreviewParams: ParamDef[] = [ 12 | { 13 | id: 'falWan25VideoDuration', 14 | type: 'dropdown', 15 | label: '时长', 16 | defaultValue: 5, // Wan 2.5 默认 5 秒 17 | options: [ 18 | { value: 5, label: '5s' }, 19 | { value: 10, label: '10s' } 20 | ] 21 | }, 22 | { 23 | id: 'falWan25AspectRatio', 24 | type: 'dropdown', 25 | defaultValue: '16:9', 26 | // 分辨率配置:整合比例和分辨率到统一面板 27 | resolutionConfig: { 28 | type: 'aspect_ratio', 29 | smartMatch: false, // Wan 2.5 不支持智能匹配 30 | visualize: true, 31 | extractRatio: (value) => { 32 | const [w, h] = value.split(':').map(Number) 33 | return w / h 34 | }, 35 | qualityOptions: [ 36 | { value: '480p', label: '480P' }, 37 | { value: '720p', label: '720P' }, 38 | { value: '1080p', label: '1080P' } 39 | ], 40 | qualityKey: 'wanResolution' 41 | }, 42 | options: [ 43 | { value: '16:9', label: '16:9' }, 44 | { value: '9:16', label: '9:16' }, 45 | { value: '1:1', label: '1:1' } 46 | ], 47 | // 图生视频时隐藏比例选项(只显示分辨率) 48 | hidden: (values) => values.uploadedImages && values.uploadedImages.length > 0, 49 | className: 'min-w-[100px]' 50 | }, 51 | { 52 | id: 'falWan25Resolution', 53 | type: 'dropdown', 54 | defaultValue: '1080p', 55 | // 图生视频时单独显示分辨率 56 | resolutionConfig: { 57 | type: 'resolution', 58 | smartMatch: false, 59 | visualize: false 60 | }, 61 | options: [ 62 | { value: '480p', label: '480P' }, 63 | { value: '720p', label: '720P' }, 64 | { value: '1080p', label: '1080P' } 65 | ], 66 | // 只在图生视频时显示(文生视频时由 wanAspectRatio 的面板显示) 67 | hidden: (values) => !values.uploadedImages || values.uploadedImages.length === 0 68 | }, 69 | { 70 | id: 'falWan25PromptExpansion', 71 | type: 'toggle', 72 | label: '提示词扩展', 73 | defaultValue: true 74 | } 75 | ] 76 | -------------------------------------------------------------------------------- /src/utils/polling.ts: -------------------------------------------------------------------------------- 1 | import { calculateProgress } from './progress' 2 | 3 | /** 4 | * 通用轮询配置 5 | */ 6 | export interface PollingOptions { 7 | /** 检查函数:返回当前状态和可能的结果 */ 8 | checkFn: () => Promise<{ status: string; result?: T }> 9 | /** 判断是否完成 */ 10 | isComplete: (status: string) => boolean 11 | /** 判断是否失败 */ 12 | isFailed: (status: string) => boolean 13 | /** 进度回调 */ 14 | onProgress?: (progress: number, status: string) => void 15 | /** 轮询间隔(毫秒) */ 16 | interval?: number 17 | /** 最大轮询次数 */ 18 | maxAttempts?: number 19 | /** 预期轮询次数(用于进度计算) */ 20 | estimatedAttempts?: number 21 | } 22 | 23 | /** 24 | * 通用轮询函数 25 | * 26 | * @example 27 | * ```typescript 28 | * const result = await pollUntilComplete({ 29 | * checkFn: () => this.checkStatus(taskId), 30 | * isComplete: (s) => s === 'COMPLETED', 31 | * isFailed: (s) => s === 'FAILED', 32 | * onProgress: (p) => logInfo(`Progress: ${p}%`, {}), 33 | * interval: 3000, 34 | * estimatedAttempts: 40 35 | * }) 36 | * ``` 37 | */ 38 | export async function pollUntilComplete( 39 | options: PollingOptions 40 | ): Promise { 41 | const { 42 | checkFn, 43 | isComplete, 44 | isFailed, 45 | onProgress, 46 | interval = 1000, 47 | maxAttempts = 120, 48 | estimatedAttempts = 40 49 | } = options 50 | 51 | let attempts = 0 52 | 53 | while (attempts < maxAttempts) { 54 | const { status, result } = await checkFn() 55 | 56 | // 计算进度(使用统一的渐近式算法) 57 | const progress = calculateProgress(attempts, estimatedAttempts) 58 | 59 | if (onProgress) { 60 | onProgress(progress, status) 61 | } 62 | 63 | if (isComplete(status)) { 64 | if (!result) { 65 | throw new Error('Task completed but no result returned') 66 | } 67 | return result 68 | } 69 | 70 | if (isFailed(status)) { 71 | throw new Error(`Task failed with status: ${status}`) 72 | } 73 | 74 | await new Promise(resolve => setTimeout(resolve, interval)) 75 | attempts++ 76 | } 77 | 78 | throw new Error('Polling timeout') 79 | } 80 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/大语言/创建嵌入请求.md: -------------------------------------------------------------------------------- 1 | # 创建嵌入请求 2 | 3 | 创建一个表示输入文本的嵌入向量。 4 | 5 | ## 请求示例 6 | 7 | **cURL** 8 | ```bash 9 | curl --request POST \ 10 | --url https://api.ppinfra.com/openai/v1/embeddings \ 11 | --header 'Authorization: ' \ 12 | --header 'Content-Type: application/json' \ 13 | --data ' 14 | { 15 | "input": {}, 16 | "model": {}, 17 | "encoding_format": "" 18 | } 19 | ' 20 | ``` 21 | 22 | **请求体示例** 23 | ```json 24 | { 25 | "input": {}, 26 | "model": {}, 27 | "encoding_format": "" 28 | } 29 | ``` 30 | 31 | **响应示例** 32 | ```json 33 | { 34 | "object": "", 35 | "data": [ 36 | { 37 | "index": 123, 38 | "embedding": [ 39 | {} 40 | ], 41 | "object": "" 42 | } 43 | ], 44 | "model": "", 45 | "usage": { 46 | "prompt_tokens": 123, 47 | "total_tokens": 123 48 | } 49 | } 50 | ``` 51 | 52 | ## 请求头 53 | 54 | | 参数 | 类型 | 是否必需 | 描述 | 55 | | :--- | :--- | :--- | :--- | 56 | | `Content-Type` | `string` | 是 | 必须为 `application/json`。 | 57 | | `Authorization` | `string` | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 58 | 59 | ## 请求体 60 | 61 | | 参数 | 类型 | 是否必需 | 描述 | 62 | | :--- | :--- | :--- | :--- | 63 | | `input` | `string` \| `array` | 是 | 要嵌入的输入文本,编码为字符串或 tokens 数组。要在单个请求中嵌入多个输入,请传入字符串数组或 tokens 数组的数组。输入不得超过模型的最大输入 tokens(text-embedding-ada-002 的最大输入为 8192 个 tokens),不能是空字符串,且任何数组的维度不得超过 2048。 | 64 | | `model` | `string` | 是 | 要使用的模型 ID。枚举值:`baai/bge-m3`。 | 65 | | `encoding_format` | `string` | 否 | 返回嵌入的格式。可以为 `float` 或 `base64`。 | 66 | 67 | ## 响应参数 68 | 69 | | 参数 | 类型 | 是否必需 | 描述 | 70 | | :--- | :--- | :--- | :--- | 71 | | `object` | `string` | 是 | 固定为 `list`。 | 72 | | `data` | `array` | 是 | 模型生成的嵌入列表。 | 73 | | `model` | `string` | 是 | 使用的模型 ID。 | 74 | | `usage` | `object` | 是 | 使用情况信息。 | 75 | 76 | ### data 对象属性 77 | 78 | | 参数 | 类型 | 是否必需 | 描述 | 79 | | :--- | :--- | :--- | :--- | 80 | | `index` | `integer` | 是 | 嵌入向量的索引。 | 81 | | `embedding` | `array` | 是 | 嵌入向量。 | 82 | | `object` | `string` | 是 | 固定为 `embedding`。 | 83 | 84 | ### usage 对象属性 85 | 86 | | 参数 | 类型 | 是否必需 | 描述 | 87 | | :--- | :--- | :--- | :--- | 88 | | `prompt_tokens` | `integer` | 是 | prompt tokens 的数量。 | 89 | | `total_tokens` | `integer` | 是 | 总 tokens 的数量。 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/视频/Vidu_2.0_图生视频.md: -------------------------------------------------------------------------------- 1 | # Vidu 2.0 图生视频 2 | 3 | Vidu 2.0 图生视频将静态图像转换为动态视频,融入创意故事叙述和动画效果。 4 | 5 | 这是一个**异步**API,只会返回异步任务的 `task_id`。您应该使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来检索视频生成结果。 6 | 7 | ## 接口信息 8 | 9 | **请求方法**: POST 10 | **请求地址**: `https://api.ppinfra.com/v3/async/vidu-2.0-img2video` 11 | 12 | ## 请求示例 13 | 14 | ```bash 15 | curl --request POST \ 16 | --url https://api.ppinfra.com/v3/async/vidu-2.0-img2video \ 17 | --header 'Authorization: ' \ 18 | --header 'Content-Type: ' \ 19 | --data ' 20 | { 21 | "images": [ 22 | "" 23 | ], 24 | "prompt": "", 25 | "duration": 123, 26 | "seed": 123, 27 | "resolution": "", 28 | "movement_amplitude": "", 29 | "bgm": true 30 | } 31 | ' 32 | ``` 33 | 34 | ## 响应示例 35 | 36 | ```json 37 | { 38 | "task_id": "" 39 | } 40 | ``` 41 | 42 | ## 请求头 43 | 44 | | 参数 | 类型 | 是否必需 | 说明 | 45 | | :--- | :--- | :--- | :--- | 46 | | `Content-Type` | string | 是 | 枚举值: `application/json` | 47 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 48 | 49 | ## 请求体 50 | 51 | | 参数 | 类型 | 是否必需 | 说明 | 52 | | :--- | :--- | :--- | :--- | 53 | | `images` | string[] | 是 | 用作生成视频起始帧的图像。**图像字段要求:**
• 仅接受 1 张图像
• 支持公共 URL 或 Base64 格式
• 支持格式:png、jpeg、jpg、webp
• 图像宽高比必须小于 1:4 或 4:1
• 所有图像限制为 50MB
• base64 解码后的长度必须小于 10MB,且必须包含适当的内容类型字符串。例如:`data:image/png;base64,{base64_encode}` | 54 | | `prompt` | string | 否 | 视频生成的文本提示词,最大长度为 1500 个字符。 | 55 | | `duration` | integer | 否 | 视频持续时间(秒)。默认为 4 秒,可选 `4` 秒或 `8` 秒。 | 56 | | `seed` | integer | 否 | 视频生成的随机种子。
• 默认为随机种子数值
• 手动设置的值将覆盖默认的随机种子 | 57 | | `resolution` | string | 否 | 基于时长的分辨率选项:
• 4秒:默认 360p,可选 `360p`、`720p`、`1080p`
• 8秒:默认 720p,可选 `720p` | 58 | | `movement_amplitude` | string | 否 | 画面中物体的运动幅度。默认值:`auto`
可选值:`auto`、`small`、`medium`、`large` | 59 | | `bgm` | boolean | 否 | 是否为生成的视频添加背景音乐。默认值:`false`
可选值:`true`、`false`
当设置为 `true` 时,系统将自动添加合适的 BGM。BGM 无时长限制,系统会自动适配。 | 60 | 61 | ## 响应 62 | 63 | | 参数 | 类型 | 是否必需 | 说明 | 64 | | :--- | :--- | :--- | :--- | 65 | | `task_id` | string | 是 | 异步任务的 `task_id`。您应该使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果。 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/视频/Seedance_V1_Lite_图生视频.md: -------------------------------------------------------------------------------- 1 | # Seedance V1 Lite 图生视频 2 | 3 | Seedance V1 Lite 是一个 AI 视频模型,专为生成连贯的多镜头视频而设计,提供流畅的运动和对详细提示的精确遵循。它支持 480p、720p 和 1080p 的分辨率。 4 | 5 | 本接口支持个人认证及企业认证用户调用。请参见 [实名认证](/docs/support/identity-verification),完成个人用户认证或企业用户认证,以确保可以正常使用本功能。 6 | 7 | ## 请求示例 8 | 9 | **请求方法**:POST 10 | **请求地址**:`https://api.ppinfra.com/v3/async/seedance-v1-lite-i2v` 11 | 12 | **cURL 示例**: 13 | ```bash 14 | curl --request POST \ 15 | --url https://api.ppinfra.com/v3/async/seedance-v1-lite-i2v \ 16 | --header 'Authorization: ' \ 17 | --header 'Content-Type: application/json' \ 18 | --data ' 19 | { 20 | "prompt": "", 21 | "image": "", 22 | "resolution": "", 23 | "aspect_ratio": "", 24 | "last_image": "", 25 | "camera_fixed": true, 26 | "seed": 123, 27 | "duration": 123 28 | } 29 | ' 30 | ``` 31 | 32 | **响应示例**: 33 | ```json 34 | { 35 | "task_id": "" 36 | } 37 | ``` 38 | 39 | ## 请求头 40 | 41 | | 参数名 | 类型 | 必填 | 说明 | 42 | | :--- | :--- | :--- | :--- | 43 | | `Content-Type` | string | 是 | 必须为 `application/json`。 | 44 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 45 | 46 | ## 请求体 47 | 48 | | 参数名 | 类型 | 必填 | 默认值 | 说明 | 49 | | :--- | :--- | :--- | :--- | :--- | 50 | | `prompt` | string | 否 | - | 视频生成的文本提示(正面提示)。支持中英文,建议不超过500字。 | 51 | | `image` | string | 是 | - | 输入图像,支持 URL 和 Base64 格式。
• 图片格式:`jpeg`, `png`, `webp`, `bmp`, `tiff`, `gif`。
• 文件大小 ≤ 30MB。
• 短边 > 300 像素,长边 < 6000 像素。
• 宽高比在 0.4 到 2.5 之间。 | 52 | | `resolution` | string | 是 | - | 视频质量。可选值:`480p`, `720p`, `1080p`。 | 53 | | `aspect_ratio` | string | 否 | `"16:9"` | 生成视频的长宽比。可选值:`21:9`, `16:9`, `4:3`, `1:1`, `3:4`, `9:16`, `9:21`。 | 54 | | `last_image` | string | 否 | - | 结束图像,支持 URL 和 Base64 格式。要求与 `image` 参数相同。
首尾帧图片可相同。若宽高比不一致,以首帧图片为主,尾帧图片会自动裁剪适配。 | 55 | | `camera_fixed` | boolean | 否 | `false` | 确定相机位置是否应保持固定。 | 56 | | `seed` | integer | 否 | `-1` | 用于生成的随机种子。`-1` 表示使用随机种子。 | 57 | | `duration` | integer | 否 | `5` | 指定生成视频的长度(秒)。可选值:`5`, `10`。 | 58 | 59 | ## 响应 60 | 61 | | 参数名 | 类型 | 必填 | 说明 | 62 | | :--- | :--- | :--- | :--- | 63 | | `task_id` | string | 是 | 异步任务的 ID。请使用此 `task_id` 调用 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果。 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/视频/Vidu_Q1_图生视频.md: -------------------------------------------------------------------------------- 1 | # Vidu Q1 图生视频 2 | 3 | Vidu Q1 图生视频将静态图像转换为动态视频,融入创意故事叙述和动画效果。 4 | 5 | 这是一个**异步**API,调用后只会返回异步任务的 `task_id`。您需要使用该 `task_id` 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来检索视频生成结果。 6 | 7 | ## 接口调用示例 8 | 9 | **请求示例** 10 | ```bash 11 | curl --request POST \ 12 | --url https://api.ppinfra.com/v3/async/vidu-q1-img2video \ 13 | --header 'Authorization: ' \ 14 | --header 'Content-Type: application/json' \ 15 | --data ' 16 | { 17 | "images": [ 18 | "" 19 | ], 20 | "prompt": "", 21 | "duration": 123, 22 | "seed": 123, 23 | "resolution": "", 24 | "movement_amplitude": "", 25 | "bgm": true 26 | } 27 | ' 28 | ``` 29 | 30 | **响应示例** 31 | ```json 32 | { 33 | "task_id": "" 34 | } 35 | ``` 36 | 37 | ## 请求头 38 | 39 | | 参数 | 类型 | 是否必需 | 说明 | 40 | | :--- | :--- | :--- | :--- | 41 | | `Content-Type` | string | 是 | 必须为 `application/json`。 | 42 | | `Authorization` | string | 是 | Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 | 43 | 44 | ## 请求体 45 | 46 | | 参数 | 类型 | 是否必需 | 说明 | 47 | | :--- | :--- | :--- | :--- | 48 | | `images` | string[] | 是 | 用作生成视频起始帧的图像。
**要求:**
• 仅接受 1 张图像。
• 支持公共 URL 或 Base64 格式。
• 支持格式:png、jpeg、jpg、webp。
• 图像宽高比必须小于 1:4 或 4:1。
• 所有图像限制为 50MB。
• Base64 字符串解码后的长度必须小于 10MB,且必须包含适当的内容类型前缀,例如:`data:image/png;base64,{base64_encode}`。 | 49 | | `prompt` | string | 是 | 视频生成的文本提示词,最大长度为 1500 个字符。 | 50 | | `duration` | integer | 否 | 视频持续时间(秒)。
**默认值:** `5`
**当前支持选项:** `5` | 51 | | `seed` | integer | 否 | 视频生成的随机种子。
**默认值:** 随机生成
手动设置的值将覆盖默认的随机种子。 | 52 | | `resolution` | string | 否 | 输出视频分辨率。
**默认值:** `1080p`
**当前支持选项:** `1080p` | 53 | | `movement_amplitude` | string | 否 | 画面中物体的运动幅度。
**默认值:** `auto`
**可选值:** `auto`、`small`、`medium`、`large` | 54 | | `bgm` | boolean | 否 | 是否为生成的视频添加背景音乐。
**默认值:** `false`
**可选值:** `true`、`false`
当设置为 `true` 时,系统将自动添加合适的 BGM。BGM 无时长限制,系统会自动适配。 | 55 | 56 | ## 响应 57 | 58 | | 参数 | 类型 | 是否必需 | 说明 | 59 | | :--- | :--- | :--- | :--- | 60 | | `task_id` | string | 是 | 异步任务的 ID。您需要使用此 ID 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果。 | 61 | 62 | [Vidu Q1 文生视频](/docs/models/reference-vidu-q1-txt2video) | [Vidu Q1 首末帧](/docs/models/reference-vidu-q1-startend2video) -------------------------------------------------------------------------------- /src/models/seedance-v1.ts: -------------------------------------------------------------------------------- 1 | import { ParamDef } from '../types/schema' 2 | 3 | /** 4 | * Seedance V1 模型参数定义 5 | */ 6 | export const seedanceV1Params: ParamDef[] = [ 7 | { 8 | id: 'ppioSeedanceV1Variant', 9 | type: 'dropdown', 10 | label: '版本', 11 | options: [ 12 | { value: 'lite', label: 'Lite' }, 13 | { value: 'pro', label: 'Pro' } 14 | ], 15 | hidden: (values) => values.selectedModel !== 'seedance-v1' 16 | }, 17 | { 18 | id: 'ppioSeedanceV1VideoDuration', 19 | type: 'dropdown', 20 | label: '时长', 21 | defaultValue: 5, // Seedance 默认 5 秒 22 | options: [ 23 | { value: 5, label: '5s' }, 24 | { value: 10, label: '10s' } 25 | ] 26 | }, 27 | { 28 | id: 'ppioSeedanceV1AspectRatio', 29 | type: 'dropdown', 30 | label: '分辨率', 31 | defaultValue: '16:9', 32 | // 分辨率配置:启用智能匹配、可视化,并将分辨率作为质量选项 33 | resolutionConfig: { 34 | type: 'aspect_ratio', 35 | smartMatch: true, 36 | visualize: true, 37 | extractRatio: (value) => { 38 | if (value === 'smart') return null 39 | const [w, h] = value.split(':').map(Number) 40 | return w / h 41 | }, 42 | // 指定分辨率参数的key 43 | qualityKey: 'ppioSeedanceV1Resolution', 44 | // 分辨率选项(作为质量选项显示) 45 | qualityOptions: [ 46 | { value: '480p', label: '480P' }, 47 | { value: '720p', label: '720P' }, 48 | { value: '1080p', label: '1080P' } 49 | ] 50 | }, 51 | // 当上传图片时自动切换到智能选项 52 | autoSwitch: { 53 | condition: (values) => values.uploadedImages && values.uploadedImages.length > 0, 54 | value: 'smart', 55 | watchKeys: ['uploadedImages'] // 只监听图片数量变化,避免用户手动选择比例时被强制切换 56 | }, 57 | options: [ 58 | { value: 'smart', label: '智能' }, 59 | ...['21:9', '16:9', '4:3', '1:1', '3:4', '9:16', '9:21'].map(v => ({ value: v, label: v })) 60 | ] 61 | }, 62 | { 63 | id: 'ppioSeedanceV1CameraFixed', 64 | type: 'toggle', 65 | label: '相机固定' 66 | } 67 | ] 68 | -------------------------------------------------------------------------------- /docs/api/派欧云PPIO/视频/Minimax_Hailuo_2.3_文生视频.md: -------------------------------------------------------------------------------- 1 | # Minimax Hailuo 2.3 文生视频 2 | 3 | Minimax Hailuo 2.3 是全新升级的视频生成模型,在肢体动作、物理效果和对指令的理解与执行能力等方面表现更为出色。 4 | 5 | 这是一个**异步**API,只会返回异步任务的 task\_id。您应该使用该 task\_id 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 来检索视频生成结果。 6 | 7 | ## 请求示例 8 | 9 | **请求** 10 | 11 | ```bash 12 | curl --request POST \ 13 | --url https://api.ppinfra.com/v3/async/minimax-hailuo-2.3-t2v \ 14 | --header 'Authorization: ' \ 15 | --header 'Content-Type: ' \ 16 | --data ' 17 | { 18 | "prompt": "", 19 | "duration": 123, 20 | "resolution": "", 21 | "enable_prompt_expansion": true 22 | } 23 | ' 24 | ``` 25 | 26 | **响应** 27 | 28 | ```json 29 | { 30 | "task_id": "" 31 | } 32 | ``` 33 | 34 | ## 请求头 35 | 36 | ### Content-Type 37 | * **类型**: string 38 | * **必需**: 是 39 | * **枚举值**: `application/json` 40 | 41 | ### Authorization 42 | * **类型**: string 43 | * **必需**: 是 44 | * **说明**: Bearer 身份验证格式,例如:`Bearer {{API 密钥}}`。 45 | 46 | ## 请求体 47 | 48 | ### prompt 49 | * **类型**: string 50 | * **必需**: 是 51 | * **范围**: `1 <= x <= 2000` 52 | * **说明**: 指导生成所需的提示词文本。支持 15 种运镜指令: 53 | * **左右移**: `[左移]`, `[右移]` 54 | * **左右摇**: `[左摇]`, `[右摇]` 55 | * **推拉**: `[推进]`, `[拉远]` 56 | * **升降**: `[上升]`, `[下降]` 57 | * **上下摇**: `[上摇]`, `[下摇]` 58 | * **变焦**: `[变焦推近]`, `[变焦拉远]` 59 | * **其他**: `[晃动]`, `[跟随]`, `[固定]` 60 | 61 | **使用规则**: 62 | * **组合运镜**: 同一组 `[]` 内的多个指令会同时生效,如 `[左摇,上升]`,建议组合不超过 3 个。 63 | * **顺序运镜**: prompt 中前后出现的指令会依次生效,如 `“…[推进], 然后…[拉远]”`。 64 | * **自然语言**: 也支持通过自然语言描述运镜,但使用标准指令能获得更准确的响应。 65 | 66 | ### duration 67 | * **类型**: integer 68 | * **必需**: 否 69 | * **默认值**: `6` 70 | * **可选值**: `6`, `10` 71 | * **说明**: 生成视频的时长(秒)。 72 | 73 | ### resolution 74 | * **类型**: string 75 | * **必需**: 否 76 | * **默认值**: `768P` 77 | * **说明**: 生成视频的分辨率。 78 | * 6 秒视频支持:`768P`、`1080P` 79 | * 10 秒视频仅支持:`768P` 80 | 81 | ### enable_prompt_expansion 82 | * **类型**: boolean 83 | * **必需**: 否 84 | * **默认值**: `true` 85 | * **说明**: 是否启用提示词优化。 86 | 87 | ## 响应 88 | 89 | ### task_id 90 | * **类型**: string 91 | * **必需**: 是 92 | * **说明**: 异步任务的 task\_id。您应该使用该 task\_id 请求 [查询任务结果 API](/docs/models/reference-get-async-task-result) 以获取生成结果。 --------------------------------------------------------------------------------