本地网关 API

从本机或其他可信机器调用 EdgeSpeak API。

快速开始

在本机调用时,先启动桌面 App 及其本地网关,再使用 App 内展示的 API 密钥。桌面网关默认绑定 127.0.0.1,基础地址为 http://127.0.0.1:1117/v1。全新安装默认关闭本机鉴权,需要时在 App 内开启。开启后,网关同时支持 Authorization: Bearerx-api-key 请求头。

export EDGESPEAK_BASE_URL=http://127.0.0.1:1117/v1
export EDGESPEAK_API_KEY=sk-edgespeak-...

curl "$EDGESPEAK_BASE_URL/models" \
  -H "Authorization: Bearer $EDGESPEAK_API_KEY"

# Anthropic-compatible clients may use this instead:
# -H "x-api-key: $EDGESPEAK_API_KEY"

从另一台机器调用 API

可以在具备所需 CPU/GPU 计算能力并已安装本地模型的机器上启动 Headless 服务,无需安装或运行桌面 App。桌面网关只能供本机调用;如需让其他机器访问,可以让 edgespeak-cli serve 显式监听局域网或私有 VPN 地址。默认情况下,它仍只监听 http://127.0.0.1:1118/v1

服务端(运行服务的机器)上,先从受保护的密钥存储中读取一段足够长的随机密钥,再启动服务:

export EDGESPEAK_API_KEY="your-long-random-secret"
edgespeak-cli serve --host 0.0.0.0 --port 1118 --allow-remote

监听非回环地址时,如果没有传入 --allow-remote,服务会拒绝启动。同时还必须设置非空的 EDGESPEAK_API_KEY,除非显式传入 --allow-unauthenticated。只有在隔离的测试网络中,才应考虑关闭远程鉴权。

调用端(发起调用的机器)上,将 192.168.1.50 替换为服务端实际使用的局域网或 VPN 地址,并使用同一个密钥:

export EDGESPEAK_BASE_URL=http://192.168.1.50:1118/v1
export EDGESPEAK_API_KEY="the-same-secret"

curl "$EDGESPEAK_BASE_URL/models" \
  -H "Authorization: Bearer $EDGESPEAK_API_KEY"

0.0.0.0 只是服务端监听地址,不能写入客户端 URL。如果 EdgeSpeak 能唯一识别可用网卡,启动日志会输出可直接复制的 EdgeSpeak service network URL。模型管理和下载、推理以及 License 验证都由服务端负责;调用时上传的音频、提示词、图片和返回的响应会在两台机器之间传输。

Headless 服务与桌面 App 使用同一套网关实现:本页所列接口的路径与请求格式在两端一致,差异在基础地址和 API 密钥。有两类输入是桌面端独有的:流式转录(stream=true)在 Headless 监听面会返回 400;本机文件路径同样不接受——Headless 监听面只读取上传的字节,因此对齐接口请传 text 而不是 text_path,分句接口请直接传 segments[] 而不是 file

Headless 服务只提供 HTTP,不内置 HTTPS。请仅在可信的局域网或私有 VPN 中使用,并通过服务端防火墙将 TCP 1118 端口限制在可信来源范围内。也可以继续监听默认回环地址,再通过 SSH 隧道从另一台机器访问:

ssh -L 1118:127.0.0.1:1118 user@edgespeak-host

如果客户端运行在浏览器中,还需要通过 --allow-origin https://your-app.example 准确添加页面来源。如果 HTTPS 反向代理把 Host 请求头改为域名,请通过 --allow-host gateway.example 将域名本身加入允许列表;直接使用 IP 地址调用时,无需配置 --allow-host。安装和启动方式见 CLI 服务说明

音频与文本

可以转录上传媒体、对齐已知文稿、进行语义分句、合成语音并管理可复用的本机声音。转录支持 json、verbose_json、text、diarized_json,以及 JSON 模式的 SSE 流;verbose 与说话人输出支持时间戳粒度。通用请求体上限为 512 MiB。

POST   /v1/audio/transcriptions   # speech → text, JSON or SSE
POST   /v1/audio/alignments       # known text → word timing
POST   /v1/audio/speech           # text → speech
GET    /v1/audio/voices           # list voices
POST   /v1/audio/voices           # add a reusable voice
DELETE /v1/audio/voices/:voice_id # delete a user voice
POST   /v1/text/segmentations     # text or timed segments → sentences

说话人

需要带说话人标签的文稿时使用 diarized_json;只需要说话人活动时间线时调用 /v1/speaker/diarizations。还可以生成说话人嵌入并计算余弦相似度,用于本机匹配。num_speakers 只是可选的聚类提示,不代表真实身份。说话人端点接收上传的音频字节,不接受任意本机路径。

POST /v1/audio/transcriptions
  response_format=diarized_json

POST /v1/speaker/diarizations
  multipart: file, num_speakers (optional)

POST /v1/speaker/embeddings
POST /v1/speaker/similarity

Realtime API

通过 WebSocket 建立实时转录会话,或完整的 ASR → 语言模型 → 语音会话。先发送 session.update,再持续追加 base64 PCM16LE 单声道音频。服务器客户端可以使用普通鉴权 Header;浏览器 WebSocket 客户端必须提供 realtime 与 openai-insecure-api-key.<KEY> 子协议。本机语言模型用于 Realtime 前需要预先加载。

const ws = new WebSocket(
  "ws://127.0.0.1:1117/v1/realtime",
  ["realtime", "openai-insecure-api-key.<KEY>"]
);

session.created
  → session.update              # type: transcription | realtime
  → input_audio_buffer.append   # base64 PCM16LE mono
  → input_audio_buffer.commit

events: conversation.item.input_audio_transcription.*
        response.output_text.*
        response.output_audio.*
        response.done | error

语言与视觉 API

根据客户端选择 OpenAI Responses、Chat Completions、Anthropic Messages 或分词接口。并非每个模型都支持全部端点;请从 /v1/models 读取 supported_endpoints,并检查 execution_location。本机模型让输入留在设备上;已配置的远程模型会接收发给它的请求。

POST /v1/responses          # OpenAI Responses-compatible
POST /v1/chat/completions   # OpenAI Chat Completions-compatible
POST /v1/messages           # Anthropic Messages-compatible
POST /v1/tokenize

curl http://127.0.0.1:1117/v1/responses \
  -H "Authorization: Bearer sk-edgespeak-..." \
  -H "Content-Type: application/json" \
  -d '{"model":"Qwen/Qwen3.5-4B","input":"Summarize this meeting"}'

原生视频输入

macOS 和 Linux 的原生视频构建支持在 POST /v1/chat/completions 中向已安装的本机多模态模型传入 input_video。桌面网关与 Headless 服务使用同一套按模型区分的预处理。Realtime WebSocket 会话不接受 input_video;其中的图片事件是静态图片,不是连续视频流。

EdgeSpeak 根据当前模型的目录配置或导入仓库元数据自动选择采样率;它不是请求字段,也不是 Server 启动参数:

本机模型家族采样率参考预处理
Qwen 3.5 / Qwen 3.62 FPSQwen 示例使用 fps=2.0 并启用抽帧
Gemma 41 FPSGemma 按 1 FPS 说明视频容量

这些数值依据模型发布方的参考预处理,而不是源视频自身的帧率。切换模型家族时,本机 worker 会使用对应数值重启。参考 Qwen 3.5Qwen 3.6Gemma 4 模型文档。

桌面 App 从 Hugging Face 或 ModelScope 导入 GGUF 仓库时,会尽力读取仓库根目录的 config.jsontokenizer_config.jsonprocessor_config.json。检测到的 video_processor.fps 会作为推荐值;缺少元数据时,已知 Qwen/Gemma 家族采用上表数值,其他包含 mmproj 文件的仓库默认使用 1 FPS。若 config.json 声明了视觉模块但没有可用的 mmproj,界面会显示警告,不会把它误判为可运行的视觉模型。用户可以在模型 → 生成设置中改为 1、2、4 或 8 FPS。采样帧越多,通常时间覆盖越完整,但也会消耗更多视觉 token、上下文、内存和处理时间。

在 Chat Completions 内容项中传入视频文件字节的 base64 编码:

{
  "model": "Qwen/Qwen3.5-4B",
  "messages": [
    {
      "role": "user",
      "content": [
        { "type": "text", "text": "请按时间顺序概括这段视频。" },
        { "type": "input_video", "input_video": { "data": "<base64 MP4 bytes>" } }
      ]
    }
  ]
}

视频解码要求服务所在机器同时提供 ffmpegffprobe。EdgeSpeak 不捆绑它们;macOS 可通过 Homebrew 安装 ffmpeg,Linux 可使用系统包管理器。完整 JSON 请求上限为 512 MiB,而 base64 会让源文件体积增加约三分之一,因此请使用时长较短、尺寸适当的视频。

上下文窗口

文本输入、对话历史、图片或视频采样帧转换出的视觉 token,以及模型输出,共享同一份上下文预算。更大的上下文可以保留更多历史或视频内容,但会在内存或显存中分配更大的 KV 缓存;更小的上下文能给模型和其他任务留下更多内存,但请求会更早达到上限。

在桌面 App 中,打开本机模型卡片的模型 → 生成设置 → 上下文长度。自动值当前为 8K,也可以从 4K 开始选择,最高不超过模型支持的上限。目录模型使用目录声明的上限;从 Hugging Face 或 ModelScope 导入的模型会依次检查 max_position_embeddings(包括嵌套的文本/语言配置)或 model_max_length、已知模型家族上限,全部缺失时再以 262K 作为可选上限兜底。设置按模型分别保存;保存后会卸载当前本机模型,下一次请求再按新的上下文长度加载 worker。

Headless Server 使用独立的启动配置,不读取桌面端偏好。启动时传入 --context-tokens;默认值为 8192 token,可接受范围为 512–262144,并应选择不超过当前模型支持上限的值。修改后需要重启对应的 Headless Server 进程。

edgespeak-cli serve --context-tokens 32768

模型发现与生命周期

使用 /v1/models 返回的规范模型 ID,单独查看正在运行的模型,并显式加载或卸载本机语言模型以控制下载状态和内存。模型下载可以发起、查询进度和取消。所需本机模型仍在准备时,请求可能返回 503 model_downloading,并通过 Retry-After 指示重试时机。

GET  /v1/models
GET  /v1/models/running
POST /v1/models/load
POST /v1/models/unload

GET  /v1/models/downloads        # download progress
POST /v1/models/download         # start a download
POST /v1/models/download/cancel  # cancel a download

# Select by supported_endpoints and execution_location.
# Local language models must be loaded before Realtime use.

MCP

Agent 场景推荐通过 edgespeak-cli mcp 使用 stdio;受支持的工具无需桌面 App,也能拉起随附的本机运行时。桌面网关和 Headless 服务都会在 /mcp 提供 Streamable HTTP,各自沿用自己的鉴权设置与 API key。

edgespeak-cli mcp                   # recommended: stdio
POST http://127.0.0.1:1117/mcp      # Streamable HTTP, desktop gateway
POST http://127.0.0.1:1118/mcp      # Streamable HTTP, headless service

错误、浏览器访问与安全

License、配额、鉴权、模型就绪状态和运行时繁忙等失败使用结构化错误响应。没有 Origin 的非浏览器客户端可访问,但仍会检查 Host。浏览器请求默认只允许回环地址来源;若要使用可信的非回环来源和代理 Host,需要通过环境变量显式加入白名单。不要把长期有效的网关 key 写入公开前端代码。

401  invalid or missing API key
403  host or origin is not allowed
413  request body exceeds 512 MiB
503  model_downloading              # honor Retry-After

EDGESPEAK_GATEWAY_PORT=1117
EDGESPEAK_GATEWAY_ALLOWED_ORIGINS=https://app.example.com
EDGESPEAK_GATEWAY_ALLOWED_HOSTS=proxy.example.com