文核心价值:虽然不能直接调用 Sora,但我们可以学习调用 AI 视频模型的通用流程,掌握核心技能。本文将带你走完“从理想到现实”的全过程。
随着OpenAI AI 视频生成技术(如 Sora)的兴起,许多开发者希望通过 API 将其集成到自己的应用中。然而,直接与底层 API 交互时,会遇到各种挑战,如参数格式、身份验证和异步任务处理。
本教程将带你走过一个完整的流程,展示如何使用 Python 和 requests
库,从零开始提交一个视频生成任务,直到最后成功下载视频文件。
准备工作:环境和必备知识
在开始之前,你将需要:
- Python 环境:确保你已安装 Python。
requests
库:这是 Python 中最流行的 HTTP 库。如果尚未安装,请运行:pip install requests
- API 凭证:你必须拥有一个 API 服务商提供的:
- API 主机地址 (Host) :例如
sg.uiuiapi.com
。 - API Key (Token) :一串用于身份验证的密钥,通常以
Bearer
开头。
- API 主机地址 (Host) :例如
请注意 :不同的 API 服务商可能有完全不同的 API 路径(Endpoint)和参数要求。本教程以我们调试通过的接口为例,你应根据你的服务商文档进行调整。
步骤一:提交“文生视频”任务
我们的第一个目标是向 API 发送一个提示词,告诉它“我想要一个xx的视频”。这类请求通常使用 multipart/form-data
格式,因为它模仿了网页表单的提交。
关键代码
我们将把所有可变参数(如提示词、时长)提取到代码顶部,方便修改。
import requests
import json
# --- 1. 在这里配置你的凭证 ---
API_KEY = "YOUR_ACTUAL_API_KEY_HERE"
API_HOST = "sg.uiuiapi.com" # 替换为你的 API 主机地址
# --- 2. 在这里配置你的视频参数 ---
my_prompt = "一只花猫在舞台上弹钢琴"
video_seconds = "15" # 视频时长
# 重要:我们发现 '1080x1920' 可能会导致 'invalid_size' 错误
# 使用空字符串 "" 让 API 自动选择一个它支持的默认尺寸 (例如 720x1280)
video_size = ""
# --- 3. 配置 API 终结点 (Endpoint) ---
# (这需要根据你的 API 文档调整)
API_URL = f"https://{API_HOST}/v1/videos"
# 准备请求头
headers = {
'Authorization': f'Bearer {API_KEY}'
# 注意:使用 requests 的 'files' 参数时,不要手动设置 Content-Type
}
# 准备要发送的表单数据
# (None, 'value') 格式告诉 requests 这是一个数据字段,而不是文件
form_data = {
'model': (None, 'sora-2'),
'prompt': (None, my_prompt),
'seconds': (None, video_seconds),
'input_reference': (None, ''), # 留空
'size': (None, video_size) # 使用我们上面定义的安全值
}
print(f"正在发送 文生视频 请求到: {API_URL}")
print(f"使用提示词: {my_prompt}")
try:
# 发送 POST 请求
# 重点:当发送 multipart/form-data 时,我们使用 'files' 参数
response = requests.post(API_URL, headers=headers, files=form_data)
# 检查 HTTP 状态码
response.raise_for_status()
# 打印成功的响应内容
print("\n--- 任务提交成功! ---")
response_data = response.json()
print(json.dumps(response_data, indent=2, ensure_ascii=False))
# 提取任务 ID,为下一步做准备
task_id = response_data.get("id")
if task_id:
print(f"\n--- 任务ID: {task_id} ---")
print("请复制这个 ID,用于下一步的状态查询。")
except requests.exceptions.HTTPError as http_err:
print(f"\nHTTP 错误: {http_err}")
print(f"响应内容: {http_err.response.text}")
except requests.exceptions.RequestException as err:
print(f"\n请求发生错误: {err}")
预期结果
如果一切顺利,你将收到一个 JSON 响应,status
为 submitted
(已提交),最重要的是,你会得到一个 id
(任务 ID)。
{
"id": "video_c5460ca6-4f96-4309-ba95-8208354fdec3",
"status": "submitted",
"progress": 0,
"seconds": "15",
"size": "720x1280"
}
保存这个 id
,它是你领取视频的唯一凭证。
步骤二:轮询任务状态并自动下载视频
视频生成不是即时的,可能需要几分钟。你不能一直“挂着”等响应,而是需要轮询(Polling)——每隔一段时间就去问一次:“我的视频做好了吗?”
我们将编写一个脚本,自动完成“询问”和“下载”两个动作。
关键代码
这个脚本会自动查询任务状态,一旦 status
变为 completed
,它会解析响应中的下载路径,并自动将视频保存到本地。
import requests
import json
import time
import os
# --- 1. 配置你的凭证 ---
API_KEY = "YOUR_ACTUAL_API_KEY_HERE"
API_HOST = "sg.uiuiapi.com" # 必须和步骤一的主机地址一致
# --- 2. 粘贴你从步骤一获取的任务ID ---
TASK_ID = "video_c5460ca6-4f96-4309-ba95-8208354fdec3"
# --- 3. 配置轮询和保存设置 ---
POLL_INTERVAL = 10 # 每 10 秒查询一次
SAVE_FOLDER = "video_downloads" # 视频保存的文件夹名
# --- 4. 配置 API 终结点 ---
# (通常是 步骤一的URL + 任务ID)
API_URL = f"https://{API_HOST}/v1/videos/{TASK_ID}"
# 准备请求头
headers = {
'Authorization': f'Bearer {API_KEY}'
}
def download_video(video_url_path, save_path):
"""根据 API 返回的相对路径,下载视频"""
# 1. 构造完整的下载 URL
# (API 返回的 "url" 可能是相对路径,如 /v1/videos/...)
full_download_url = f"https://{API_HOST}{video_url_path}"
print(f"\n正在下载视频从: {full_download_url}")
try:
# 2. 下载也需要身份验证
with requests.get(full_download_url, headers=headers, stream=True) as r:
r.raise_for_status()
# 3. 确保保存文件夹存在
os.makedirs(os.path.dirname(save_path), exist_ok=True)
# 4. 分块写入文件,防止大文件撑爆内存
with open(save_path, 'wb') as f:
for chunk in r.iter_content(chunk_size=8192):
f.write(chunk)
print(f"--- 视频已成功保存到: {save_path} ---")
except requests.exceptions.RequestException as e:
print(f"!!! 下载视频失败: {e} !!!")
# --- 轮询主循环 ---
print(f"开始轮询任务: {TASK_ID}")
try:
while True:
response = requests.get(API_URL, headers=headers)
if response.status_code >= 500:
print(f"服务器错误 {response.status_code},{POLL_INTERVAL}秒后重试...")
time.sleep(POLL_INTERVAL)
continue
response.raise_for_status()
data = response.json()
status = data.get("status")
progress = data.get("progress", 0)
print(f"[{time.strftime('%H:%M:%S')}] 状态: {status} | 进度: {progress}%")
# 检查是否成功
if status == "completed" or status == "succeeded":
print("\n--- 任务成功! ---")
print(json.dumps(data, indent=2, ensure_ascii=False))
video_relative_url = data.get("url")
if video_relative_url:
file_name = f"{TASK_ID}.mp4"
save_file_path = os.path.join(SAVE_FOLDER, file_name)
download_video(video_relative_url, save_file_path)
else:
print("!!! 任务已完成,但响应中未找到 'url' 字段。")
break # 退出循环
# 检查是否失败
elif status == "failed":
print("\n--- 任务失败! ---")
print(json.dumps(data, indent=2, ensure_ascii=False))
break # 退出循环
# 任务仍在进行中
time.sleep(POLL_INTERVAL)
except requests.exceptions.HTTPError as http_err:
print(f"\nHTTP 错误: {http_err}")
print(f"响应内容: {http_err.response.text}")
except KeyboardInterrupt:
print("\n用户停止了轮询。")
预期结果
脚本会持续打印状态,直到任务完成或失败。如果成功,它会显示 JSON 结果,然后自动下载视频到 video_downloads
文件夹。
[13:20:17] 状态: processing | 进度: 50%
[13:20:27] 状态: completed | 进度: 100%
--- 任务成功! ---
{
"status": "completed",
"progress": 100,
"url": "/v1/videos/video_c5460ca6.../content"
}
正在下载视频从: https://sg.uiuiapi.com/v1/videos/video_c5460ca6.../content
--- 视频已成功保存到: video_downloads\video_c5460ca6-4f96-4309-ba95-8208354fdec3.mp4 ---
(进阶)步骤三:提交“图生视频”任务
有些 API 还支持“图生视频”。这通常使用不同的 API 路径(如 /v2/videos/generations
)和不同的数据格式(application/json
)。
关键区别:你不能直接上传图片文件。API 期望你提供一个公开可访问的图片 URL。
关键代码
import requests
import json
# --- 1. 配置你的凭证 ---
API_KEY = "YOUR_ACTUAL_API_KEY_HERE"
API_HOST = "sg.uiuiapi.com" # 替换为你的 API 主机地址
# --- 2. 配置你的参数 ---
my_prompt = "一只猫在海滩上,太阳正在下山"
my_model = "sora-2"
# 重点: 必须是公开可访问的图片 URL
my_image_urls = [
"https://example.com/my-public-image.jpg"
]
# --- 3. 配置 API 终结点 ---
# (注意:这个路径可能和文生视频不同!)
API_URL = f"https://{API_HOST}/v2/videos/generations"
headers = {
'Authorization': f'Bearer {API_KEY}',
'Content-Type': 'application/json' # 明确指定 JSON
}
# 准备 JSON payload
payload = {
"prompt": my_prompt,
"model": my_model,
"images": my_image_urls,
"aspect_ratio": "16:9",
"hd": True,
"duration": "5"
}
print(f"正在发送 图生视频 请求到: {API_URL}")
try:
# 发送 POST 请求,使用 'json' 参数
response = requests.post(API_URL, headers=headers, json=payload)
response.raise_for_status()
print("\n--- 任务提交成功! ---")
response_data = response.json()
print(json.dumps(response_data, indent=2, ensure_ascii=False))
task_id = response_data.get("id")
if task_id:
print(f"\n--- 任务ID: {task_id} ---")
print("请复制这个 ID,并使用 步骤二 的轮询脚本来查询状态。")
except requests.exceptions.HTTPError as http_err:
print(f"\nHTTP 错误: {http_err}")
print(f"响应内容: {http_err.response.text}")
提交成功后,你会得到一个新的 任务 ID。然后,你只需重复步骤二,将这个新的 ID 填入轮询脚本即可。
常见错误与“陷阱”
在调试过程中,我们遇到了几个典型的错误,这里是它们的成因和解决方案:
-
502 Server Error: Bad Gateway
- 现象:
{"message":"Service temporarily unavailable"}
- 原因:这是服务器端的临时故障。你的代码没有错。
- 解决:等待几分钟,然后重试。
- 现象:
-
400 Client Error: Bad Request
(错误 1: 平台无效)- 现象:
{"code":"invalid_api_platform"}
- 原因:这通常是凭证和主机不匹配。例如,你用了 A 平台的 Key 却请求了 B 平台的 Host 地址。
- 解决:仔细检查你的
API_KEY
和API_HOST
是否是配套的。
- 现象:
-
400 Client Error: Bad Request
(错误 2: 尺寸无效)- 现象:
{"code":"invalid_size","message":"sora-2 size is invalid"}
- 原因:你提交的
size
(如"1080x1920"
)不被该 API 服务商支持。 - 解决:在步骤一中,将
video_size
设置为""
(空字符串),让 API 自动选择一个安全的默认值。
- 现象:
-
400 Client Error: Bad Request
(错误 3: 接口混淆)- 现象:向
/v1/chat/completions
发送sora-2
模型请求。 - 原因:你混淆了聊天接口和视频接口。
/chat/completions
是用来生成文本的(如 GPT-4),而/v1/videos
才是用来生成视频的(如 Sora)。 - 解决:确保你使用了正确的 API 路径(Endpoint)来执行你想要的动作。
- 现象:向
** 开发者指南:国内开发者openai api key获取方案**
为帮助开发者快速上手,OpenAI设计了简洁明了的API接入流程:
方式A:官方直连模式
- 注册/登录账户: 访问OpenAI平台官网。
- 设置支付信息: 在“Billing”(计费)部分绑定有效的支付方式,激活API功能。
- 生成API密钥: 在“API keys”页面创建新密钥。务必注意:密钥仅在创建时完整显示一次,请立即复制并保存在安全之处。
- 安全存储密钥: 最佳实践是将其存储为环境变量(如
OPENAI_API_KEY
),切勿硬编码在代码中。
方式 B:国内加速模式
借助国内技术团队(如 uiuiapi.com
)提供的中转服务,可显著提升连接稳定性与响应速度,适合通过AI聚合服务商获取 OpenAI或其他模型 API Key 的场景。使用前请确认服务商支持目标模型并评估其资质与隐私合规性。
界智通jieagi总结
通过本教程,你已经掌握了使用 Python requests
库与 AI 视频 API 交互的完整闭环:从提交任务、处理异步轮询、解析 JSON 响应,到最终下载文件,并学会了如何排查常见的 HTTP 错误。
版权信息: 本文由界智通(jieagi)团队编写,图片、文本保留所有权利。未经授权,不得转载或用于商业用途。
共同学习,写下你的评论
评论加载中...
作者其他优质文章