Task Progress Query
Task Progress Query lets clients subscribe to task status changes through WebSocket, reducing polling requests and delivering progress updates faster. The current endpoint is /ws/v1/progress. After a subscription succeeds, the server immediately sends the latest task snapshot and then streams subsequent progress events.
Request
Basic Information
| Item | Value |
|---|---|
| Protocol | WebSocket |
| Path | /ws/v1/progress |
| Authentication | API Key |
Handshake Authentication
Prefer passing the API Key through the Authorization header:
Authorization: YOUR_API_KEY
When custom headers are unavailable in a browser environment, use the api_key query parameter fallback:
wss://api.ai-mcn.tv:10000/ws/v1/progress?api_key=YOUR_API_KEY
Warning: query parameters may be recorded by proxies or gateways. Use the
Authorizationheader in production whenever possible.
Subscribe to Tasks
{
"type": "subscribe",
"task_ids": ["TASK_ID"]
}
The server validates each task independently, including existence and ownership by the current API Key user. Valid tasks are added to the subscription set and receive an immediate progress snapshot.
Unsubscribe
{
"type": "unsubscribe",
"task_ids": ["TASK_ID"]
}
When the connection closes, the server automatically removes all subscriptions for that connection.
Connection Lifecycle
When every task in the current subscription set reaches completed, failed, or cancelled, the server sends the final terminal progress_update and then proactively closes the WebSocket. Treat this close as a normal completion signal; create a new WebSocket connection before subscribing to new tasks.
If the same connection still has any task in queued or processing, the connection stays open and continues streaming progress for that task.
Progress Message
{
"type": "progress_update",
"data": {
"task_id": "TASK_ID",
"status": "processing",
"progress_percent": 42,
"progress_node": "render",
"extra": {},
"timestamp": 1790000000000
}
}
| Field | Type | Description |
|---|---|---|
type | string | Always progress_update |
data.task_id | string | Task ID |
data.status | string | Task status, matching the task query API |
data.progress_percent | number | Optional progress percentage |
data.progress_node | string | Optional current processing node |
data.extra | object | Optional business-specific extension data |
data.timestamp | number | Server event time in Unix milliseconds |
Progress Nodes by Modality
Different task_type values push slightly different progress_node and extra fields. Treat the following as guidance rather than a hard contract.
Status messages (shared across all task_types)
Every task pushes at least 2 status transition messages:
status: "processing"(task begins,progress_percent: 0)- Terminal:
status: "completed"(progress_percent: 100) /failed/cancelled
Image / Text task_types
Image processing usually < 5 seconds, text < 1 second. These task types do not push intermediate progress, so clients receive only the 2 status transition messages.
Audio task_types (asr / audio_silence_remove / audio_noise_reduce / audio_speaker_split)
Every audio task pushes at least 3 progress nodes:
progress_node: "decoded",progress_percent ≈ 10(input file decoded)progress_node: "processing",progress_percent ≈ 50(core processing past midway)progress_node: "encoding",progress_percent ≈ 95(output encoded)
Video processing task_types
Including video_blackborder_remove / video_canvas_adapt / video_interpolate / video_upscale / video_purify / video_stabilizer / video_vaporwave / video_ai_subtitle.
These task types push the following 3 progress nodes:
progress_node: "decoded",progress_percent ≈ 10progress_node: "processing",progress_percent ≈ 50progress_node: "encoding",progress_percent ≈ 95
⚠️ The
extrafor these task types does NOT includecurrent_frame/total_frames. Fields inextraare optional; clients should handle them defensively (treat missing fields asNone/ absent).
Video splitting task_types (video_segment / video_ai_segment / video_motion_cut)
Splitting tasks (one input video, multiple output segments) include segment_count in extra at the encoding node so clients can sense the split scale:
{
"type": "progress_update",
"data": {
"task_id": "TASK_ID",
"status": "processing",
"progress_percent": 95,
"progress_node": "encoding",
"extra": { "segment_count": 12 },
"timestamp": 1790000000000
}
}
Time-based progress estimate node (elapsed, shared by all task_types)
For long-running tasks, the server continuously pushes a progress estimate based on elapsed time so the progress bar advances smoothly:
progress_node: "elapsed"progress_percentis an estimate based on elapsed time
This estimate shares a monotonic increase guarantee with precise progress (progress only goes up): once precise progress arrives, any estimate lower than the precise value is skipped. Clients need no special handling; treat it as a regular progress_update.
Some task types may not include this estimate node; in that case progress comes only from processing-stage nodes and status transitions.
Error Message
{
"type": "error",
"code": "TASK_NOT_FOUND",
"message": "task not found",
"task_id": "TASK_ID"
}
| Error Code | Description | Resolution |
|---|---|---|
AUTH_REQUIRED | Missing or invalid API Key | Check the Authorization header or api_key query parameter |
TASK_NOT_FOUND | Task does not exist | Confirm that task_id is correct |
TASK_FORBIDDEN | Task does not belong to the current user | Subscribe with the API Key that created the task |
INVALID_MESSAGE | Invalid JSON, missing fields, or unknown type | Check the message format |
RATE_LIMITED | Per-user connection limit exceeded | Close extra connections and retry |
Limits
Each user can open up to 5 WebSocket connections in the initial release. Connections beyond the limit receive RATE_LIMITED and are closed.
Node Example
import WebSocket from 'ws'
const ws = new WebSocket('wss://api.ai-mcn.tv:10000/ws/v1/progress', {
headers: {
Authorization: process.env.GITRUCK_API_KEY,
},
})
ws.on('open', () => {
ws.send(JSON.stringify({
type: 'subscribe',
task_ids: ['TASK_ID'],
}))
})
ws.on('message', (raw) => {
const message = JSON.parse(raw.toString())
console.log(message)
})
ws.on('close', () => {
console.log('progress stream closed; reconnect before subscribing to new tasks')
})
Python Example
import json
import os
import websocket
ws = websocket.create_connection(
"wss://api.ai-mcn.tv:10000/ws/v1/progress",
header=[f"Authorization: {os.environ['GITRUCK_API_KEY']}"],
)
ws.send(json.dumps({
"type": "subscribe",
"task_ids": ["TASK_ID"],
}))
try:
while True:
print(json.loads(ws.recv()))
except websocket.WebSocketConnectionClosedException:
print("progress stream closed; reconnect before subscribing to new tasks")
finally:
ws.close()