监听渲染
curl --request GET \
--url https://apis.viggle.ai/v1/renders/{render_id}/events \
--header 'Authorization: Bearer <token>'import requests
url = "https://apis.viggle.ai/v1/renders/{render_id}/events"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://apis.viggle.ai/v1/renders/{render_id}/events', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://apis.viggle.ai/v1/renders/{render_id}/events",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://apis.viggle.ai/v1/renders/{render_id}/events"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://apis.viggle.ai/v1/renders/{render_id}/events")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://apis.viggle.ai/v1/renders/{render_id}/events")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body"<string>"{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}监听渲染
通过服务器发送事件监听渲染状态。
GET
/
v1
/
renders
/
{render_id}
/
events
监听渲染
curl --request GET \
--url https://apis.viggle.ai/v1/renders/{render_id}/events \
--header 'Authorization: Bearer <token>'import requests
url = "https://apis.viggle.ai/v1/renders/{render_id}/events"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://apis.viggle.ai/v1/renders/{render_id}/events', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://apis.viggle.ai/v1/renders/{render_id}/events",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://apis.viggle.ai/v1/renders/{render_id}/events"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://apis.viggle.ai/v1/renders/{render_id}/events")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://apis.viggle.ai/v1/renders/{render_id}/events")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body"<string>"{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "<string>",
"retryable": true,
"request_id": "<string>",
"details": {},
"remediation": {
"action": "<string>",
"retry_after_ms": 1
}
}
}服务先发送状态快照,再每 10–15 秒发送心跳,进入
渲染事件的
ready、failed 或 cancelled 后关闭流。断开后可使用 Last-Event-ID 恢复快照后的事件。若事件历史已过期,先调用获取视频(GET /v1/videos/{render_id})读取当前状态,再重新连接。
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
render_id | string | 是 | 创建渲染或视频列表返回的完整 ID,通常以 render_ 开头。此连接仅报告该任务的事件。 |
Last-Event-ID | string | 否 | 上一次已完整处理的 SSE 事件 ID,请放入请求头。重连时从该事件之后继续发送保留的历史;新建连接可省略。 |
响应
返回200 OK 和 text/event-stream 响应体。业务事件的 data 为 JSON,心跳可能不带 data。
| 事件 | data 内容 | 说明 |
|---|---|---|
snapshot | 渲染事件数据 | 连接后立即发送。 |
queued | 渲染事件数据 | 已受理,尚未处理。 |
processing | 渲染事件数据 | 开始处理。 |
progress | 渲染事件数据 | progress 或 stage 发生变化。 |
ready | 渲染事件数据 | 终态,输出 URL 就绪,随后关闭流。 |
failed | 渲染事件数据 | 终态,error 有值,随后关闭流。 |
cancelled | 渲染事件数据 | 终态,随后关闭流。 |
heartbeat | 无 | 仅保持连接,不含业务数据。 |
data 字段如下:
| 字段 | 类型 | 始终返回 | 说明 |
|---|---|---|---|
event_id | string | 是 | 用作 Last-Event-ID,从该事件之后恢复。 |
sequence | integer | 是 | 在单个渲染任务内单调递增。 |
id | string | 是 | 渲染任务 ID。 |
status | string | 是 | queued、processing、ready、failed 或 cancelled。 |
stage | string 或 null | 是 | 可用时提供大致阶段。 |
progress | integer 或 null | 是 | 可用时为 0–100 的进度。 |
video_url / alpha_url | string 或 null | 是 | ready 时返回相应输出链接。 |
occurred_at | string | 是 | ISO 8601 事件时间。 |
completed_at | string 或 null | 是 | ISO 8601 完成时间。 |
error | object 或 null | 是 | failed 时有值。 |
示例
curl -N "https://apis.viggle.ai/v1/renders/render_789ghi/events" \
-H "Authorization: Bearer $VIGGLE_API_KEY" \
-H "Accept: text/event-stream"
const response = await fetch("https://apis.viggle.ai/v1/renders/render_789ghi/events", {
headers: { Authorization: `Bearer ${process.env.VIGGLE_API_KEY}`, Accept: "text/event-stream" },
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = "";
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
// Split on blank lines to get whole SSE frames, then parse `event:`/`data:`.
}
import os, requests
with requests.get(
"https://apis.viggle.ai/v1/renders/render_789ghi/events",
headers={"Authorization": f"Bearer {os.environ['VIGGLE_API_KEY']}", "Accept": "text/event-stream"},
stream=True,
) as response:
response.raise_for_status()
for line in response.iter_lines(decode_unicode=True):
if line:
print(line)
能够保持长连接时,可使用本接口减少获取视频的轮询延迟与请求量,状态判断方式不变。
下一步
收到ready 事件后,使用下载渲染结果,或直接读取事件中的 video_url/alpha_url。Authorizations
服务端 SDK 使用项目 API 密钥,Remote MCP 使用 OAuth 访问令牌。不要在浏览器代码中暴露项目密钥。
Headers
客户端最后完整处理的 SSE 事件 ID。重连时传入,以便在历史仍保留时从该事件之后继续。
Minimum string length:
1可选的调用者自定义关联 ID,最长 128 字符。服务会在响应头返回实际使用的值,便于追踪和支持排查。
Required string length:
1 - 128可选来源标签,最长 128 字符,用于识别 SDK、集成、产品入口或内部工作流。
Required string length:
1 - 128Path Parameters
创建或列出渲染时返回的公开 ID,通常以 render_ 开头,必须属于当前调用者。
Minimum string length:
1Response
请求成功。
UTF-8 编码的服务器发送事件流。

