在 CodexBar 中接入 ElevenLabs Provider:API Key 配置、订阅用量解析与错误排查实战指南
【免费下载链接】CodexBarShow usage stats for OpenAI Codex and Claude Code, without having to login.项目地址: https://gitcode.com/GitHub_Trending/co/CodexBar
ElevenLabs 是 CodexBar 内置的用量统计 Provider 之一,它通过官方订阅接口按 API Key 读取当前计费周期内的字符额度、剩余字符数、重置时间与音色槽位用量,无需任何浏览器登录流程。本篇指南以 docs/elevenlabs.md 为核心骨架,结合仓库内 ElevenLabs Provider 的完整源码实现与测试用例,系统讲解其功能边界、三种配置方式、底层 API 解析逻辑与全部错误场景的定位方法,读完即可在菜单栏中正确展示 ElevenLabs 额度并独立排障。
功能总览:ElevenLabs Provider 能展示什么
ElevenLabs Provider 的数据来源是官方订阅接口,面向 API Key 鉴权场景,主要提供以下能力:
- 字符信用额度(Character credits):展示当前订阅周期内已使用字符数与总限额;
- 重置时间:当接口返回
next_character_count_reset_unix时,将其换算为本地重置时间并用于"何时回满额度"的提示; - 音色槽位用量:当响应中存在
voice_slots_used/voice_limit与professional_voice_slots_used/professional_voice_limit时,分别展示普通音色与专业音色槽位的占用情况; - 套餐与状态文本:从订阅响应中解析
tier(套餐档位)与status(订阅状态),用于菜单栏的登录方式与套餐标签显示。
值得注意的两个设计点:其一,该 Provider不支持费用历史与 Token 成本统计,其令牌成本配置中的提示文案明确写着"ElevenLabs cost history is not available via API yet"(见 ElevenLabsProviderDescriptor.swift);其二,它默认不启用(defaultEnabled: false),需要用户显式配置并开启。
工作原理:订阅接口的请求与字段映射
请求规格
Provider 的核心请求封装在 ElevenLabsUsageFetcher.swift 中:
- 端点:
GET https://api.elevenlabs.io/v1/user/subscription - 鉴权头:
xi-api-key: <key>(同时设置Accept: application/json) - 超时:15 秒(
timeoutSeconds = 15,测试中亦有对应断言) - Key 预处理:请求前会对 API Key 做空白字符 trim,空白 Key 直接抛出
missingCredentials,不会发出网络请求
响应字段映射
响应体通过ElevenLabsSubscriptionResponse解码(snake_case 与 Swift 驼峰命名通过CodingKeys映射),完整字段如下:
| 接口字段 | 内部属性 | 说明 |
|---|---|---|
character_count | characterCount | 当前周期已使用字符数 |
character_limit | characterLimit | 当前周期字符总额度 |
voice_slots_used | voiceSlotsUsed | 已占用普通音色槽位(可选) |
voice_limit | voiceLimit | 普通音色槽位上限(可选) |
professional_voice_slots_used | professionalVoiceSlotsUsed | 已占用专业音色槽位(可选) |
professional_voice_limit | professionalVoiceLimit | 专业音色槽位上限(可选) |
current_overage | currentOverage | 当前超额信息{amount, currency}(可选) |
tier | tier | 套餐档位(可选) |
status | status | 订阅状态(可选) |
next_character_count_reset_unix | nextCharacterCountResetUnix | 下次字符额度重置的 Unix 时间戳(可选) |
解码成功后,parseSnapshot将next_character_count_reset_unix转换为Date存入resetsAt,供菜单栏的刷新倒计时使用。
用量与展示计算
ElevenLabsUsageSnapshot提供三个关键派生值,均有测试覆盖(见 ElevenLabsUsageFetcherTests.swift):
usedPercent:character_count / character_limit经UsagePercent的displayClamped处理后的显示百分比,额度为 0 时返回 0;remainingCharacters:max(0, character_limit - character_count),即剩余字符数;toUsageSnapshot():将快照映射为通用UsageSnapshot。其中主用量窗口的 reset 描述格式为"25,000 / 100,000 credits"(数字带千分位分组);当音色槽位字段存在且 limit 大于 0 时,会额外生成voice-slots(Voice slots)与professional-voices(Professional voices)两个命名窗口,作为extraRateWindows叠加展示。
套餐标签的展示逻辑也有讲究:tier中的下划线会被替换为空格并首字母大写(如creator显示为Creator);当status存在且不为active时,会追加" · <status>"后缀;若tier为空则直接回退显示status。此外,ElevenLabsProviderDescriptor.swift 中还维护了一套套餐档位到本地化标签的映射表:free / starter / creator / pro / scale / business / growing business / enterprise分别对应Free / Starter / Creator / Pro / Scale / Business / Business / Enterprise。
端点覆盖与 URL 拼装
请求默认打到https://api.elevenlabs.io,但支持通过ELEVENLABS_API_URL覆盖(详见下文"环境变量")。URL 拼装逻辑在subscriptionURL(baseURL:)中:若基础 URL 路径以/v1结尾,则直接追加user/subscription;否则追加v1/user/subscription。因此https://elevenlabs.test与https://elevenlabs.test/v1/两种写法都能正确得到/v1/user/subscription,这一点同样有测试专门验证(fetch usage accepts versioned API base with trailing slash)。
配置方式:三种途径与多 Key 账户
方式一:CLI 快速写入(推荐)
无需打开设置界面,一条命令即可把 Key 写入本地配置:
printf '%s' "$ELEVENLABS_API_KEY" | codexbar config set-api-key --provider elevenlabs --stdin该命令会:trim 管道传入的 Key → 以受限文件权限写入~/.codexbar/config.json→ 默认启用 ElevenLabs Provider。如果只想保存 Key 而不启用 Provider,追加--no-enable参数即可。这一能力由 CLIConfigCommand.swift 提供。
方式二:设置界面
- 打开Settings -> Providers;
- 启用ElevenLabs;
- 在 ElevenLabs 控制台的API Keys设置页创建或复制一个 API Key;
- 将 Key 粘贴到 CodexBar 的 ElevenLabs Provider 设置项中。
对应设置字段由 ElevenLabsProviderImplementation.swift 描述:这是一个 secure 类型的 "API key" 字段,占位符为xi-...,存储位置同样是~/.codexbar/config.json。Provider 的可用性判定也很明确:只要环境变量中存在 Key、配置中已填写 Key、或已配置至少一个 ElevenLabs 令牌账户,Provider 即视为可用。
方式三:环境变量
CodexBar 依次读取以下环境变量(第一个非空值生效,且值会被 trim,支持去掉成对的引号包裹):
| 变量 | 用途 |
|---|---|
ELEVENLABS_API_KEY | 主 API Key |
XI_API_KEY | ElevenLabs 官方兼容别名(兼容旧脚本/旧环境) |
ELEVENLABS_API_URL | 覆盖 API 基础地址,用于测试或自托管/代理场景 |
环境变量的解析与校验集中在 ElevenLabsSettingsReader.swift。需要特别说明ELEVENLABS_API_URL的安全约束:该值必须通过ProviderEndpointOverrideValidator.normalizedHTTPSURL的校验(即 HTTPS URL 或裸主机名),否则会抛出invalidEndpointOverride错误,提示"ElevenLabs endpoint override must use HTTPS or a bare host"。这一校验同样适用于其他 Provider,防止配置被篡改为非 HTTPS 端点。
多 Key 令牌账户
除上述单一 Key 之外,ElevenLabs Provider 还支持令牌账户(Token Account):在 ElevenLabsProviderDescriptor.swift 的凭据适配器中,令牌账户被描述为"Store multiple ElevenLabs API keys",占位符为Paste API key…,以环境注入方式(ELEVENLABS_API_KEY)向请求解析器提供当前激活账户的 Key。这意味着你可以维护多个 ElevenLabs Key 账户并随时切换;故障排查中提到的"活跃账户优先于独立 API Key 字段"正是这一机制的表现。
状态码处理与错误分类机制
fetchUsage对 HTTP 状态码的分流非常清晰:
- 200:解析订阅响应;
- 401:调用
authenticationError(responseData:),默认归类为authenticationFailed; - 403:调用
authenticationError(responseData:fallback: .accessDenied),默认归类为accessDenied; - 其余状态码:记录日志并抛出通用
apiError("HTTP <code>")。
authenticationError会先尝试从响应体中解码detail对象,然后依次优先读取detail.code,再读取旧的detail.status字段——因为线上响应可能用通用 code 搭配更具体的 legacy status。两个字段任一命中以下值即完成归类(均先 trim 再转小写匹配):
| 识别值(code 或 status) | 归类错误 | 触发状态码 |
|---|---|---|
invalid_api_key | invalidCredentials | 401 |
missing_permissions/insufficient_permissions | missingPermissions | 401 / 403 |
| 其他未知值 | authenticationFailed(401)或accessDenied(403) | 401 / 403 |
一个值得强调的安全细节:错误消息(如message字段中的敏感内容)不会被复制进诊断输出。测试current and legacy error details preserve safe diagnostics专门验证了包含sensitive-response-marker的原始消息绝不会出现在errorDescription中。
故障排查:全部错误场景速查
"Missing ElevenLabs API key"
Key 未配置。按上面任一方式补齐即可:使用codexbar config set-api-key --provider elevenlabs --stdin、在Settings -> Providers -> ElevenLabs中粘贴 Key、设置ELEVENLABS_API_KEY环境变量,或配置一个 ElevenLabs 令牌账户。对应源码中的missingCredentials,其错误描述会提示在~/.codexbar/config.json的apiKey字段或ELEVENLABS_API_KEY中设置。
"ElevenLabs rejected the selected API key"
接口返回了识别为invalid_api_key的认证/访问错误。请确认 Key 有效且未被吊销;若配置了多个 ElevenLabs API-Key 账户,注意当前激活账户优先于独立的 API Key 字段,应检查激活账户所用的 Key。
"ElevenLabs API key is missing the user_read permission"
接口返回 HTTP 401/403,且错误标识为missing_permissions或insufficient_permissions。请为所选 Key 开启user_read权限——CodexBar 需要该权限才能获取订阅用量。
"ElevenLabs could not authenticate the selected API key"
接口返回 HTTP 401 且错误中未识别出已知的 code/status。检查 Key 本身及该 Key 的端点权限。
"ElevenLabs denied access for the selected API key"
接口返回 HTTP 403 且未识别出明确的 Key 或权限错误。检查该 Key 的端点权限以及 ElevenLabs API-Key 设置中的IP 白名单(IP allowlist)——请求来源 IP 被拒通常表现为这一场景。
"ElevenLabs API error"
非 2xx 且非 401/403 的通用错误(例如 HTTP 500)。确认当前网络可以访问api.elevenlabs.io,并核对报告的具体 HTTP 状态码。
关于错误判定的整体规则:CodexBar 优先读取响应中已识别的detail.code值,其次读取旧版detail.status(当 code 缺失或过于泛化时,线上响应仍可能用该字段表达具体拒绝原因),具体实现见 ElevenLabsUsageFetcher.swift 的authenticationError方法;Provider 错误消息不会原样进入诊断输出。
源码级验证:测试如何保证解析正确
ElevenLabs Provider 的解析与错误逻辑在 ElevenLabsUsageFetcherTests.swift 中有系统性覆盖,主要验证点包括:
- 完整响应解析:一份包含全部字段的样例响应(
tier: creator、25,000/100,000 字符、2/10 普通音色、1/2 专业音色、current_overage、next_character_count_reset_unix)应得到 25% 用量、75,000 剩余字符、"25,000 / 100,000 credits"的 reset 描述、Creator登录标签与 2 个附加音色窗口; - 请求头正确性:
xi-api-key头、/v1/user/subscription路径与 15 秒超时均有断言; - 错误分类矩阵:13 组 401/403 与不同
detail形态(code 优先、status 兜底、大小写与空白容忍、空 detail、非 JSON、非对象 detail 等)逐一映射到正确的错误类型; - 安全约束:敏感响应内容不会泄漏到错误描述中;
- 空 Key 拦截:纯空白 Key 在发请求前即被拒绝。
此外,ElevenLabsUsageSnapshotLinuxTests.swift 提供了 Linux 侧的用量快照测试,印证该 Provider 的解析逻辑在跨平台(macOS/Linux)测试链路中保持一致。
小结
ElevenLabs Provider 是 CodexBar 众多 Provider 中典型的"纯 API Key + 订阅接口"范式:无浏览器 Cookie、无登录态,数据面只有字符额度、音色槽位与套餐状态三类信息,但通过完善的字段映射、额度百分比/剩余量计算、tier标签本地化、多 Key 令牌账户与精细的错误分类,足以在菜单栏中提供可靠的 ElevenLabs 用量监控。配置侧,CLI 管道写入、设置界面与环境变量三选一即可完成接入;排障侧,五类具体错误消息配合 code/status 双字段识别机制,能让绝大多数认证与权限问题在几十秒内定位。如果你正自托管或通过代理访问 ElevenLabs API,ELEVENLABS_API_URL配合 HTTPS 校验的覆盖机制同样为你预留了完整的接入路径。更多 Provider 横向对比可参考 docs/providers.md。
【免费下载链接】CodexBarShow usage stats for OpenAI Codex and Claude Code, without having to login.项目地址: https://gitcode.com/GitHub_Trending/co/CodexBar
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考