feat(settings): 模型设置新增赞助合作伙伴 Infistar 无限星河预设

- 后端 cloud_presets 新增 infistar:预设 https://infistar.cc/v1,独立 infistar_api_key
  (含 INFISTAR_API_KEY 环境变量);CLI / MCP 支持 --provider infistar。
- 多模型网关不内置型号名单、不预设默认模型:填好 Key 后从 /v1/models 拉取,
  选中的 gpt / deepseek / gemini 等型号不会被当成「别家型号」重置。
- 设置页选 Infistar 时显示「注册并领取体验额度」「接入说明」,并注明含推广分成;
  新增 sponsor_link_opened 事件(只记录入口,不含个人信息)。八语文案同步。
- 接入说明补充新版一步选择的流程,保留旧版手动填写方式。

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
周小舟
2026-09-29 17:12:12 +08:00
co-authored by Claude Opus 5.5
parent 3d1985aa33
commit e25b00bc13
23 changed files with 223 additions and 28 deletions
+3
View File
@@ -7,6 +7,9 @@
## [未发布]
### 新增
- 模型设置新增赞助合作伙伴「Infistar 无限星河」:接口地址已预设,填好 Key 后自动列出账号可用的模型;设置页提供专属注册链接(可领 $5 体验额度)和接入说明。CLI / MCP 支持 `--provider infistar` 与 `INFISTAR_API_KEY`。
### 修复
- 时间线重试只使用本次有效结果,避免失败后误用上次候选;原始响应缓存现在会正常解析,无效缓存不会自动触发模型请求。
- 智能导入后台任务提交失败后可明确重试,已有方案、草稿和成片保留;修改方案失败时同步恢复偏好。
+4 -1
View File
@@ -58,6 +58,7 @@ class ApiKeys(BaseModel):
kimi: str = Field(default="", description="Kimi / 月之暗面 API密钥")
glm: str = Field(default="", description="智谱 GLM API密钥")
grok: str = Field(default="", description="xAI Grok API密钥")
infistar: str = Field(default="", description="Infistar 无限星河 API密钥")
seed: str = Field(default="", description="火山方舟 Seed / 豆包 API密钥")
jimeng_access: str = Field(default="", description="即梦AI访问密钥")
jimeng_secret: str = Field(default="", description="即梦AI秘密密钥")
@@ -66,7 +67,7 @@ class ApiKeys(BaseModel):
class ApiSettings(BaseModel):
"""API设置"""
api_keys: ApiKeys = Field(default_factory=ApiKeys, description="API密钥")
api_provider: str = Field(default="dashscope", description="当前 LLM 提供商(dashscope / openai / gemini / deepseek / seed / kimi / glm / grok,或本地预设 ollama / lmstudio)")
api_provider: str = Field(default="dashscope", description="当前 LLM 提供商(dashscope / openai / gemini / deepseek / seed / kimi / glm / grok / infistar,或本地预设 ollama / lmstudio)")
api_base_url: str = Field(default="", description="OpenAI 兼容接口地址;provider=openai 时空为官方地址,本地预设为空时用预设默认地址")
api_model: str = Field(default="qwen-plus", description="默认模型")
api_max_tokens: int = Field(default=4096, description="最大Token数")
@@ -258,6 +259,7 @@ async def get_settings():
kimi="",
glm="",
grok="",
infistar="",
seed="",
jimeng_access="", # 默认值
jimeng_secret="" # 默认值
@@ -692,6 +694,7 @@ def _saved_provider_api_key(settings: DesktopSettings, provider: str) -> str:
"kimi": keys.kimi,
"glm": keys.glm,
"grok": keys.grok,
"infistar": keys.infistar,
"seed": keys.seed,
}.get((provider or "").strip().lower(), "") or ""
+2 -1
View File
@@ -59,7 +59,7 @@ def _err(msg: str) -> None:
def _add_llm_args(p: argparse.ArgumentParser) -> None:
g = p.add_argument_group("模型(不填则用桌面应用设置页里的配置)")
g.add_argument("--provider", choices=PROVIDER_CHOICES, help="dashscope / openai / gemini / deepseek / seed / kimi / glm / grok,或本地预设 ollama / lmstudio")
g.add_argument("--provider", choices=PROVIDER_CHOICES, help="dashscope / openai / gemini / deepseek / seed / kimi / glm / grok / infistar,或本地预设 ollama / lmstudio")
g.add_argument("--model", help="模型名,如 qwen-plus、gpt-4o-mini、qwen2.5:7b")
g.add_argument("--base-url", help="OpenAI 兼容接口地址(provider=openai 时用;ollama/lmstudio 有默认值)")
g.add_argument("--api-key", help="API Key(本地模型可不填)。也可用环境变量 AUTOCLIP_API_KEY")
@@ -206,6 +206,7 @@ def cmd_providers(args: argparse.Namespace) -> int:
("kimi", "Kimi(月之暗面)", "需要 key;国内直连"),
("glm", "智谱 GLM", "需要 key;国内直连"),
("grok", "Grok(xAI)", "需要 key"),
("infistar", "Infistar 无限星河(赞助)", "需要 key,专属链接注册可领体验额度"),
] + [
(p.key, p.display_name, f"无需 key;默认 {p.base_url}" + (f",默认模型 {p.default_model}" if p.default_model else ""))
for p in LOCAL_PRESETS.values()
+15 -2
View File
@@ -1,5 +1,5 @@
"""
云端 OpenAI 兼容预设:DeepSeek / Seed / Kimi / GLM / Grok。
云端 OpenAI 兼容预设:DeepSeek / Seed / Kimi / GLM / Grok / Infistar(赞助)。
底层仍是 openai + 官方 base_url,和 Ollama 预设同一套路,但必须带各家自己的 key,
不能复用用户的 OpenAI key。设置页、CLI、MCP 都用 `--provider deepseek` 这种名字。
@@ -67,6 +67,17 @@ CLOUD_PRESETS: Dict[str, CloudPreset] = {
docs_url="https://console.x.ai",
hint="xAI Grok。需要 xAI 账号。",
),
# 赞助合作伙伴。多模型网关,可用型号随账号而定,所以不预设默认模型,填好 key 后从 /v1/models 拉取。
# docs_url 是 AutoClip 专属注册链接(新用户可领体验额度),说明见 docs/INFISTAR_SETUP.md。
"infistar": CloudPreset(
key="infistar",
display_name="Infistar 无限星河",
base_url="https://infistar.cc/v1",
default_model="",
api_key_setting="infistar_api_key",
docs_url="https://www.infistar.cc/register?aff=XLK3BCM6&ref_source=link",
hint="赞助合作伙伴。一个 Key 调 Claude / GPT / Gemini / DeepSeek 等模型,专属链接注册可领体验额度。",
),
}
_ALIASES = {
@@ -84,6 +95,8 @@ _ALIASES = {
"ark": "seed",
"bytedance": "seed",
"volces": "seed",
"infistar.cc": "infistar",
"wuxianxinghe": "infistar",
}
@@ -97,7 +110,7 @@ def normalize_cloud_preset_key(name: Optional[str]) -> Optional[str]:
def resolve_cloud_preset(provider: Optional[str], base_url: Optional[str] = None) -> Optional[Tuple[str, str, CloudPreset]]:
"""
若 provider 是 deepseek / seed / kimi / glm / grok(或别名),返回 (openai, base_url, preset)。
若 provider 是 deepseek / seed / kimi / glm / grok / infistar(或别名),返回 (openai, base_url, preset)。
不是云端预设则返回 None。
"""
key = normalize_cloud_preset_key(provider)
+11 -2
View File
@@ -101,6 +101,7 @@ class LLMManager:
"kimi_api_key": "",
"glm_api_key": "",
"grok_api_key": "",
"infistar_api_key": "",
"seed_api_key": "",
"model_name": "qwen-plus",
"chunk_size": 5000,
@@ -127,6 +128,7 @@ class LLMManager:
"kimi_api_key": api_keys.get("kimi", ""),
"glm_api_key": api_keys.get("glm", ""),
"grok_api_key": api_keys.get("grok", ""),
"infistar_api_key": api_keys.get("infistar", ""),
"seed_api_key": api_keys.get("seed", ""),
"model_name": api.get("api_model", "qwen-plus")
})
@@ -173,7 +175,7 @@ class LLMManager:
settings["model_name"] = default_model
def _apply_cloud_preset(self, settings: Dict[str, Any]) -> None:
"""deepseek / seed / kimi / glm / grok → openai + 官方地址,用各家自己的 key。"""
"""deepseek / seed / kimi / glm / grok / infistar → openai + 官方地址,用各家自己的 key。"""
from backend.core.cloud_presets import resolve_cloud_preset
from backend.core.model_catalog import curated_models, default_model_for
@@ -186,8 +188,14 @@ class LLMManager:
settings["cloud_preset"] = preset.key
settings["openai_base_url"] = base_url
current = (settings.get("model_name") or "").strip()
own = curated_models(preset.key)
if not own:
# 多模型网关(infistar):gpt / deepseek / gemini 都是合法型号,用户选什么就用什么
if not current and preset.default_model:
settings["model_name"] = preset.default_model
return
known = set(curated_models())
if not current or current == "qwen-plus" or (current in known and current not in curated_models(preset.key)):
if not current or current == "qwen-plus" or (current in known and current not in own):
settings["model_name"] = preset.default_model or default_model_for(preset.key)
# Docker / 本地脚本模式没有设置页可用,只能靠环境变量(env.example 里也是这么写的),
@@ -201,6 +209,7 @@ class LLMManager:
"kimi_api_key": ("API_KIMI_API_KEY", "MOONSHOT_API_KEY", "KIMI_API_KEY"),
"glm_api_key": ("API_GLM_API_KEY", "ZHIPU_API_KEY", "GLM_API_KEY"),
"grok_api_key": ("API_GROK_API_KEY", "XAI_API_KEY", "GROK_API_KEY"),
"infistar_api_key": ("API_INFISTAR_API_KEY", "INFISTAR_API_KEY"),
"seed_api_key": ("API_SEED_API_KEY", "ARK_API_KEY", "VOLCENGINE_API_KEY", "DOUBAO_API_KEY"),
}
+6 -1
View File
@@ -74,6 +74,8 @@ CURATED_MODELS: Dict[str, List[str]] = {
"grok-4.5",
"grok-4.3",
],
# 多模型网关,型号随账号而定:不内置名单,填好 key 后实时拉取
"infistar": [],
}
DEFAULT_MODELS: Dict[str, str] = {
@@ -85,6 +87,7 @@ DEFAULT_MODELS: Dict[str, str] = {
"kimi": "kimi-k2.6",
"glm": "glm-5.3",
"grok": "grok-4.6",
"infistar": "",
}
PROVIDER_LABELS: Dict[str, str] = {
@@ -96,6 +99,7 @@ PROVIDER_LABELS: Dict[str, str] = {
"kimi": "Kimi",
"glm": "GLM",
"grok": "Grok",
"infistar": "Infistar",
}
CLOUD_PROVIDERS = frozenset(CURATED_MODELS)
@@ -386,7 +390,8 @@ async def list_available_models(
source="catalog",
reachable=False,
default_model=default_model_for(key),
models=curated or curated_models("dashscope"),
# 已知提供商内置名单为空(如 infistar)时保持为空,别拿通义的型号冒充
models=curated if key in CURATED_MODELS else curated_models("dashscope"),
catalog=catalog,
)
+2 -2
View File
@@ -121,7 +121,7 @@ def _make_override(provider: Optional[str], model: Optional[str], base_url: Opti
description=(
"把一条本地视频切成高光片段(同步,耗时数分钟到数十分钟,期间会发进度)。"
"返回切片列表(标题 / 起止时间 / 评分 / mp4 路径)与合集。"
"provider 可选 dashscope / openai / gemini / deepseek / seed / kimi / glm / grok / ollama / lmstudio;不填用桌面应用里已配置的模型。"
"provider 可选 dashscope / openai / gemini / deepseek / seed / kimi / glm / grok / infistar / ollama / lmstudio;不填用桌面应用里已配置的模型。"
),
)
async def clip_video(
@@ -220,7 +220,7 @@ def list_providers() -> Dict[str, Any]:
return {
"current": get_llm_manager().get_current_provider_info(),
"cloud": ["dashscope", "openai", "gemini", "deepseek", "seed", "kimi", "glm", "grok"],
"cloud": ["dashscope", "openai", "gemini", "deepseek", "seed", "kimi", "glm", "grok", "infistar"],
"local_presets": presets_as_dicts(),
}
+2 -2
View File
@@ -25,7 +25,7 @@ from typing import Any, Callable, Dict, List, Optional
logger = logging.getLogger(__name__)
PROVIDER_CHOICES = ("dashscope", "openai", "gemini", "deepseek", "seed", "kimi", "glm", "grok", "ollama", "lmstudio")
PROVIDER_CHOICES = ("dashscope", "openai", "gemini", "deepseek", "seed", "kimi", "glm", "grok", "infistar", "ollama", "lmstudio")
# ---------------------------------------------------------------- environment ---
@@ -145,7 +145,7 @@ def configure_llm(override: LLMOverride) -> Dict[str, Any]:
"dashscope": "dashscope_api_key", "openai": "openai_api_key",
"gemini": "gemini_api_key", "siliconflow": "siliconflow_api_key",
"deepseek": "deepseek_api_key",
"kimi": "kimi_api_key", "glm": "glm_api_key", "grok": "grok_api_key",
"kimi": "kimi_api_key", "glm": "glm_api_key", "grok": "grok_api_key", "infistar": "infistar_api_key",
"seed": "seed_api_key",
}.get(provider)
if key_field:
+32 -2
View File
@@ -31,7 +31,7 @@ def fake_openai(monkeypatch):
monkeypatch.setitem(sys.modules, "openai", module)
_FakeOpenAIClient.created.clear()
monkeypatch.delenv("OPENAI_BASE_URL", raising=False)
for name in ("LLM_PROVIDER", "API_MODEL_NAME", "LLM_MODEL", "API_OPENAI_API_KEY", "OPENAI_API_KEY", "API_DEEPSEEK_API_KEY", "DEEPSEEK_API_KEY"):
for name in ("LLM_PROVIDER", "API_MODEL_NAME", "LLM_MODEL", "API_OPENAI_API_KEY", "OPENAI_API_KEY", "API_DEEPSEEK_API_KEY", "DEEPSEEK_API_KEY", "API_INFISTAR_API_KEY", "INFISTAR_API_KEY"):
monkeypatch.delenv(name, raising=False)
from backend.core import llm_manager as manager_module
monkeypatch.setattr(manager_module.config_sync_service, "is_sync_needed", lambda: False)
@@ -89,4 +89,34 @@ def test_manager_uses_seed_ark_key_not_openai(fake_openai, tmp_path):
def test_curated_lists_drop_retired_aliases():
assert "gpt-4o" not in CLOUD_PRESETS
assert set(CLOUD_PRESETS) == {"deepseek", "seed", "kimi", "glm", "grok"}
assert set(CLOUD_PRESETS) == {"deepseek", "seed", "kimi", "glm", "grok", "infistar"}
def test_infistar_sponsor_preset_uses_gateway_and_own_key(fake_openai, tmp_path):
provider, url, preset = resolve_cloud_preset("infistar")
assert provider == "openai"
assert url == "https://infistar.cc/v1"
# 多模型网关不预设型号;专属注册链接带推广参数
assert preset.default_model == ""
assert "aff=" in preset.docs_url
settings = tmp_path / "settings.json"
settings.write_text(
'{"api": {"api_keys": {"openai": "sk-openai-should-not-be-used", "infistar": "sk-infistar-key-123"}, '
'"api_provider": "infistar", "api_model": "deepseek-v4-pro"}}',
encoding="utf-8",
)
info = LLMManager(settings_file=settings).get_current_provider_info()
assert info["provider"] == "infistar"
assert info["base_url"] == "https://infistar.cc/v1"
assert info["model"] == "deepseek-v4-pro"
assert fake_openai.created[-1]["api_key"] == "sk-infistar-key-123"
assert fake_openai.created[-1]["base_url"] == "https://infistar.cc/v1"
def test_infistar_key_from_env(fake_openai, tmp_path, monkeypatch):
monkeypatch.setenv("INFISTAR_API_KEY", "sk-infistar-from-env")
settings = tmp_path / "settings.json"
settings.write_text('{"api": {"api_keys": {}, "api_provider": "infistar", "api_model": "gpt-5-mini"}}', encoding="utf-8")
LLMManager(settings_file=settings).get_current_provider_info()
assert fake_openai.created[-1]["api_key"] == "sk-infistar-from-env"
+21
View File
@@ -225,3 +225,24 @@ def test_provider_catalog_infos_follow_curated_list():
assert names == model_catalog.curated_models("dashscope")
openai_names = [m.name for m in _catalog_model_infos(ProviderType.OPENAI)]
assert "gpt-5" in openai_names
def test_infistar_has_no_builtin_list_and_fetches_gateway_models(monkeypatch):
# 没 key:不拿通义的型号冒充
empty = asyncio.run(model_catalog.list_available_models("infistar"))
assert empty.models == [] and empty.default_model == "" and empty.source == "catalog"
_FakeAsyncClient.calls = []
_FakeAsyncClient.routes = {
"https://infistar.cc/v1/models": (
{"data": [{"id": "claude-sonnet-5-5"}, {"id": "deepseek-v4-pro"}, {"id": "gemini-3.8-flash"},
{"id": "text-embedding-3-large"}, {"id": "sora-2"}]},
200,
)
}
import httpx
monkeypatch.setattr(httpx, "AsyncClient", _FakeAsyncClient)
live = asyncio.run(model_catalog.list_available_models("infistar", api_key="sk-infistar-key-123", refresh=True))
assert live.source == "live"
# 网关里各家型号都保留,只去掉嵌入 / 视频
assert live.models == ["claude-sonnet-5-5", "deepseek-v4-pro", "gemini-3.8-flash"]
+11
View File
@@ -10,6 +10,17 @@ Register through the [AutoClip referral link](https://www.infistar.cc/register?a
## Configure AutoClip
### Version 1.4.1 and later: pick Infistar directly
1. Open Settings → Model and choose **Infistar**. The base URL `https://infistar.cc/v1` is preset.
2. No account yet? Click "Sign up & claim credit" to register through the referral link, then create an API key in the console.
3. Paste the key. The model list fills in with the models available to your account; pick one.
4. Test the connection and save.
CLI / MCP: `autoclip run video.mp4 --provider infistar --api-key sk-… --model <model id>`, or set `INFISTAR_API_KEY`.
### Older versions: configure as an OpenAI-compatible API
Open Settings → Model and enter:
| Field | Value |
+12 -1
View File
@@ -10,6 +10,17 @@ Infistar 是 AutoClip 的赞助合作伙伴,可通过现有 OpenAI 兼容接
## 配置 AutoClip
### 新版本(1.4.1 起):直接选择 Infistar
1. 打开「设置 → 模型」,提供商选 **Infistar**。接口地址已预设为 `https://infistar.cc/v1`,不用填。
2. 还没有账号时,点「注册并领取体验额度」,用专属链接注册并在控制台创建 API Key。
3. 把 API Key 粘贴进来。模型下拉会自动列出这个账号可用的型号,选一个。
4. 点「测试连接」,再保存。
命令行 / MCP:`autoclip run video.mp4 --provider infistar --api-key sk-… --model <模型 ID>`,也可以设置环境变量 `INFISTAR_API_KEY`。
### 旧版本:用 OpenAI 兼容接口手动填写
打开「设置 → 模型」,填写以下内容:
| 配置项 | 内容 |
@@ -19,7 +30,7 @@ Infistar 是 AutoClip 的赞助合作伙伴,可通过现有 OpenAI 兼容接
| API Key | 你在 Infistar 创建的 API Key |
| 模型 | 当前账号可用、支持 Chat Completions 的真实模型 ID |
接口地址中的 `/v1` 只填写一次,不要追加 `/chat/completions`。国际网络也可使用 `https://infistar.ai/v1`,参见 [Infistar 网关配置文档](https://doc.infistar.cc/integration-guides/gateway-config)。
接口地址中的 `/v1` 只填写一次,不要追加 `/chat/completions`。国际网络也可使用 `https://infistar.ai/v1`(新版本选 OpenAI 兼容接口手动填写即可),参见 [Infistar 网关配置文档](https://doc.infistar.cc/integration-guides/gateway-config)。
从模型列表选择或手动输入真实模型 ID,执行「测试连接」并保存。不要直接沿用 OpenAI 官方默认模型名,具体可用型号由 Infistar 账号权限和模型目录决定。
+1
View File
@@ -23,6 +23,7 @@ API_DASHSCOPE_API_KEY=your_dashscope_api_key_here
# API_KIMI_API_KEY=
# API_GLM_API_KEY=
# API_GROK_API_KEY=
# API_INFISTAR_API_KEY=
# OpenAI 兼容接口地址(LLM_PROVIDER=openai 时生效,留空走 OpenAI 官方)。
# 智谱: https://open.bigmodel.cn/api/paas/v4 DeepSeek: https://api.deepseek.com/v1
# Seed / 火山方舟: https://ark.cn-beijing.volces.com/api/v3
+10
View File
@@ -15,6 +15,8 @@ export const AnalyticsEvent = {
ProcessingFailed: 'processing_failed',
/** 设置/更新 LLM API key */
ApiKeyConfigured: 'api_key_configured',
/** 打开赞助商的注册 / 接入说明链接(只记录是哪家、哪个入口) */
SponsorLinkOpened: 'sponsor_link_opened',
} as const
export type AnalyticsEventName =
@@ -55,6 +57,14 @@ export function trackProcessingFailed(props: {
trackEvent(AnalyticsEvent.ProcessingFailed, { stage: props.stage, code: props.code })
}
export function trackSponsorLinkOpened(props: {
sponsor: 'infistar'
target: 'register' | 'guide'
placement: 'settings_model'
}): void {
trackEvent(AnalyticsEvent.SponsorLinkOpened, props)
}
export function trackApiKeyConfigured(props: {
provider: string
/** 不要传 key 明文,仅标记是否填写 */
+8 -1
View File
@@ -1122,5 +1122,12 @@
"导入任务未能启动,请重试;原素材与已有成片已保留": "Could not start the import. Please retry; your source and existing exports are preserved.",
"原片无法播放时,可生成兼容预览;原片不变,不调用模型。": "If the source cannot play, create a compatible preview. The original stays unchanged; no AI is used.",
"正在生成兼容预览,长视频可能需要几分钟…": "Preparing preview; long videos may take a few minutes…",
"生成兼容预览": "Create compatible preview"
"生成兼容预览": "Create compatible preview",
"Infistar 无限星河": "Infistar",
"赞助合作伙伴。一个 Key 调用 Claude、GPT、Gemini、DeepSeek 等模型,接口地址已预设。": "Sponsor. One key for Claude, GPT, Gemini, DeepSeek and more. The endpoint is preset.",
"开始使用": "Get started",
"通过 AutoClip 专属推广链接注册可领取 $5 体验额度,领取条件以活动页面为准。注册后在控制台创建 API Key,粘贴到下方。该链接含推广分成,用于支持项目维护。": "Sign up through AutoClip's referral link to claim $5 in trial credit (terms on the promotion page). Then create an API key in the console and paste it below. This is a referral link; commissions support AutoClip's maintenance.",
"注册并领取体验额度": "Sign up & claim credit",
"接入说明": "Setup guide",
"填写 API Key 后会自动列出该账号可用的模型,选一个即可。": "Once you enter the API key, the models available to your account are listed here. Pick one."
}
+8 -1
View File
@@ -1122,5 +1122,12 @@
"导入任务未能启动,请重试;原素材与已有成片已保留": "No se pudo iniciar la importación. Inténtalo de nuevo; el original y las exportaciones existentes se conservan.",
"原片无法播放时,可生成兼容预览;原片不变,不调用模型。": "Si el original no se reproduce, crea una vista previa compatible. No se modifica el original ni se usa IA.",
"正在生成兼容预览,长视频可能需要几分钟…": "Preparando vista previa; puede tardar unos minutos…",
"生成兼容预览": "Crear vista previa compatible"
"生成兼容预览": "Crear vista previa compatible",
"Infistar 无限星河": "Infistar",
"赞助合作伙伴。一个 Key 调用 Claude、GPT、Gemini、DeepSeek 等模型,接口地址已预设。": "Patrocinador. Una clave para Claude, GPT, Gemini, DeepSeek y más. El endpoint ya está configurado.",
"开始使用": "Empezar",
"通过 AutoClip 专属推广链接注册可领取 $5 体验额度,领取条件以活动页面为准。注册后在控制台创建 API Key,粘贴到下方。该链接含推广分成,用于支持项目维护。": "Regístrate con el enlace de referido de AutoClip para obtener $5 de crédito de prueba (condiciones en la página de la promoción). Después crea una clave API en la consola y pégala abajo. Es un enlace de referido; las comisiones ayudan a mantener AutoClip.",
"注册并领取体验额度": "Registrarse y obtener crédito",
"接入说明": "Guía de configuración",
"填写 API Key 后会自动列出该账号可用的模型,选一个即可。": "Al introducir la clave API se listan los modelos disponibles para tu cuenta. Elige uno."
}
+8 -1
View File
@@ -1122,5 +1122,12 @@
"导入任务未能启动,请重试;原素材与已有成片已保留": "Impossible de démarrer l’importation. Réessayez ; la source et les exports existants sont conservés.",
"原片无法播放时,可生成兼容预览;原片不变,不调用模型。": "Si la source ne se lit pas, créez un aperçu compatible. Original inchangé, sans IA.",
"正在生成兼容预览,长视频可能需要几分钟…": "Préparation de l’aperçu ; cela peut prendre quelques minutes…",
"生成兼容预览": "Créer un aperçu compatible"
"生成兼容预览": "Créer un aperçu compatible",
"Infistar 无限星河": "Infistar",
"赞助合作伙伴。一个 Key 调用 Claude、GPT、Gemini、DeepSeek 等模型,接口地址已预设。": "Sponsor. Une seule clé pour Claude, GPT, Gemini, DeepSeek et d’autres. L’endpoint est déjà configuré.",
"开始使用": "Commencer",
"通过 AutoClip 专属推广链接注册可领取 $5 体验额度,领取条件以活动页面为准。注册后在控制台创建 API Key,粘贴到下方。该链接含推广分成,用于支持项目维护。": "Inscrivez-vous via le lien de parrainage d’AutoClip pour obtenir 5 $ de crédit d’essai (conditions sur la page de l’offre). Créez ensuite une clé API dans la console et collez-la ci-dessous. Lien de parrainage : les commissions financent la maintenance d’AutoClip.",
"注册并领取体验额度": "S’inscrire et obtenir le crédit",
"接入说明": "Guide de configuration",
"填写 API Key 后会自动列出该账号可用的模型,选一个即可。": "Une fois la clé API saisie, les modèles disponibles pour votre compte s’affichent ici. Choisissez-en un."
}
+8 -1
View File
@@ -1122,5 +1122,12 @@
"导入任务未能启动,请重试;原素材与已有成片已保留": "インポートを開始できませんでした。再試行してください。元の素材と既存の書き出しは保持されています。",
"原片无法播放时,可生成兼容预览;原片不变,不调用模型。": "原動画を再生できない場合は互換プレビューを作成できます。原本は変更せず、AIは使用しません。",
"正在生成兼容预览,长视频可能需要几分钟…": "互換プレビューを生成中。長い動画は数分かかる場合があります…",
"生成兼容预览": "互換プレビューを作成"
"生成兼容预览": "互換プレビューを作成",
"Infistar 无限星河": "Infistar(無限星河)",
"赞助合作伙伴。一个 Key 调用 Claude、GPT、Gemini、DeepSeek 等模型,接口地址已预设。": "スポンサー。1 つのキーで Claude、GPT、Gemini、DeepSeek などを利用できます。接続先は設定済みです。",
"开始使用": "はじめる",
"通过 AutoClip 专属推广链接注册可领取 $5 体验额度,领取条件以活动页面为准。注册后在控制台创建 API Key,粘贴到下方。该链接含推广分成,用于支持项目维护。": "AutoClip 専用の紹介リンクから登録すると $5 分の体験クレジットを受け取れます(条件はキャンペーンページを参照)。登録後、コンソールで API キーを作成して下に貼り付けてください。紹介報酬はプロジェクトの維持に使われます。",
"注册并领取体验额度": "登録してクレジットを受け取る",
"接入说明": "設定ガイド",
"填写 API Key 后会自动列出该账号可用的模型,选一个即可。": "API キーを入力すると、このアカウントで使えるモデルが一覧表示されます。1 つ選んでください。"
}
+8 -1
View File
@@ -1122,5 +1122,12 @@
"导入任务未能启动,请重试;原素材与已有成片已保留": "가져오기를 시작하지 못했습니다. 다시 시도해 주세요. 원본과 기존 내보내기는 보존됩니다.",
"原片无法播放时,可生成兼容预览;原片不变,不调用模型。": "원본을 재생할 수 없다면 호환 미리보기를 만드세요. 원본은 변경되지 않으며 AI를 사용하지 않습니다.",
"正在生成兼容预览,长视频可能需要几分钟…": "미리보기 생성 중. 긴 동영상은 몇 분 걸릴 수 있습니다…",
"生成兼容预览": "호환 미리보기 생성"
"生成兼容预览": "호환 미리보기 생성",
"Infistar 无限星河": "Infistar(무한성하)",
"赞助合作伙伴。一个 Key 调用 Claude、GPT、Gemini、DeepSeek 等模型,接口地址已预设。": "후원 파트너. 키 하나로 Claude, GPT, Gemini, DeepSeek 등을 사용할 수 있습니다. 엔드포인트는 미리 설정되어 있습니다.",
"开始使用": "시작하기",
"通过 AutoClip 专属推广链接注册可领取 $5 体验额度,领取条件以活动页面为准。注册后在控制台创建 API Key,粘贴到下方。该链接含推广分成,用于支持项目维护。": "AutoClip 전용 추천 링크로 가입하면 $5 체험 크레딧을 받을 수 있습니다(조건은 이벤트 페이지 기준). 가입 후 콘솔에서 API 키를 만들어 아래에 붙여 넣으세요. 추천 수수료는 프로젝트 유지에 쓰입니다.",
"注册并领取体验额度": "가입하고 크레딧 받기",
"接入说明": "설정 안내",
"填写 API Key 后会自动列出该账号可用的模型,选一个即可。": "API 키를 입력하면 이 계정에서 쓸 수 있는 모델이 표시됩니다. 하나를 고르세요."
}
+8 -1
View File
@@ -1122,5 +1122,12 @@
"导入任务未能启动,请重试;原素材与已有成片已保留": "Não foi possível iniciar a importação. Tente novamente; o original e as exportações existentes foram preservados.",
"原片无法播放时,可生成兼容预览;原片不变,不调用模型。": "Se o original não reproduzir, crie uma prévia compatível. O original não muda e nenhuma IA é usada.",
"正在生成兼容预览,长视频可能需要几分钟…": "Preparando prévia; vídeos longos podem levar alguns minutos…",
"生成兼容预览": "Criar prévia compatível"
"生成兼容预览": "Criar prévia compatível",
"Infistar 无限星河": "Infistar",
"赞助合作伙伴。一个 Key 调用 Claude、GPT、Gemini、DeepSeek 等模型,接口地址已预设。": "Patrocinador. Uma chave para Claude, GPT, Gemini, DeepSeek e outros. O endpoint já está configurado.",
"开始使用": "Começar",
"通过 AutoClip 专属推广链接注册可领取 $5 体验额度,领取条件以活动页面为准。注册后在控制台创建 API Key,粘贴到下方。该链接含推广分成,用于支持项目维护。": "Cadastre-se pelo link de indicação do AutoClip para receber US$ 5 de crédito de teste (condições na página da promoção). Depois crie uma chave de API no console e cole abaixo. É um link de indicação; as comissões ajudam a manter o AutoClip.",
"注册并领取体验额度": "Cadastrar e receber crédito",
"接入说明": "Guia de configuração",
"填写 API Key 后会自动列出该账号可用的模型,选一个即可。": "Ao inserir a chave de API, os modelos disponíveis para sua conta aparecem aqui. Escolha um."
}
+8 -1
View File
@@ -1122,5 +1122,12 @@
"导入任务未能启动,请重试;原素材与已有成片已保留": "Не удалось запустить импорт. Повторите попытку; исходный материал и готовые файлы сохранены.",
"原片无法播放时,可生成兼容预览;原片不变,不调用模型。": "Если исходное видео не воспроизводится, создайте совместимый предпросмотр. Оригинал не меняется, ИИ не используется.",
"正在生成兼容预览,长视频可能需要几分钟…": "Подготовка предпросмотра может занять несколько минут…",
"生成兼容预览": "Создать совместимый предпросмотр"
"生成兼容预览": "Создать совместимый предпросмотр",
"Infistar 无限星河": "Infistar",
"赞助合作伙伴。一个 Key 调用 Claude、GPT、Gemini、DeepSeek 等模型,接口地址已预设。": "Спонсор. Один ключ для Claude, GPT, Gemini, DeepSeek и других моделей. Адрес API уже указан.",
"开始使用": "Начало работы",
"通过 AutoClip 专属推广链接注册可领取 $5 体验额度,领取条件以活动页面为准。注册后在控制台创建 API Key,粘贴到下方。该链接含推广分成,用于支持项目维护。": "Зарегистрируйтесь по реферальной ссылке AutoClip и получите $5 пробного баланса (условия — на странице акции). Затем создайте API-ключ в консоли и вставьте его ниже. Это реферальная ссылка; комиссия идёт на поддержку AutoClip.",
"注册并领取体验额度": "Зарегистрироваться и получить баланс",
"接入说明": "Инструкция",
"填写 API Key 后会自动列出该账号可用的模型,选一个即可。": "После ввода API-ключа здесь появятся модели, доступные вашему аккаунту. Выберите одну."
}
+8 -1
View File
@@ -1122,5 +1122,12 @@
"导入任务未能启动,请重试;原素材与已有成片已保留": "导入任务未能启动,请重试;原素材与已有成片已保留",
"原片无法播放时,可生成兼容预览;原片不变,不调用模型。": "原片无法播放时,可生成兼容预览;原片不变,不调用模型。",
"正在生成兼容预览,长视频可能需要几分钟…": "正在生成兼容预览,长视频可能需要几分钟…",
"生成兼容预览": "生成兼容预览"
"生成兼容预览": "生成兼容预览",
"Infistar 无限星河": "Infistar 无限星河",
"赞助合作伙伴。一个 Key 调用 Claude、GPT、Gemini、DeepSeek 等模型,接口地址已预设。": "赞助合作伙伴。一个 Key 调用 Claude、GPT、Gemini、DeepSeek 等模型,接口地址已预设。",
"开始使用": "开始使用",
"通过 AutoClip 专属推广链接注册可领取 $5 体验额度,领取条件以活动页面为准。注册后在控制台创建 API Key,粘贴到下方。该链接含推广分成,用于支持项目维护。": "通过 AutoClip 专属推广链接注册可领取 $5 体验额度,领取条件以活动页面为准。注册后在控制台创建 API Key,粘贴到下方。该链接含推广分成,用于支持项目维护。",
"注册并领取体验额度": "注册并领取体验额度",
"接入说明": "接入说明",
"填写 API Key 后会自动列出该账号可用的模型,选一个即可。": "填写 API Key 后会自动列出该账号可用的模型,选一个即可。"
}
+27 -6
View File
@@ -12,7 +12,7 @@ import PublishSettings from '../components/PublishSettings'
import CoverSettings from '../components/CoverSettings'
import { isDesktopMode } from '../utils/desktopMode'
import { openExternalLink } from '../utils/externalLinks'
import { trackApiKeyConfigured } from '../analytics/events'
import { trackApiKeyConfigured, trackSponsorLinkOpened } from '../analytics/events'
import { isAnalyticsEnabled, setAnalyticsEnabled } from '../analytics/posthog'
import { getRuntimeInfo } from '../analytics/lifecycle'
import { isCrashReportsEnabled, setCrashReportsEnabled } from '../desktop/sentry'
@@ -35,12 +35,15 @@ const toNumber = (v: unknown, fallback: number): number => {
return Number.isFinite(n) ? n : fallback
}
type ProviderKey = 'dashscope' | 'openai' | 'gemini' | 'deepseek' | 'seed' | 'kimi' | 'glm' | 'grok' | 'ollama' | 'lmstudio'
type ProviderKey = 'dashscope' | 'openai' | 'infistar' | 'gemini' | 'deepseek' | 'seed' | 'kimi' | 'glm' | 'grok' | 'ollama' | 'lmstudio'
type LocalPreset = { baseUrl: string; defaultModel: string; docsUrl: string; app: string }
type CloudPreset = { baseUrl: string; defaultModel: string }
const PROVIDERS: Record<ProviderKey, { name: string; short: string; hint: string; apiKeyField: string; placeholder: string; keyUrl: string; local?: LocalPreset; cloud?: CloudPreset }> = {
type Sponsor = { registerUrl: string; guideUrl: string }
const PROVIDERS: Record<ProviderKey, { name: string; short: string; hint: string; apiKeyField: string; placeholder: string; keyUrl: string; local?: LocalPreset; cloud?: CloudPreset; sponsor?: Sponsor }> = {
dashscope: { get name() { return t("阿里通义千问") }, get short() { return t("通义千问") }, get hint() { return t("阿里云 DashScope。国内直连,qwen-plus 性价比高。") }, apiKeyField: 'dashscope_api_key', placeholder: 'sk-…', keyUrl: 'https://dashscope.console.aliyun.com/apiKey' },
openai: { get name() { return t("OpenAI / 兼容接口") }, get short() { return t("OpenAI 兼容") }, get hint() { return t("OpenAI,或任何兼容接口:OpenRouter、vLLM。") }, apiKeyField: 'openai_api_key', get placeholder() { return t("sk-…(自建服务可留空)") }, keyUrl: 'https://platform.openai.com/api-keys' },
// 赞助合作伙伴(docs/INFISTAR_SETUP.md)。多模型网关,型号随账号而定:不预设默认模型,填好 key 后实时拉取
infistar: { get name() { return t("Infistar 无限星河") }, short: 'Infistar', get hint() { return t("赞助合作伙伴。一个 Key 调用 Claude、GPT、Gemini、DeepSeek 等模型,接口地址已预设。") }, apiKeyField: 'infistar_api_key', placeholder: 'sk-…', keyUrl: 'https://www.infistar.cc/register?aff=XLK3BCM6&ref_source=link', cloud: { baseUrl: 'https://infistar.cc/v1', defaultModel: '' }, sponsor: { registerUrl: 'https://www.infistar.cc/register?aff=XLK3BCM6&ref_source=link', guideUrl: 'https://github.com/zhouxiaoka/autoclip/blob/main/docs/INFISTAR_SETUP.md' } },
gemini: { name: 'Google Gemini', short: 'Gemini', get hint() { return t("Google AI Studio 的 Gemini 系列。") }, apiKeyField: 'gemini_api_key', placeholder: 'AIza…', keyUrl: 'https://aistudio.google.com/apikey' },
deepseek: { name: 'DeepSeek', short: 'DeepSeek', get hint() { return t("DeepSeek 官方。国内直连,deepseek-flash 是当前 V4.1。") }, apiKeyField: 'deepseek_api_key', placeholder: 'sk-…', keyUrl: 'https://platform.deepseek.com/api_keys', cloud: { baseUrl: 'https://api.deepseek.com', defaultModel: 'deepseek-flash' } },
seed: { name: 'Seed', short: 'Seed', get hint() { return t("火山方舟 Seed。国内直连,豆包 Seed 2.1 系列。") }, apiKeyField: 'seed_api_key', placeholder: '…', keyUrl: 'https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey', cloud: { baseUrl: 'https://ark.cn-beijing.volces.com/api/v3', defaultModel: 'doubao-seed-2-1-lite-260915' } },
@@ -68,11 +71,12 @@ const FALLBACK_CATALOG: Record<string, string[]> = {
kimi: ['kimi-k3', 'kimi-k2.6', 'kimi-k2.5', 'kimi-k2.7-code'],
glm: ['glm-5.3', 'glm-5.2', 'glm-4.7'],
grok: ['grok-4.6', 'grok-4.5', 'grok-4.3'],
infistar: [],
}
const PROVIDER_GROUP_ORDER: ProviderKey[] = ['dashscope', 'openai', 'gemini', 'deepseek', 'seed', 'kimi', 'glm', 'grok']
const PROVIDER_GROUP_ORDER: ProviderKey[] = ['dashscope', 'openai', 'infistar', 'gemini', 'deepseek', 'seed', 'kimi', 'glm', 'grok']
const providerGroupLabel = (key: string) => ({
dashscope: t("通义千问"), openai: 'OpenAI', gemini: 'Gemini', deepseek: 'DeepSeek',
seed: 'Seed', kimi: 'Kimi', glm: 'GLM', grok: 'Grok',
seed: 'Seed', kimi: 'Kimi', glm: 'GLM', grok: 'Grok', infistar: 'Infistar',
} as Record<string, string>)[key] || key
const knownCloudModels = (catalog: Record<string, string[]>, extra: string[] = []) =>
new Set([...Object.values(catalog).flat(), ...extra])
@@ -93,7 +97,7 @@ const cloudModelOptions = (
const CLOUD_DEFAULT_MODEL: Partial<Record<ProviderKey, string>> = {
dashscope: 'qwen-plus', openai: 'gpt-5-mini', gemini: 'gemini-3.8-flash', deepseek: 'deepseek-flash',
seed: 'doubao-seed-2-1-lite-260915', kimi: 'kimi-k2.6', glm: 'glm-5.3', grok: 'grok-4.6',
seed: 'doubao-seed-2-1-lite-260915', kimi: 'kimi-k2.6', glm: 'glm-5.3', grok: 'grok-4.6', infistar: undefined,
}
type SectionKey = 'analysis' | 'vision' | 'model' | 'speech' | 'app' | 'publish' | 'cover' | 'feedback'
@@ -174,6 +178,7 @@ const SettingsPage: React.FC = () => {
kimi_api_key: settingsData.api?.api_keys?.kimi || '',
glm_api_key: settingsData.api?.api_keys?.glm || '',
grok_api_key: settingsData.api?.api_keys?.grok || '',
infistar_api_key: settingsData.api?.api_keys?.infistar || '',
seed_api_key: settingsData.api?.api_keys?.seed || '',
jimeng_access_key: settingsData.api?.api_keys?.jimeng_access || '',
jimeng_secret_key: settingsData.api?.api_keys?.jimeng_secret || '',
@@ -212,6 +217,7 @@ const SettingsPage: React.FC = () => {
kimi: values.kimi_api_key || keys.kimi || '',
glm: values.glm_api_key || keys.glm || '',
grok: values.grok_api_key || keys.grok || '',
infistar: values.infistar_api_key || keys.infistar || '',
seed: values.seed_api_key || keys.seed || '',
jimeng_access: values.jimeng_access_key || keys.jimeng_access || '',
jimeng_secret: values.jimeng_secret_key || keys.jimeng_secret || ''
@@ -476,6 +482,19 @@ const SettingsPage: React.FC = () => {
</Row>
)}
{cfg.sponsor && (
<Row
wide
label={t("开始使用")}
hint={t("通过 AutoClip 专属推广链接注册可领取 $5 体验额度,领取条件以活动页面为准。注册后在控制台创建 API Key,粘贴到下方。该链接含推广分成,用于支持项目维护。")}
>
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
<Btn variant="cta" size="sm" onClick={() => { trackSponsorLinkOpened({ sponsor: 'infistar', target: 'register', placement: 'settings_model' }); openExternalLink(cfg.sponsor!.registerUrl) }}>{t("注册并领取体验额度")}</Btn>
<Btn size="sm" onClick={() => { trackSponsorLinkOpened({ sponsor: 'infistar', target: 'guide', placement: 'settings_model' }); openExternalLink(cfg.sponsor!.guideUrl) }}>{t("接入说明")}</Btn>
</div>
</Row>
)}
{!localCfg && <Row
wide
label="API Key"
@@ -512,6 +531,8 @@ const SettingsPage: React.FC = () => {
? <>{t("已拉取最新模型数量", { count: cloudModels.models.length })} <a onClick={() => void loadCloudModels(selectedProvider, { refresh: true })} style={{ color: 'var(--ac-accent)', cursor: 'pointer' }}>{t("刷新")}</a></>
: usingCustomEndpoint
? <>{t("填该服务实际提供的模型名(如 glm-4-flash、deepseek-chat、qwen2.5:7b),回车确认。")} <a onClick={() => void loadCloudModels(selectedProvider, { refresh: true })} style={{ color: 'var(--ac-accent)', cursor: 'pointer' }}>{t("刷新")}</a></>
: cfg.sponsor && !cloudModels.models.length
? <>{t("填写 API Key 后会自动列出该账号可用的模型,选一个即可。")} <a onClick={() => void loadCloudModels(selectedProvider, { refresh: true })} style={{ color: 'var(--ac-accent)', cursor: 'pointer' }}>{t("刷新")}</a></>
: <>{t("可直接输入模型名,回车确认。")} {t("填写密钥后可拉取该账号可用的最新模型。")} <a onClick={() => void loadCloudModels(selectedProvider, { refresh: true })} style={{ color: 'var(--ac-accent)', cursor: 'pointer' }}>{t("刷新")}</a></>}
>
<Form.Item name="model_name" style={{ width: '100%' }} rules={[{ required: true, message: t("请输入或选择模型") }]}>