一、环境变量
在部署环境中设置以下值,不要把密钥写入源代码:export BASE_URL='https://api.bytedance.mom'
export API_KEY='your-byte-api-key'
export GEMINI_MODEL='gemini-3.7-flash'
GEMINI_MODEL来使用其他 Gemini 系列模型。
请求地址为:
POST ${BASE_URL}/v1beta/models/${GEMINI_MODEL}:generateContent
Authorization: Bearer ${API_KEY}
二、分意图请求说明
1、媒体视频识别
通过我们的原生 Gemini 路由,把完整 MP4 以 Base64inlineData 发送给模型进行识别。
Byte API 的该路由只支持inlineData。不要使用 Google Gemini File API、fileData.fileUri或把视频 URL 直接放入请求体。
Python
依赖:pip install requests
import base64
import os
from pathlib import Path
import requests
video_path = Path("/path/to/source.mp4")
video_b64 = base64.b64encode(video_path.read_bytes()).decode("ascii")
base_url = os.environ["BASE_URL"].rstrip("/")
api_key = os.environ["API_KEY"]
model = os.getenv("GEMINI_MODEL", "gemini-3.7-flash")
payload = {
"contents": [{
"role": "user",
"parts": [
{
"inlineData": {
"mimeType": "video/mp4",
"data": video_b64,
}
},
{
"text": "分析这条视频"
},
],
}]
}
response = requests.post(
f"{base_url}/v1beta/models/{model}:generateContent",
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {api_key}",
},
json=payload,
# connect timeout, read timeout(视频理解通常比纯文本慢,超时时长尽量调高一些)
timeout=(15, 300),
)
response.raise_for_status()
result = response.json()
print(result["candidates"][0]["content"]["parts"][0]["text"])
Java(JDK 17+)
不需要额外 HTTP 依赖。jsonString 用于安全地将提示词写入 JSON;Base64 字符串本身无需再转义。
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import java.util.Base64;
public class GeminiVideoExample {
private static String jsonString(String value) {
return "\"" + value
.replace("\\", "\\\\")
.replace("\"", "\\\"")
.replace("\n", "\\n")
.replace("\r", "\\r")
.replace("\t", "\\t") + "\"";
}
public static void main(String[] args) throws Exception {
String baseUrl = System.getenv("BASE_URL").replaceAll("/+$", "");
String apiKey = System.getenv("API_KEY");
String model = System.getenv().getOrDefault("GEMINI_MODEL", "gemini-3.7-flash");
byte[] videoBytes = Files.readAllBytes(Path.of("/path/to/source.mp4"));
String videoBase64 = Base64.getEncoder().encodeToString(videoBytes);
String prompt = "分析这条视频";
String body = """
{
"contents": [{
"role": "user",
"parts": [
{"inlineData": {"mimeType": "video/mp4", "data": "%s"}},
{"text": %s}
]
}]
}
""".formatted(videoBase64, jsonString(prompt));
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/v1beta/models/" + model + ":generateContent"))
.timeout(Duration.ofMinutes(5))
.header("Content-Type", "application/json")
.header("Authorization", "Bearer " + apiKey)
.POST(HttpRequest.BodyPublishers.ofString(body, StandardCharsets.UTF_8))
.build();
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(15))
.build();
HttpResponse<String> response = client.send(
request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
if (response.statusCode() / 100 != 2) {
throw new IllegalStateException("New API error "
+ response.statusCode() + ": " + response.body());
}
System.out.println(response.body());
}
}
JavaScript(Node.js 18+)
Node.js 18 及以上已提供全局fetch。
import { readFile } from "node:fs/promises";
const baseUrl = process.env.BASE_URL.replace(/\/+$/, "");
const apiKey = process.env.API_KEY;
const model = process.env.GEMINI_MODEL || "gemini-3.7-flash";
const video = await readFile("/path/to/source.mp4");
const videoBase64 = video.toString("base64");
const response = await fetch(
`${baseUrl}/v1beta/models/${model}:generateContent`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`,
},
body: JSON.stringify({
contents: [{
role: "user",
parts: [
{
inlineData: {
mimeType: "video/mp4",
data: videoBase64,
},
},
{ text: "分析这条视频" },
],
}]
}),
signal: AbortSignal.timeout(300_000),
},
);
if (!response.ok) {
throw new Error(`New API error ${response.status}: ${await response.text()}`);
}
const result = await response.json();
console.log(result.candidates?.[0]?.content?.parts?.[0]?.text);
2、文本聊天
文本聊天与视频识别使用相同的 Gemini 原生端点。将系统提示词放在顶层systemInstruction,将用户消息放在 contents 中即可;不需要 inlineData。
POST ${BASE_URL}/v1beta/models/${GEMINI_MODEL}:generateContent
Authorization: Bearer ${API_KEY}
generationConfig 是可选项,不写时使用模型/网关的默认值。
Python
依赖:pip install requests
import os
import requests
base_url = os.environ["BASE_URL"].rstrip("/")
api_key = os.environ["API_KEY"]
model = os.getenv("GEMINI_MODEL", "gemini-3.7-flash")
payload = {
"systemInstruction": {
"parts": [{"text": "我是一个地理专家"}]
},
"contents": [{
"role": "user",
"parts": [{"text": "什么是丹霞地貌"}],
}],
}
response = requests.post(
f"{base_url}/v1beta/models/{model}:generateContent",
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {api_key}",
},
json=payload,
timeout=(15, 90),
)
response.raise_for_status()
result = response.json()
print(result["candidates"][0]["content"]["parts"][0]["text"])
Java(JDK 17+)
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
public class GeminiTextChatExample {
public static void main(String[] args) throws Exception {
String baseUrl = System.getenv("BASE_URL").replaceAll("/+$", "");
String apiKey = System.getenv("API_KEY");
String model = System.getenv().getOrDefault("GEMINI_MODEL", "gemini-3.7-flash");
String body = """
{
"systemInstruction": {
"parts": [{"text": "我是一个地理专家"}]
},
"contents": [{
"role": "user",
"parts": [{"text": "什么是丹霞地貌"}]
}]
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(baseUrl + "/v1beta/models/" + model + ":generateContent"))
.timeout(Duration.ofSeconds(90))
.header("Content-Type", "application/json")
.header("Authorization", "Bearer " + apiKey)
.POST(HttpRequest.BodyPublishers.ofString(body, StandardCharsets.UTF_8))
.build();
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(15))
.build();
HttpResponse<String> response = client.send(
request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));
if (response.statusCode() / 100 != 2) {
throw new IllegalStateException("New API error "
+ response.statusCode() + ": " + response.body());
}
System.out.println(response.body());
}
}
JavaScript(Node.js 18+)
const baseUrl = process.env.BASE_URL.replace(/\/+$/, "");
const apiKey = process.env.API_KEY;
const model = process.env.GEMINI_MODEL || "gemini-3.7-flash";
const response = await fetch(
`${baseUrl}/v1beta/models/${model}:generateContent`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`,
},
body: JSON.stringify({
systemInstruction: {
parts: [{ text: "我是一个地理专家" }],
},
contents: [{
role: "user",
parts: [{ text: "什么是丹霞地貌" }],
}],
}),
signal: AbortSignal.timeout(90_000),
},
);
if (!response.ok) {
throw new Error(`New API error ${response.status}: ${await response.text()}`);
}
const result = await response.json();
console.log(result.candidates?.[0]?.content?.parts?.[0]?.text);
生产配置要点
- 认证使用
Authorization: Bearer <API_KEY>。 - Base64 后的体积约为原视频的
4 / 3;例如 20 MB MP4 约为 26.7 MB,加上 JSON 包装后还会略增。请相应提高生产环境应用和反向代理的请求体大小限制。 - 为视频请求配置至少 300 秒的客户端读取超时与反向代理上游读取超时。不要复用面向普通文本聊天的短超时。
- 由于视频大小不确定,建议按示例代码来,不设置
maxOutputTokens或设置足够的maxOutputTokens。