├── 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 |
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 |
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) 以获取生成结果。
--------------------------------------------------------------------------------