# Gemini 双协议与视频分析

## 先确认模型入口

管理员为模型启用协议桥接后，Gemini 原生、Chat Completions、Responses 共用同一个公开模型 ID、权限和价格。上游可以使用 Gemini 原生接口，也可以使用 OpenRouter 等兼容接口；网关按所选上游转换，并用你调用的协议返回结果。

使用平台域名和平台 Key，分别通过带认证的 `GET /v1/models` 与 `GET /v1beta/models` 查询可用模型。不要把平台 Key 发送给 OpenRouter。该功能按模型启用，不代表所有型号或所有供应商专用参数都支持跨协议转换。

## 三种视频请求

以下例子中的 `gemini-4-argon` 必须替换为当前账号实际可用的 ID；URL 替换为可访问的视频文件直链或签名链接。它应返回视频文件，不能是播放器网页。

Gemini 原生：`POST /v1beta/models/gemini-4-argon:generateContent`，使用 `x-goog-api-key: API_KEY`。

```json
{
  "contents": [{"role": "user", "parts": [
    {"text": "按时间顺序分析整段视频，说明画面变化和声音。"},
    {"fileData": {"mimeType": "video/mp4", "fileUri": "https://files.example.com/clip.mp4"}}
  ]}],
  "generationConfig": {"maxOutputTokens": 4096, "thinkingConfig": {"thinkingLevel": "LOW", "includeThoughts": true}}
}
```

Chat Completions：`POST /v1/chat/completions`，使用 `Authorization: Bearer API_KEY`。

```json
{
  "model": "gemini-4-argon",
  "messages": [{"role": "user", "content": [
    {"type": "text", "text": "按时间顺序分析整段视频，说明画面变化和声音。"},
    {"type": "video_url", "video_url": {"url": "https://files.example.com/clip.mp4"}}
  ]}],
  "max_tokens": 4096,
  "reasoning_effort": "low"
}
```

Responses：`POST /v1/responses`，使用 `Authorization: Bearer API_KEY`。

```json
{
  "model": "gemini-4-argon",
  "input": [{"role": "user", "content": [
    {"type": "input_text", "text": "按时间顺序分析整段视频，说明画面变化和声音。"},
    {"type": "input_video", "video_url": "https://files.example.com/clip.mp4"}
  ]}],
  "max_output_tokens": 4096,
  "reasoning": {"effort": "low"},
  "store": false
}
```

视频字段是兼容接口的扩展；SDK 必须允许发送这些内容片段。对于本地文件，Gemini 使用 `inlineData: {"mimeType":"video/mp4","data":"BASE64"}`；另外两种接口把 URL 换成 `data:video/mp4;base64,BASE64`。不要重复编码 data URL。

**视频 URL** 的原文件上限为 **15 MB（15,000,000 字节）**，超限在转发前返回 413。**内联 base64 可以超过 15 MB**，按编码后的完整 JSON 请求预算校验；默认预算为 100 MiB，部署或上游可以设置更低限制。base64 约增加三分之一体积，因此请求预算不等于原文件容量。

固定走 OpenRouter / Google Vertex 时，网关会安全下载直链并编码原文件。上传保持原画质、时长和音轨，不自动压缩或裁剪。两分钟、1080P 已覆盖转发保真测试，容量仍须满足所选输入方式及实际上游的限制。签名链接必须在下载期间有效；不要把签名参数或 Key 写进日志。

需要可返回的思考摘要时，在 Gemini 请求中设置 `generationConfig.thinkingConfig.includeThoughts: true`，并读取响应中 `thought: true` 的文本部分。它是供应商提供的思考摘要；部分请求可能没有该部分，不能把非零思考 token 数当作一定返回了摘要。

## 流式和多轮追问

Gemini 流式使用 `:streamGenerateContent?alt=sse`；Chat 和 Responses 增加 `"stream": true`。按对应协议消费事件和结束状态，不要把 SSE 当作普通 JSON。

追问时保留完整助手消息：

```javascript
// Gemini：保留 parts 中的 thoughtSignature。
contents.push(first.candidates[0].content);
contents.push({ role: 'user', parts: [{ text: '最后十秒发生了什么？' }] });

// Chat：保留整条 message，包括 reasoning_details 和 tool_calls。
messages.push(first.choices[0].message);
messages.push({ role: 'user', content: '最后十秒发生了什么？' });

// Responses：保留所有 output items，包括加密 reasoning items。
input.push(...first.output);
input.push({ role: 'user', content: [{ type: 'input_text', text: '最后十秒发生了什么？' }] });
```

三个片段分别用于各自协议。不要只拷贝可见文字，不要修改或解析 opaque 签名。工具结果必须关联原来的调用 ID。跨协议 Responses 使用完整历史，不使用 `previous_response_id`。

长输出可能返回续写状态。Gemini 使用候选结果中的 `continuationToken`，继续时把它放到原请求顶层；Chat/Responses 保留停止的助手消息或 output items。保持原始输入和参数，仅按需要提高输出 token 上限。每次续写都是独立计费请求；网关不会自动执行下一跳。跨协议流需要完整结束才能拿到完整上下文，断流后不能假定可以自动续传。

没有可兼容的上游、过期文件链接或不能转换的字段会明确报错；不会通过丢掉视频、工具参数或切换受限制的提供商来继续请求。发生断流或超时时，先用响应中的 `x-gateway-request-id` 查询请求与用量，不盲目重复生成。
