Polyv Help Center

Help Center

subtitle_content_callback

Updated: 2026-03-06 14:50:23

Live Subtitle Real-time Callback Integration Guide

Once configured in the management console, the system will send a callback request to the specified URL when a batch of subtitle data is generated or aggregated, pushing the subtitle content to your server.

The backend configuration is shown in the image below:

How to Fill in the callbackUrl

  • Content: A complete URL accessible from the public internet, e.g., https://api.example.com/polyv/subtitles/callback
  • Request Method: Must support POST
  • Data Format: Must support parsing multipart/form-data (form format, not JSON Body)
  • Response Requirement: It is recommended to respond within 10 seconds; any 2xx response is considered successful (response body content is not strictly validated)

Callback Request Description

Request Method

POST

Content-Type

multipart/form-data

Timeout and Retry

  • Timeout: 10 seconds
  • Retry: Automatically retries on failure, up to 3 times
  • Idempotency Recommendation: Due to possible retries, please use roomId + sessionId + index (or another business unique key) for deduplication/idempotency handling

Request Parameters

Parameter Required Type Description
roomId Yes string Channel ID (Room ID)
sessionId Yes string Current live stream/session ID
subtitles Yes string JSON string of the subtitle array (see field description below)
timestamp Yes number 13-digit request timestamp (milliseconds, Date.now())
sign Yes string Signature for authentication and anti-tampering (see signature verification below)

subtitles Field Description

subtitles is a JSON string that, when parsed, becomes an array. Each element represents a subtitle segment object. Example:

[
  {
    "text": "红不再是地产与金融的鼓舞,中环的键盘声中,一场重构全球资本格局的科技革命正在发生。",
    "language": "Chinese",
    "index": 0,
    "relativeTime": 0,
    "duration": 7610
  }
]

The subtitle segment fields are as follows (if new fields are added, please ignore them following the "backward compatibility" principle):

Field Required Type Description
text Yes string Subtitle text
language Yes string Language, currently supported (Chinese name in parentheses): Chinese (Chinese), English (English), Tagalog (Tagalog), Thai (Thai), Cantonese (Cantonese), Korean (Korean), Japanese (Japanese), Indonesian (Indonesian), Vietnamese (Vietnamese), Malay (Malay), Portuguese (Portuguese), Turkish (Turkish), Arabic (Arabic), Spanish (Spanish), Hindi (Hindi), French (French), German (German), Uyghur (Uyghur)
index Yes number Subtitle index (incremental, used for sorting/idempotency)
relativeTime Yes number Relative time (milliseconds)
duration Yes number Duration (milliseconds)

Signature (sign) Generation and Verification

To ensure the callback request has not been tampered with, the system includes sign in the request. You can verify the signature using the same algorithm:

  • Signature Key (appSecret): polyvlog
  • Signature Algorithm: MD5 (output uppercase hexadecimal)
  • Fields Involved in Signing: All request fields except sign itself (for this callback, these are roomId, sessionId, subtitles, timestamp)

Signature Algorithm Steps

  1. Take all parameters (including timestamp, excluding sign), sort them in ascending order by key (equivalent to JS's Object.keys(data).sort()).
  2. Concatenate the strings in order: key + value (if the value is an object, JSON.stringify; in this callback, subtitles itself is a string).
  3. Add the key to the beginning and end of the concatenated string: appSecret + 拼接串 + appSecret
  4. Compute the MD5 of the result from the previous step, get the hexadecimal string, and convert it to uppercase. This is the sign.

Node.js Signature Verification Example

const crypto = require('crypto');

function sortKeyAndValues(data) {
  return Object.keys(data).sort().reduce((acc, key) => {
    if (key === 'sign') return acc;
    const v = data[key];
    return acc + key + (v && typeof v === 'object' ? JSON.stringify(v) : String(v));
  }, '');
}

function createApiSign(appSecret, data) {
  const md5 = crypto.createHash('md5');
  md5.update(`${appSecret}${sortKeyAndValues(data)}${appSecret}`, 'utf8');
  return md5.digest('hex').toUpperCase();
}

// 验签
function verifySign(body) {
  const { sign } = body;
  const expect = createApiSign('polyvlog', body);
  return String(sign).toUpperCase() === expect;
}

To prevent replay attacks, it is recommended to verify that the difference between timestamp and the current server time does not exceed 30 minutes (in milliseconds).

Request Example (curl)

The following example shows the format of the system callback request (multipart/form-data form fields):

curl -X POST 'https://api.example.com/polyv/subtitles/callback' \
  -F 'roomId=123456' \
  -F 'sessionId=test_session_id' \
  -F 'subtitles=[{"text":"hello","language":"English","index":0,"relativeTime":0,"duration":1000}]' \
  -F 'timestamp=1700000000000' \
  -F 'sign=YOUR_SIGN'

Response Requirements

  • Success: Return HTTP 2xx (recommended 200), the response body can be JSON or plain text
  • Failure: Returning a non-2xx status is considered a failure and will trigger a retry

Example of a recommended successful JSON response:

{
  "code": 200,
  "status": "success",
  "message": "ok",
  "data": ""
}

Common Integration Issues

  • Cannot receive parameters/parameters are empty: Please confirm that your backend supports parsing multipart/form-data (Express's default json/urlencoded middleware cannot parse this format).
  • Signature verification fails:
    • Confirm that timestamp is in milliseconds;
    • Confirm that the concatenation order is ascending by key;
    • Confirm that the MD5 output needs to be converted to uppercase;
    • Confirm that the fields involved in signing do not include sign itself, and that subtitles is treated as a "raw string" when participating in signing.
联系客服,在线咨询