mirror of
https://github.com/Anil-matcha/Open-Generative-AI.git
synced 2026-08-31 01:40:10 +08:00
Sync Studio models and add all-category pickers
This commit is contained in:
@@ -841,23 +841,27 @@ export default function AudioStudio({
|
||||
|
||||
{isOpen && (
|
||||
<div className="absolute left-0 right-0 mt-1 z-50 bg-[#161618] border border-zinc-700 rounded shadow-3xl max-h-60 overflow-y-auto custom-scrollbar p-1">
|
||||
{schema.enum.map((opt) => (
|
||||
<button
|
||||
key={opt}
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setParams(prev => ({ ...prev, [key]: opt }));
|
||||
setOpenParamDropdown(null);
|
||||
}}
|
||||
className={`w-full text-left px-4 py-2.5 rounded text-xs font-bold transition-all border ${
|
||||
params[key] === opt
|
||||
? "text-primary bg-primary/10 border-primary/20"
|
||||
: "text-zinc-200 border-transparent hover:bg-zinc-900 hover:text-white"
|
||||
}`}
|
||||
>
|
||||
{opt}
|
||||
</button>
|
||||
))}
|
||||
{schema.enum.map((opt) => {
|
||||
const optionValue = typeof opt === "object" ? opt.value : opt;
|
||||
const optionLabel = typeof opt === "object" ? (opt.label || opt.value) : opt;
|
||||
return (
|
||||
<button
|
||||
key={optionValue}
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setParams(prev => ({ ...prev, [key]: optionValue }));
|
||||
setOpenParamDropdown(null);
|
||||
}}
|
||||
className={`w-full text-left px-4 py-2.5 rounded text-xs font-bold transition-all border ${
|
||||
params[key] === optionValue
|
||||
? "text-primary bg-primary/10 border-primary/20"
|
||||
: "text-zinc-200 border-transparent hover:bg-zinc-900 hover:text-white"
|
||||
}`}
|
||||
>
|
||||
{optionLabel}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
{schema.description && (
|
||||
|
||||
@@ -582,13 +582,32 @@ const PROVIDER_LOGOS = {
|
||||
|
||||
const invertLogos = ['openai', 'blackforest', 'runway', 'ideogram', 'lightricks', 'grok'];
|
||||
|
||||
function ModelDropdown({ models, selectedModel, onSelect, onClose }) {
|
||||
function ModelDropdown({ selectedModel, onSelect, onClose }) {
|
||||
const [search, setSearch] = useState("");
|
||||
|
||||
// Find current model's provider to pre-select the provider tab ("slide")
|
||||
const currentModelObj = models.find((m) => m.id === selectedModel);
|
||||
const initialProvider = currentModelObj?.provider || "all";
|
||||
const [selectedProvider, setSelectedProvider] = useState(initialProvider);
|
||||
const modelCategories = [
|
||||
{
|
||||
id: "all",
|
||||
label: "All",
|
||||
entries: [
|
||||
...t2iModels.map((model) => ({ model, category: "t2i" })),
|
||||
...i2iModels.map((model) => ({ model, category: "i2i" })),
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "t2i",
|
||||
label: "Text to Image",
|
||||
entries: t2iModels.map((model) => ({ model, category: "t2i" })),
|
||||
},
|
||||
{
|
||||
id: "i2i",
|
||||
label: "Image to Image",
|
||||
entries: i2iModels.map((model) => ({ model, category: "i2i" })),
|
||||
},
|
||||
];
|
||||
const [selectedCategory, setSelectedCategory] = useState("all");
|
||||
const [selectedProvider, setSelectedProvider] = useState("all");
|
||||
const activeCategory = modelCategories.find((category) => category.id === selectedCategory) || modelCategories[0];
|
||||
const modelEntries = activeCategory.entries;
|
||||
|
||||
const activeItemRef = useRef(null);
|
||||
|
||||
@@ -639,7 +658,7 @@ function ModelDropdown({ models, selectedModel, onSelect, onClose }) {
|
||||
const availableProviders = [];
|
||||
const seenProviders = new Set();
|
||||
|
||||
models.forEach(m => {
|
||||
modelEntries.forEach(({ model: m }) => {
|
||||
const pId = m.provider || 'muapi';
|
||||
const pName = m.provider_name || 'Muapi';
|
||||
if (!seenProviders.has(pId)) {
|
||||
@@ -648,7 +667,7 @@ function ModelDropdown({ models, selectedModel, onSelect, onClose }) {
|
||||
}
|
||||
});
|
||||
|
||||
const filtered = models.filter((m) => {
|
||||
const filtered = modelEntries.filter(({ model: m }) => {
|
||||
// 1. Filter by provider tab
|
||||
if (selectedProvider !== "all") {
|
||||
const pId = m.provider || 'muapi';
|
||||
@@ -714,7 +733,26 @@ function ModelDropdown({ models, selectedModel, onSelect, onClose }) {
|
||||
|
||||
{/* Right Pane: Search input + Models list */}
|
||||
<div className="flex-1 flex flex-col gap-2 min-w-0">
|
||||
<div className="border-b border-white/5 shrink-0 pb-2">
|
||||
<div className="border-b border-white/5 shrink-0 pb-2 space-y-2">
|
||||
<div className="flex gap-1.5 overflow-x-auto custom-scrollbar pb-0.5">
|
||||
{modelCategories.map((category) => (
|
||||
<button
|
||||
key={category.id}
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setSelectedCategory(category.id);
|
||||
setSelectedProvider("all");
|
||||
}}
|
||||
className={`shrink-0 rounded-lg px-2.5 py-1.5 text-[10px] font-bold transition-colors border ${
|
||||
selectedCategory === category.id
|
||||
? "bg-primary/15 text-primary border-primary/30"
|
||||
: "bg-white/[0.02] text-white/50 border-white/[0.04] hover:bg-white/5 hover:text-white"
|
||||
}`}
|
||||
>
|
||||
{category.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex items-center gap-3 bg-white/5 rounded-xl px-4 py-2 border border-white/5 focus-within:border-primary/50 transition-colors">
|
||||
<svg
|
||||
width="14"
|
||||
@@ -740,7 +778,7 @@ function ModelDropdown({ models, selectedModel, onSelect, onClose }) {
|
||||
</div>
|
||||
|
||||
<div className="text-xs font-semibold text-secondary py-1 shrink-0 flex items-center justify-between">
|
||||
<span>Available models</span>
|
||||
<span>{activeCategory.label} models</span>
|
||||
{selectedProvider !== "all" && (
|
||||
<span className="text-[10px] bg-white/5 px-2 py-0.5 rounded text-white/60">
|
||||
{availableProviders.find(p => p.id === selectedProvider)?.name || selectedProvider}
|
||||
@@ -754,13 +792,13 @@ function ModelDropdown({ models, selectedModel, onSelect, onClose }) {
|
||||
No models found
|
||||
</div>
|
||||
) : (
|
||||
filtered.map((m) => (
|
||||
filtered.map(({ model: m, category }) => (
|
||||
<div
|
||||
key={m.id}
|
||||
key={`${category}:${m.id}`}
|
||||
ref={selectedModel === m.id ? activeItemRef : null}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onSelect(m);
|
||||
onSelect(m, category);
|
||||
onClose();
|
||||
}}
|
||||
className={`flex items-center justify-between p-3 hover:bg-white/5 rounded-lg cursor-pointer transition-all border border-transparent hover:border-white/5 ${
|
||||
@@ -1149,23 +1187,30 @@ export default function ImageStudio({
|
||||
}, [selectedModelId]);
|
||||
|
||||
// ── Model selection ──────────────────────────────────────────────────────
|
||||
const handleModelSelect = (m) => {
|
||||
const ars = imageMode
|
||||
const handleModelSelect = (m, category = imageMode ? "i2i" : "t2i") => {
|
||||
const nextImageMode = category === "i2i";
|
||||
const ars = nextImageMode
|
||||
? getAspectRatiosForI2IModel(m.id)
|
||||
: getAspectRatiosForModel(m.id);
|
||||
const resolutions = imageMode
|
||||
const resolutions = nextImageMode
|
||||
? getResolutionsForI2IModel(m.id)
|
||||
: getResolutionsForModel(m.id);
|
||||
if (!nextImageMode && imageMode) {
|
||||
setUploadedImageUrls([]);
|
||||
setSwapImageUrl(null);
|
||||
}
|
||||
setImageMode(nextImageMode);
|
||||
setSelectedModelId(m.id);
|
||||
setSelectedModelName(m.name);
|
||||
setSelectedAr(ars[0] || "1:1");
|
||||
setSelectedQuality(resolutions[0] || null);
|
||||
setSwapImageUrl(null);
|
||||
if (imageMode) {
|
||||
if (nextImageMode) {
|
||||
setMaxImages(getMaxImagesForI2IModel(m.id));
|
||||
const effects = getEffectsForI2IModel(m.id);
|
||||
setSelectedEffect(effects.length > 0 ? (getDefaultEffectForI2IModel(m.id) || effects[0]) : "");
|
||||
} else {
|
||||
setMaxImages(1);
|
||||
setSelectedEffect("");
|
||||
}
|
||||
};
|
||||
@@ -1542,7 +1587,6 @@ export default function ImageStudio({
|
||||
>
|
||||
<PromptPopoverHeader>Model</PromptPopoverHeader>
|
||||
<ModelDropdown
|
||||
models={currentModels}
|
||||
selectedModel={selectedModelId}
|
||||
onSelect={handleModelSelect}
|
||||
onClose={() => setDropdownOpen(null)}
|
||||
|
||||
@@ -146,15 +146,38 @@ const PROVIDER_LOGOS = {
|
||||
|
||||
const invertLogos = ['openai', 'blackforest', 'runway', 'ideogram', 'lightricks', 'grok'];
|
||||
|
||||
function ModelDropdown({ imageMode, selectedModel, onSelect, onClose }) {
|
||||
function ModelDropdown({ selectedModel, onSelect, onClose }) {
|
||||
const [search, setSearch] = useState("");
|
||||
const generationModels = imageMode ? i2vModels : t2vModels;
|
||||
|
||||
// Find current model's provider to pre-select the provider tab ("slide")
|
||||
const allCurrentModels = [...generationModels, ...v2vModels];
|
||||
const currentModelObj = allCurrentModels.find((m) => m.id === selectedModel);
|
||||
const initialProvider = currentModelObj?.provider || "all";
|
||||
const [selectedProvider, setSelectedProvider] = useState(initialProvider);
|
||||
const modelCategories = [
|
||||
{
|
||||
id: "all",
|
||||
label: "All",
|
||||
entries: [
|
||||
...t2vModels.map((model) => ({ model, category: "t2v" })),
|
||||
...i2vModels.map((model) => ({ model, category: "i2v" })),
|
||||
...v2vModels.map((model) => ({ model, category: "v2v" })),
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "t2v",
|
||||
label: "Text to Video",
|
||||
entries: t2vModels.map((model) => ({ model, category: "t2v" })),
|
||||
},
|
||||
{
|
||||
id: "i2v",
|
||||
label: "Image to Video",
|
||||
entries: i2vModels.map((model) => ({ model, category: "i2v" })),
|
||||
},
|
||||
{
|
||||
id: "v2v",
|
||||
label: "Video Tools",
|
||||
entries: v2vModels.map((model) => ({ model, category: "v2v" })),
|
||||
},
|
||||
];
|
||||
const [selectedCategory, setSelectedCategory] = useState("all");
|
||||
const [selectedProvider, setSelectedProvider] = useState("all");
|
||||
const activeCategory = modelCategories.find((category) => category.id === selectedCategory) || modelCategories[0];
|
||||
const modelEntries = activeCategory.entries;
|
||||
|
||||
const activeItemRef = useRef(null);
|
||||
|
||||
@@ -205,7 +228,7 @@ function ModelDropdown({ imageMode, selectedModel, onSelect, onClose }) {
|
||||
const availableProviders = [];
|
||||
const seenProviders = new Set();
|
||||
|
||||
allCurrentModels.forEach(m => {
|
||||
modelEntries.forEach(({ model: m }) => {
|
||||
const pId = m.provider || 'muapi';
|
||||
const pName = m.provider_name || 'Muapi';
|
||||
if (!seenProviders.has(pId)) {
|
||||
@@ -216,7 +239,7 @@ function ModelDropdown({ imageMode, selectedModel, onSelect, onClose }) {
|
||||
|
||||
const lf = search.toLowerCase();
|
||||
|
||||
const filterFn = (m) => {
|
||||
const filterFn = ({ model: m }) => {
|
||||
// 1. Filter by provider tab
|
||||
if (selectedProvider !== "all") {
|
||||
const pId = m.provider || 'muapi';
|
||||
@@ -229,8 +252,8 @@ function ModelDropdown({ imageMode, selectedModel, onSelect, onClose }) {
|
||||
);
|
||||
};
|
||||
|
||||
const filteredMain = generationModels.filter(filterFn);
|
||||
const filteredV2V = v2vModels.filter(filterFn);
|
||||
const filteredMain = modelEntries.filter(filterFn).filter(({ category }) => category !== "v2v");
|
||||
const filteredV2V = modelEntries.filter(filterFn).filter(({ category }) => category === "v2v");
|
||||
|
||||
const getIconColor = (m, isV2V) => {
|
||||
if (isV2V) return "bg-orange-500/10 text-orange-400 border-orange-500/10";
|
||||
@@ -240,14 +263,16 @@ function ModelDropdown({ imageMode, selectedModel, onSelect, onClose }) {
|
||||
return "bg-primary/10 text-primary border-primary/10";
|
||||
};
|
||||
|
||||
const renderItem = (m, isV2V = false) => (
|
||||
const renderItem = ({ model: m, category }) => {
|
||||
const isV2V = category === "v2v";
|
||||
return (
|
||||
<div
|
||||
key={m.id}
|
||||
key={`${category}:${m.id}`}
|
||||
ref={selectedModel === m.id ? activeItemRef : null}
|
||||
className={`flex items-center justify-between p-3.5 hover:bg-white/5 rounded-2xl cursor-pointer transition-all border border-transparent hover:border-white/5 ${selectedModel === m.id ? "bg-white/5 border-white/5" : ""}`}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
onSelect(m, isV2V);
|
||||
onSelect(m, category);
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
@@ -286,7 +311,8 @@ function ModelDropdown({ imageMode, selectedModel, onSelect, onClose }) {
|
||||
</div>
|
||||
{selectedModel === m.id && <CheckSvg />}
|
||||
</div>
|
||||
);
|
||||
);
|
||||
};
|
||||
|
||||
const invertLogos = ['openai', 'blackforest', 'runway', 'ideogram', 'lightricks', 'grok'];
|
||||
|
||||
@@ -340,7 +366,26 @@ function ModelDropdown({ imageMode, selectedModel, onSelect, onClose }) {
|
||||
|
||||
{/* Right Pane: Search + Lists */}
|
||||
<div className="flex-1 flex flex-col gap-2 min-w-0">
|
||||
<div className="px-1 pb-2 border-b border-white/5 shrink-0">
|
||||
<div className="px-1 pb-2 border-b border-white/5 shrink-0 space-y-2">
|
||||
<div className="flex gap-1.5 overflow-x-auto custom-scrollbar pb-0.5">
|
||||
{modelCategories.map((category) => (
|
||||
<button
|
||||
key={category.id}
|
||||
type="button"
|
||||
onClick={() => {
|
||||
setSelectedCategory(category.id);
|
||||
setSelectedProvider("all");
|
||||
}}
|
||||
className={`shrink-0 rounded-lg px-2.5 py-1.5 text-[10px] font-bold transition-colors border ${
|
||||
selectedCategory === category.id
|
||||
? "bg-primary/15 text-primary border-primary/30"
|
||||
: "bg-white/[0.02] text-white/50 border-white/[0.04] hover:bg-white/5 hover:text-white"
|
||||
}`}
|
||||
>
|
||||
{category.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex items-center gap-3 bg-white/5 rounded-xl px-4 py-2 border border-white/5 focus-within:border-primary/50 transition-colors">
|
||||
<svg
|
||||
width="14"
|
||||
@@ -366,7 +411,7 @@ function ModelDropdown({ imageMode, selectedModel, onSelect, onClose }) {
|
||||
</div>
|
||||
|
||||
<div className="text-xs font-bold text-secondary px-2 py-1 shrink-0 flex items-center justify-between">
|
||||
<span>Video models</span>
|
||||
<span>{activeCategory.label} models</span>
|
||||
{selectedProvider !== "all" && (
|
||||
<span className="text-[10px] bg-white/5 px-2 py-0.5 rounded text-white/60">
|
||||
{availableProviders.find(p => p.id === selectedProvider)?.name || selectedProvider}
|
||||
@@ -381,13 +426,13 @@ function ModelDropdown({ imageMode, selectedModel, onSelect, onClose }) {
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{filteredMain.map((m) => renderItem(m, false))}
|
||||
{filteredMain.map((entry) => renderItem(entry))}
|
||||
{filteredV2V.length > 0 && (
|
||||
<>
|
||||
<div className="text-xs font-bold text-orange-400/70 px-3 py-2 mt-1 border-t border-white/5">
|
||||
Video Tools
|
||||
</div>
|
||||
{filteredV2V.map((m) => renderItem(m, true))}
|
||||
{filteredV2V.map((entry) => renderItem(entry))}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
@@ -1011,7 +1056,8 @@ export default function VideoStudio({
|
||||
|
||||
// ── model selection from dropdown ─────────────────────────────────────────
|
||||
const handleModelSelect = useCallback(
|
||||
(m, isV2V) => {
|
||||
(m, category = imageMode ? "i2v" : "t2v") => {
|
||||
const isV2V = category === "v2v";
|
||||
if (isV2V) {
|
||||
setV2vMode(true);
|
||||
setImageMode(false);
|
||||
@@ -1037,9 +1083,16 @@ export default function VideoStudio({
|
||||
setUploadedVideoName(null);
|
||||
setPromptDisabled(false);
|
||||
}
|
||||
const nextImageMode = category === "i2v";
|
||||
if (!nextImageMode && imageMode) {
|
||||
setUploadedImageUrl(null);
|
||||
setUploadedImageUrls([]);
|
||||
setUploadedEndImageUrl(null);
|
||||
}
|
||||
setImageMode(nextImageMode);
|
||||
setSelectedModel(m.id);
|
||||
setSelectedModelName(m.name);
|
||||
applyControlsForModel(m.id, imageMode, false);
|
||||
applyControlsForModel(m.id, nextImageMode, false);
|
||||
}
|
||||
},
|
||||
[v2vMode, imageMode, applyControlsForModel],
|
||||
@@ -1881,7 +1934,6 @@ export default function VideoStudio({
|
||||
>
|
||||
<PromptPopoverHeader>Model</PromptPopoverHeader>
|
||||
<ModelDropdown
|
||||
imageMode={imageMode}
|
||||
selectedModel={selectedModel}
|
||||
onSelect={handleModelSelect}
|
||||
onClose={() => setOpenDropdown(null)}
|
||||
|
||||
@@ -217,6 +217,7 @@ export const t2iModels = [
|
||||
{
|
||||
"id": "hidream-i1-fast",
|
||||
"name": "Hidream I1 Fast",
|
||||
"endpoint": "hidream_i1_fast_image",
|
||||
"inputs": {
|
||||
"prompt": {
|
||||
"examples": [
|
||||
@@ -264,6 +265,7 @@ export const t2iModels = [
|
||||
{
|
||||
"id": "hidream-i1-dev",
|
||||
"name": "Hidream I1 Dev",
|
||||
"endpoint": "hidream_i1_dev_image",
|
||||
"inputs": {
|
||||
"prompt": {
|
||||
"examples": [
|
||||
@@ -311,6 +313,7 @@ export const t2iModels = [
|
||||
{
|
||||
"id": "hidream-i1-full",
|
||||
"name": "Hidream I1 Full",
|
||||
"endpoint": "hidream_i1_full_image",
|
||||
"inputs": {
|
||||
"prompt": {
|
||||
"examples": [
|
||||
@@ -668,6 +671,7 @@ export const t2iModels = [
|
||||
{
|
||||
"id": "bytedance-seedream-v3",
|
||||
"name": "Bytedance Seedream v3",
|
||||
"endpoint": "bytedance-seedream-image",
|
||||
"inputs": {
|
||||
"prompt": {
|
||||
"examples": [
|
||||
@@ -3235,6 +3239,100 @@ export const t2iModels = [
|
||||
},
|
||||
"provider": "bytedance",
|
||||
"provider_name": "ByteDance"
|
||||
},
|
||||
{
|
||||
"id": "qwen3-text-to-image",
|
||||
"name": "Qwen 3 Text to Image",
|
||||
"endpoint": "qwen3-text-to-image",
|
||||
"inputs": {
|
||||
"prompt": {
|
||||
"type": "string",
|
||||
"title": "Prompt",
|
||||
"name": "prompt",
|
||||
"description": "Text prompt describing the image to generate."
|
||||
},
|
||||
"resolution": {
|
||||
"enum": ["1k", "2k"],
|
||||
"type": "string",
|
||||
"title": "Resolution",
|
||||
"name": "resolution",
|
||||
"default": "1k"
|
||||
},
|
||||
"aspect_ratio": {
|
||||
"enum": ["1:1", "3:2", "2:3", "4:3", "3:4", "16:9", "9:16", "21:9"],
|
||||
"type": "string",
|
||||
"title": "Aspect Ratio",
|
||||
"name": "aspect_ratio",
|
||||
"default": "16:9"
|
||||
},
|
||||
"output_format": {
|
||||
"enum": ["png", "jpeg"],
|
||||
"type": "string",
|
||||
"title": "Output Format",
|
||||
"name": "output_format",
|
||||
"default": "png"
|
||||
},
|
||||
"prompt_extend": {
|
||||
"type": "boolean",
|
||||
"title": "Intelligent Prompt Extend",
|
||||
"name": "prompt_extend",
|
||||
"default": true
|
||||
},
|
||||
"negative_prompt": {
|
||||
"type": "string",
|
||||
"title": "Negative Prompt",
|
||||
"name": "negative_prompt"
|
||||
}
|
||||
},
|
||||
"provider": "alibaba",
|
||||
"provider_name": "Alibaba"
|
||||
},
|
||||
{
|
||||
"id": "qwen3-pro-text-to-image",
|
||||
"name": "Qwen 3 Pro Text to Image",
|
||||
"endpoint": "qwen3-pro-text-to-image",
|
||||
"inputs": {
|
||||
"prompt": {
|
||||
"type": "string",
|
||||
"title": "Prompt",
|
||||
"name": "prompt",
|
||||
"description": "Text prompt describing the image to generate."
|
||||
},
|
||||
"resolution": {
|
||||
"enum": ["1k", "2k"],
|
||||
"type": "string",
|
||||
"title": "Resolution",
|
||||
"name": "resolution",
|
||||
"default": "1k"
|
||||
},
|
||||
"aspect_ratio": {
|
||||
"enum": ["1:1", "3:2", "2:3", "4:3", "3:4", "16:9", "9:16", "21:9"],
|
||||
"type": "string",
|
||||
"title": "Aspect Ratio",
|
||||
"name": "aspect_ratio",
|
||||
"default": "16:9"
|
||||
},
|
||||
"output_format": {
|
||||
"enum": ["png", "jpeg"],
|
||||
"type": "string",
|
||||
"title": "Output Format",
|
||||
"name": "output_format",
|
||||
"default": "png"
|
||||
},
|
||||
"prompt_extend": {
|
||||
"type": "boolean",
|
||||
"title": "Intelligent Prompt Extend",
|
||||
"name": "prompt_extend",
|
||||
"default": true
|
||||
},
|
||||
"negative_prompt": {
|
||||
"type": "string",
|
||||
"title": "Negative Prompt",
|
||||
"name": "negative_prompt"
|
||||
}
|
||||
},
|
||||
"provider": "alibaba",
|
||||
"provider_name": "Alibaba"
|
||||
}
|
||||
];
|
||||
|
||||
@@ -5534,6 +5632,7 @@ export const t2vModels = [
|
||||
"id": "wan2.7-text-to-video",
|
||||
"name": "Wan2.7",
|
||||
"endpoint": "wan2.7-text-to-video",
|
||||
"family": "wan2.7",
|
||||
"inputs": {
|
||||
"prompt": {
|
||||
"type": "string",
|
||||
@@ -7629,6 +7728,80 @@ export const t2vModels = [
|
||||
},
|
||||
"provider": "bytedance",
|
||||
"provider_name": "ByteDance"
|
||||
},
|
||||
{
|
||||
"id": "minimax-h3-text-to-video",
|
||||
"name": "MiniMax H3 Text to Video",
|
||||
"endpoint": "minimax-h3-text-to-video",
|
||||
"family": "minimax-h3",
|
||||
"inputs": {
|
||||
"prompt": {
|
||||
"type": "string",
|
||||
"title": "Prompt",
|
||||
"name": "prompt",
|
||||
"description": "Text prompt describing the video to generate."
|
||||
},
|
||||
"aspect_ratio": {
|
||||
"enum": ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16"],
|
||||
"type": "string",
|
||||
"title": "Aspect Ratio",
|
||||
"name": "aspect_ratio",
|
||||
"default": "16:9"
|
||||
},
|
||||
"resolution": {
|
||||
"enum": ["2k"],
|
||||
"type": "string",
|
||||
"title": "Resolution",
|
||||
"name": "resolution",
|
||||
"default": "2k"
|
||||
},
|
||||
"duration": {
|
||||
"enum": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
||||
"type": "integer",
|
||||
"title": "Duration",
|
||||
"name": "duration",
|
||||
"default": 5
|
||||
}
|
||||
},
|
||||
"provider": "minimax",
|
||||
"provider_name": "Minimax"
|
||||
},
|
||||
{
|
||||
"id": "minimax-h3-open-text-to-video",
|
||||
"name": "MiniMax H3 Open Text to Video",
|
||||
"endpoint": "minimax-h3-open-text-to-video",
|
||||
"family": "minimax-h3",
|
||||
"inputs": {
|
||||
"prompt": {
|
||||
"type": "string",
|
||||
"title": "Prompt",
|
||||
"name": "prompt",
|
||||
"description": "Text prompt describing the video to generate."
|
||||
},
|
||||
"aspect_ratio": {
|
||||
"enum": ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9", "9:21"],
|
||||
"type": "string",
|
||||
"title": "Aspect Ratio",
|
||||
"name": "aspect_ratio",
|
||||
"default": "16:9"
|
||||
},
|
||||
"resolution": {
|
||||
"enum": ["480p", "768p"],
|
||||
"type": "string",
|
||||
"title": "Resolution",
|
||||
"name": "resolution",
|
||||
"default": "480p"
|
||||
},
|
||||
"duration": {
|
||||
"enum": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
||||
"type": "integer",
|
||||
"title": "Duration",
|
||||
"name": "duration",
|
||||
"default": 5
|
||||
}
|
||||
},
|
||||
"provider": "minimax",
|
||||
"provider_name": "Minimax"
|
||||
}
|
||||
];
|
||||
|
||||
@@ -10826,6 +10999,122 @@ export const i2iModels = [
|
||||
},
|
||||
"provider": "bytedance",
|
||||
"provider_name": "ByteDance"
|
||||
},
|
||||
{
|
||||
"id": "qwen3-image-to-image",
|
||||
"name": "Qwen 3 Image to Image",
|
||||
"endpoint": "qwen3-image-to-image",
|
||||
"family": "qwen3",
|
||||
"imageField": "images_list",
|
||||
"maxImages": 3,
|
||||
"inputs": {
|
||||
"prompt": {
|
||||
"type": "string",
|
||||
"title": "Prompt",
|
||||
"name": "prompt",
|
||||
"description": "Text prompt describing the desired image edit."
|
||||
},
|
||||
"images_list": {
|
||||
"type": "array",
|
||||
"field": "images_list",
|
||||
"title": "Input Images",
|
||||
"name": "images_list",
|
||||
"maxItems": 3,
|
||||
"items": {"type": "string"}
|
||||
},
|
||||
"resolution": {
|
||||
"enum": ["1k", "2k"],
|
||||
"type": "string",
|
||||
"title": "Resolution",
|
||||
"name": "resolution",
|
||||
"default": "1k"
|
||||
},
|
||||
"aspect_ratio": {
|
||||
"enum": ["1:1", "3:2", "2:3", "4:3", "3:4", "16:9", "9:16", "21:9"],
|
||||
"type": "string",
|
||||
"title": "Aspect Ratio",
|
||||
"name": "aspect_ratio",
|
||||
"default": "16:9"
|
||||
},
|
||||
"output_format": {
|
||||
"enum": ["png", "jpeg"],
|
||||
"type": "string",
|
||||
"title": "Output Format",
|
||||
"name": "output_format",
|
||||
"default": "png"
|
||||
},
|
||||
"prompt_extend": {
|
||||
"type": "boolean",
|
||||
"title": "Intelligent Prompt Extend",
|
||||
"name": "prompt_extend",
|
||||
"default": true
|
||||
},
|
||||
"negative_prompt": {
|
||||
"type": "string",
|
||||
"title": "Negative Prompt",
|
||||
"name": "negative_prompt"
|
||||
}
|
||||
},
|
||||
"provider": "alibaba",
|
||||
"provider_name": "Alibaba"
|
||||
},
|
||||
{
|
||||
"id": "qwen3-pro-image-to-image",
|
||||
"name": "Qwen 3 Pro Image to Image",
|
||||
"endpoint": "qwen3-pro-image-to-image",
|
||||
"family": "qwen3",
|
||||
"imageField": "images_list",
|
||||
"maxImages": 3,
|
||||
"inputs": {
|
||||
"prompt": {
|
||||
"type": "string",
|
||||
"title": "Prompt",
|
||||
"name": "prompt",
|
||||
"description": "Text prompt describing the desired image edit."
|
||||
},
|
||||
"images_list": {
|
||||
"type": "array",
|
||||
"field": "images_list",
|
||||
"title": "Input Images",
|
||||
"name": "images_list",
|
||||
"maxItems": 3,
|
||||
"items": {"type": "string"}
|
||||
},
|
||||
"resolution": {
|
||||
"enum": ["1k", "2k"],
|
||||
"type": "string",
|
||||
"title": "Resolution",
|
||||
"name": "resolution",
|
||||
"default": "1k"
|
||||
},
|
||||
"aspect_ratio": {
|
||||
"enum": ["1:1", "3:2", "2:3", "4:3", "3:4", "16:9", "9:16", "21:9"],
|
||||
"type": "string",
|
||||
"title": "Aspect Ratio",
|
||||
"name": "aspect_ratio",
|
||||
"default": "16:9"
|
||||
},
|
||||
"output_format": {
|
||||
"enum": ["png", "jpeg"],
|
||||
"type": "string",
|
||||
"title": "Output Format",
|
||||
"name": "output_format",
|
||||
"default": "png"
|
||||
},
|
||||
"prompt_extend": {
|
||||
"type": "boolean",
|
||||
"title": "Intelligent Prompt Extend",
|
||||
"name": "prompt_extend",
|
||||
"default": true
|
||||
},
|
||||
"negative_prompt": {
|
||||
"type": "string",
|
||||
"title": "Negative Prompt",
|
||||
"name": "negative_prompt"
|
||||
}
|
||||
},
|
||||
"provider": "alibaba",
|
||||
"provider_name": "Alibaba"
|
||||
}
|
||||
];
|
||||
|
||||
@@ -18892,6 +19181,220 @@ export const i2vModels = [
|
||||
},
|
||||
"provider": "bytedance",
|
||||
"provider_name": "ByteDance"
|
||||
},
|
||||
{
|
||||
"id": "minimax-h3-image-to-video",
|
||||
"name": "MiniMax H3 Image to Video",
|
||||
"endpoint": "minimax-h3-image-to-video",
|
||||
"family": "minimax-h3",
|
||||
"imageField": "image_url",
|
||||
"lastImageField": "last_image_url",
|
||||
"hasPrompt": true,
|
||||
"inputs": {
|
||||
"prompt": {
|
||||
"type": "string",
|
||||
"title": "Prompt",
|
||||
"name": "prompt",
|
||||
"description": "Motion prompt describing the desired video."
|
||||
},
|
||||
"image_url": {
|
||||
"type": "string",
|
||||
"field": "image",
|
||||
"title": "Image URL",
|
||||
"name": "image_url"
|
||||
},
|
||||
"last_image_url": {
|
||||
"type": "string",
|
||||
"field": "image",
|
||||
"title": "Last Image URL",
|
||||
"name": "last_image_url"
|
||||
},
|
||||
"resolution": {
|
||||
"enum": ["2k"],
|
||||
"type": "string",
|
||||
"title": "Resolution",
|
||||
"name": "resolution",
|
||||
"default": "2k"
|
||||
},
|
||||
"duration": {
|
||||
"enum": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
||||
"type": "integer",
|
||||
"title": "Duration",
|
||||
"name": "duration",
|
||||
"default": 5
|
||||
}
|
||||
},
|
||||
"provider": "minimax",
|
||||
"provider_name": "Minimax"
|
||||
},
|
||||
{
|
||||
"id": "minimax-h3-reference-to-video",
|
||||
"name": "MiniMax H3 Reference to Video",
|
||||
"endpoint": "minimax-h3-reference-to-video",
|
||||
"family": "minimax-h3",
|
||||
"imageField": "reference_images",
|
||||
"hasPrompt": true,
|
||||
"inputs": {
|
||||
"prompt": {
|
||||
"type": "string",
|
||||
"title": "Prompt",
|
||||
"name": "prompt",
|
||||
"description": "Prompt describing the desired video."
|
||||
},
|
||||
"reference_images": {
|
||||
"type": "array",
|
||||
"field": "image",
|
||||
"title": "Reference Images",
|
||||
"name": "reference_images",
|
||||
"items": {"type": "string"}
|
||||
},
|
||||
"reference_videos": {
|
||||
"type": "array",
|
||||
"field": "video",
|
||||
"title": "Reference Videos",
|
||||
"name": "reference_videos",
|
||||
"items": {"type": "string"}
|
||||
},
|
||||
"reference_audios": {
|
||||
"type": "array",
|
||||
"field": "audio",
|
||||
"title": "Reference Audio",
|
||||
"name": "reference_audios",
|
||||
"items": {"type": "string"}
|
||||
},
|
||||
"aspect_ratio": {
|
||||
"enum": ["21:9", "16:9", "4:3", "1:1", "3:4", "9:16"],
|
||||
"type": "string",
|
||||
"title": "Aspect Ratio",
|
||||
"name": "aspect_ratio",
|
||||
"default": "16:9"
|
||||
},
|
||||
"resolution": {
|
||||
"enum": ["2k"],
|
||||
"type": "string",
|
||||
"title": "Resolution",
|
||||
"name": "resolution",
|
||||
"default": "2k"
|
||||
},
|
||||
"duration": {
|
||||
"enum": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
||||
"type": "integer",
|
||||
"title": "Duration",
|
||||
"name": "duration",
|
||||
"default": 5
|
||||
}
|
||||
},
|
||||
"provider": "minimax",
|
||||
"provider_name": "Minimax"
|
||||
},
|
||||
{
|
||||
"id": "minimax-h3-open-image-to-video",
|
||||
"name": "MiniMax H3 Open Image to Video",
|
||||
"endpoint": "minimax-h3-open-image-to-video",
|
||||
"family": "minimax-h3",
|
||||
"imageField": "image_url",
|
||||
"lastImageField": "last_image",
|
||||
"hasPrompt": true,
|
||||
"inputs": {
|
||||
"prompt": {
|
||||
"type": "string",
|
||||
"title": "Prompt",
|
||||
"name": "prompt",
|
||||
"description": "Motion prompt describing the desired video."
|
||||
},
|
||||
"image_url": {
|
||||
"type": "string",
|
||||
"field": "image",
|
||||
"title": "First Frame Image URL",
|
||||
"name": "image_url"
|
||||
},
|
||||
"last_image": {
|
||||
"type": "string",
|
||||
"field": "image",
|
||||
"title": "Last Frame Image URL",
|
||||
"name": "last_image"
|
||||
},
|
||||
"resolution": {
|
||||
"enum": ["480p", "768p"],
|
||||
"type": "string",
|
||||
"title": "Resolution",
|
||||
"name": "resolution",
|
||||
"default": "480p"
|
||||
},
|
||||
"duration": {
|
||||
"enum": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
||||
"type": "integer",
|
||||
"title": "Duration",
|
||||
"name": "duration",
|
||||
"default": 5
|
||||
}
|
||||
},
|
||||
"provider": "minimax",
|
||||
"provider_name": "Minimax"
|
||||
},
|
||||
{
|
||||
"id": "minimax-h3-open-reference-to-video",
|
||||
"name": "MiniMax H3 Open Reference to Video",
|
||||
"endpoint": "minimax-h3-open-reference-to-video",
|
||||
"family": "minimax-h3",
|
||||
"imageField": "images_list",
|
||||
"maxImages": 9,
|
||||
"hasPrompt": true,
|
||||
"inputs": {
|
||||
"prompt": {
|
||||
"type": "string",
|
||||
"title": "Prompt",
|
||||
"name": "prompt",
|
||||
"description": "Prompt describing the desired video."
|
||||
},
|
||||
"images_list": {
|
||||
"type": "array",
|
||||
"field": "images_list",
|
||||
"title": "Reference Images",
|
||||
"name": "images_list",
|
||||
"maxItems": 9,
|
||||
"items": {"type": "string"}
|
||||
},
|
||||
"videos_list": {
|
||||
"type": "array",
|
||||
"field": "videos_list",
|
||||
"title": "Reference Videos",
|
||||
"name": "videos_list",
|
||||
"maxItems": 3,
|
||||
"items": {"type": "string"}
|
||||
},
|
||||
"audios_list": {
|
||||
"type": "array",
|
||||
"field": "audios_list",
|
||||
"title": "Reference Audio",
|
||||
"name": "audios_list",
|
||||
"maxItems": 3,
|
||||
"items": {"type": "string"}
|
||||
},
|
||||
"aspect_ratio": {
|
||||
"enum": ["16:9", "9:16", "1:1", "4:3", "3:4", "21:9", "9:21"],
|
||||
"type": "string",
|
||||
"title": "Aspect Ratio",
|
||||
"name": "aspect_ratio",
|
||||
"default": "16:9"
|
||||
},
|
||||
"resolution": {
|
||||
"enum": ["480p", "768p"],
|
||||
"type": "string",
|
||||
"title": "Resolution",
|
||||
"name": "resolution",
|
||||
"default": "480p"
|
||||
},
|
||||
"duration": {
|
||||
"enum": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
|
||||
"type": "integer",
|
||||
"title": "Duration",
|
||||
"name": "duration",
|
||||
"default": 5
|
||||
}
|
||||
},
|
||||
"provider": "minimax",
|
||||
"provider_name": "Minimax"
|
||||
}
|
||||
];
|
||||
|
||||
@@ -18902,6 +19405,8 @@ export const getMaxImagesForI2VModel = (modelId) => {
|
||||
const model = getI2VModelById(modelId);
|
||||
if (!model) return 1;
|
||||
if (model.maxImages) return model.maxImages;
|
||||
const imageInput = model.inputs?.[model.imageField];
|
||||
if (imageInput?.type === 'array') return imageInput.maxItems || 1;
|
||||
if (model.lastImageField) return 2;
|
||||
return 1;
|
||||
};
|
||||
@@ -22737,6 +23242,80 @@ export const audioModels = [
|
||||
"maximum": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "elevenlabs-tts-turbo-2-5",
|
||||
"name": "ElevenLabs TTS Turbo 2.5",
|
||||
"endpoint": "elevenlabs-tts-turbo-2-5",
|
||||
"family": "audio-generation",
|
||||
"description": "Convert text to natural-sounding speech with adjustable voice stability, similarity, and speed.",
|
||||
"required": ["prompt"],
|
||||
"inputs": {
|
||||
"prompt": {
|
||||
"type": "string",
|
||||
"title": "Prompt",
|
||||
"name": "prompt",
|
||||
"description": "Text to convert to speech."
|
||||
},
|
||||
"voice_id": {
|
||||
"type": "string",
|
||||
"title": "Voice ID",
|
||||
"name": "voice_id",
|
||||
"default": "21m00Tcm4TlvDq8ikWAM",
|
||||
"enum": [
|
||||
{"label": "James — Husky, Engaging and Bold", "value": "ZQe5CZNOzWyzPSCn5a3c"},
|
||||
{"label": "Arabella — Mysterious and Emotive", "value": "Z3R5wn05IrDiVCyEkUrK"},
|
||||
{"label": "Bradford — Expressive and Articulate", "value": "NNl6r8mD7vthiJatiJt1"},
|
||||
{"label": "Xavier — Dominating, Metallic Announcer", "value": "YOq2y2Up4RgXP2HyXjE5"},
|
||||
{"label": "Taksh — Calm, Serious and Smooth", "value": "qDuRKMlYmrm8trt5QyBn"},
|
||||
{"label": "Monika Sogam — Deep and Natural", "value": "iP95p4xoKVk53GoZ742B"},
|
||||
{"label": "Mark — Casual, Relaxed and Light", "value": "UgBBYS2sOqTuMpoF3BR0"},
|
||||
{"label": "Adeline — Feminine and Conversational", "value": "5l5f8iK3YPeGga21rQIX"},
|
||||
{"label": "Sam — Support Agent", "value": "yoZ06aMxZJJ28mfd3POQ"},
|
||||
{"label": "Spuds Oxley — Wise and Approachable", "value": "NOpBlnGInO9m6vDvFkFC"},
|
||||
{"label": "Eve — Authentic, Energetic and Happy", "value": "scOwDtmlLZohaFMFCHFe"},
|
||||
{"label": "Callum — Husky Trickster", "value": "N2lVS1w4EtoT3dr4eOWO"},
|
||||
{"label": "Laura — Enthusiast, Quirky Attitude", "value": "FGY2WhTYpPnrIDTdsKH5"},
|
||||
{"label": "Brian — Deep, Resonant and Comforting", "value": "zPhCVfO2NBER7bRLIdbq"},
|
||||
{"label": "Nathan — Virtual Radio Host", "value": "nPczCjzI2devNBz1zQrb"},
|
||||
{"label": "Charlie — Natural", "value": "IKne3meq5aSn9XLyUdCD"},
|
||||
{"label": "George — Warm", "value": "JBFqnCBsd6RMkjVDRZzb"},
|
||||
{"label": "Sarah — Soft", "value": "EXAVITQu4vr4xnSDxMaL"},
|
||||
{"label": "Charlotte — Clear", "value": "XB0fDUnXU5powFXDhCwa"},
|
||||
{"label": "Hope — Bubbly, Gossipy and Girly", "value": "tnSpp4vdxKPjI9w0GnoV"},
|
||||
{"label": "Finn — Youthful, Eager and Energetic", "value": "DYkrAHD8iwork3YSUBbs"},
|
||||
{"label": "Tom — Conversations and Books", "value": "56AoDkrOh6qfVPDXZ7Pt"},
|
||||
{"label": "Lucy — Fresh and Casual", "value": "lcMyyd2HUfFzxdCaC4Ta"},
|
||||
{"label": "Tiffany — Natural and Welcoming", "value": "6aDn1KB0hjpdcocrUkmq"},
|
||||
{"label": "Brock — Commanding and Loud Sergeant", "value": "7ftFdxRlmR6Z9V3nTdUh"},
|
||||
{"label": "Viraj — Rich and Soft", "value": "bajNon13EdhNMndG3z05"}
|
||||
]
|
||||
},
|
||||
"stability": {
|
||||
"type": "number",
|
||||
"title": "Stability",
|
||||
"name": "stability",
|
||||
"default": 0.5
|
||||
},
|
||||
"similarity_boost": {
|
||||
"type": "number",
|
||||
"title": "Similarity Boost",
|
||||
"name": "similarity_boost",
|
||||
"default": 0.75
|
||||
},
|
||||
"speed": {
|
||||
"type": "number",
|
||||
"title": "Speed",
|
||||
"name": "speed",
|
||||
"default": 1
|
||||
},
|
||||
"language_code": {
|
||||
"enum": ["en", "fr", "de", "ja", "vi", "hu", "no"],
|
||||
"type": "string",
|
||||
"title": "Language Code",
|
||||
"name": "language_code"
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -125,12 +125,16 @@ export async function generateI2V(apiKey, params) {
|
||||
const payload = {};
|
||||
if (params.prompt) payload.prompt = params.prompt;
|
||||
const imageField = modelInfo?.imageField || 'image_url';
|
||||
if (params.images_list && params.images_list.length > 0) {
|
||||
if (imageField === 'images_list') payload.images_list = params.images_list;
|
||||
else payload[imageField] = params.images_list[0];
|
||||
} else if (params.image_url) {
|
||||
if (imageField === 'images_list') payload.images_list = [params.image_url];
|
||||
else payload[imageField] = params.image_url;
|
||||
const imageInput = modelInfo?.inputs?.[imageField];
|
||||
const imageUrls = params.images_list?.length > 0
|
||||
? params.images_list
|
||||
: (params.image_url ? [params.image_url] : []);
|
||||
if (imageUrls.length > 0) {
|
||||
if (imageInput?.type === 'array' || imageField === 'images_list') {
|
||||
payload[imageField] = imageUrls;
|
||||
} else {
|
||||
payload[imageField] = imageUrls[0];
|
||||
}
|
||||
}
|
||||
const lastImageField = modelInfo?.lastImageField;
|
||||
if (lastImageField && params.last_image) {
|
||||
|
||||
Reference in New Issue
Block a user