ZiB Network
Transcription
ZiB Transcription generates subtitle tracks for your video or audio files. The SRT/WebVTT output is encrypted, stored redundantly on the network, and accessible via the same CDN URL pattern as any other file. Three quality tiers are available — pick based on the speed/accuracy tradeoff you need.
When requested alongside video encoding, subtitle tracks are automatically embedded in the HLS manifest as #EXT-X-MEDIA entries. Any HLS player (hls.js, Video.js, native Safari, AVPlayer) will surface them automatically in the subtitle menu.
Tiers
fastFast — Whisper SmallBest for short clips or when speed matters most. Good English accuracy; lighter on multilingual nuance.
balancedBalanced — Whisper Large-v3 TurboDefaultThe default. Large-v3-turbo runs roughly 8× faster than full large-v3 at near-identical accuracy — the best choice for most content, including long-form and feature-length.
accurateAccurate — Whisper Large-v3Full Whisper large-v3. Maximum accuracy across languages and on difficult audio — use when transcription quality is paramount and runtime is not a concern.
Legacy tier names still work and now map to the faster models automatically — no change needed in existing integrations: recommended → balanced (turbo), and fastest → fast. Each tier is a separate model the node operator enables/downloads, so a tier is only available if a participating node has that model.
Standalone Job
Submit a standalone job to transcribe a file that has already been uploaded. The objectId is the file_id UUID returned by any upload method, and the file must belong to your account.
submitTranscription, submitVisionAI and getComputeStatus call /v1/api/compute/…, which only accepts a signed-in dashboard session, so they return 401 with an access key. The access-key routes are POST /v1/api/compute-api/{file_id} and GET /v1/api/compute-api/job/{job_id}.// Submit a transcription job (server-side)
const ZIB_AUTH = `Bearer ${process.env.ZIB_ACCESS_KEY}:${process.env.ZIB_SECRET_KEY}`;
const job = await fetch(`https://api.mosnet.io/v1/api/compute-api/${fileId}`, {
method: 'POST',
headers: { Authorization: ZIB_AUTH, 'Content-Type': 'application/json' },
body: JSON.stringify({ transcription: 'balanced' }),
}).then((r) => r.json());
// => { job_id: 'uuid', status: 'queued', ... }
console.log('Job ID:', job.job_id);Request body (raw HTTP)
POST /v1/api/compute-api/{file_id}
Authorization: Bearer ACCESS_KEY:SECRET_KEY
Content-Type: application/json
{
"transcription": "balanced",
"webhook_url": "https://your-app.example.com/hooks/zib",
"webhook_secret": "whsec_..."
}
// transcription: "fast" | "balanced" | "accurate" (aliases "fastest", "recommended");
// any other value runs as "balanced". webhook_url / webhook_secret are optional:
// transcription.complete goes ONLY to this URL (no account default), signed only
// if webhook_secret is sent.Response
{
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "queued",
"progress": 0,
"transcription_model": "balanced",
"vision_model": null,
"srt_file_id": null,
"sidecar_file_id": null,
"error_message": null
}With Encoding
Pass transcription as an option to startEncoding(). Transcription runs in parallel with video encoding. The HLS manifest will include subtitle tracks when the job completes.
// SERVER-SIDE: `storage` is new ZiBStorage({ accessKey, secretKey }) on your server.
const { encoding_id } = await storage.startEncoding(fileId, {
transcription: 'balanced',
});
// Poll encoding status
let status;
do {
await new Promise(r => setTimeout(r, 3000));
status = await storage.getEncodingStatus(encoding_id);
} while (status.status !== 'complete' && status.status !== 'failed');
// HLS URL — subtitle tracks embedded automatically
console.log('Stream:', status.hls_manifest_url);
// => https://cdn.zibnetwork.com/stream/<id>/master.m3u8 (either CDN host plays it)
// Subtitle track visible in any HLS playerPolling & Status
const getStatus = (jobId) => fetch(`https://api.mosnet.io/v1/api/compute-api/job/${jobId}`, {
headers: { Authorization: ZIB_AUTH },
}).then((r) => r.json());
const status = await getStatus(jobId);
// => {
// job_id: 'uuid',
// status: 'queued' | 'processing' | 'complete' | 'failed',
// srt_file_id: 'uuid' | null,
// sidecar_file_id: null,
// error_message: null | 'string'
// }queuedJob is waiting to be picked up by a compute node.processingA compute node is currently running inference.completeDone. srt_file_id is populated with the output file UUID.failedJob failed. error_message contains the reason.Recommended polling interval
Poll every 3–5 seconds. Typical transcription times: 10–30s for short clips, 1–3 minutes for a 30-minute video on the recommended tier.
SRT Output
The transcription output is a standard SRT file stored encrypted on the ZiB network. Fetch it via the CDN URL using the srt_file_id from the job status.
const status = await getStatus(jobId); // GET /v1/api/compute-api/job/{job_id}
if (status.status === 'complete' && status.srt_file_id) {
// Resolve a signed URL server-side: GET /v1/api/object-url?file_id=<srt_file_id>
const { url: srtUrl } = await fetch(
`https://api.mosnet.io/v1/api/object-url?file_id=${status.srt_file_id}`,
{ headers: { Authorization: `Bearer ${process.env.ZIB_ACCESS_KEY}:${process.env.ZIB_SECRET_KEY}` } },
).then((r) => r.json());
// => https://cdn.mosnet.io/objects/<srt_file_id>?exp=...&tok=...
// Fetch the SRT content
const srt = await fetch(srtUrl).then(r => r.text());
console.log(srt);
}Example SRT
1
00:00:01,240 --> 00:00:04,800
Welcome to ZiB Network.
2
00:00:05,100 --> 00:00:09,200
Files are encrypted client-side before
any bytes leave the browser.
3
00:00:10,000 --> 00:00:13,500
Node operators never see plaintext content.HLS Subtitles
When transcription is requested with encoding, ZiB embeds the subtitle track directly in the HLS master manifest using #EXT-X-MEDIA. No extra work is needed — just load the HLS URL in any compatible player.
hls.js example
import Hls from 'hls.js';
const video = document.querySelector('video');
const hls = new Hls();
hls.loadSource(status.hls_manifest_url);
hls.attachMedia(video);
// Subtitle tracks are automatically available in hls.subtitleTrackController
// The user can select them via the player's subtitle menuVideo.js example
import videojs from 'video.js';
const player = videojs('my-video', {
sources: [{ src: status.hls_manifest_url, type: 'application/x-mpegURL' }],
});
// Subtitle tracks appear in the CC button automatically