Upload files and add tracks
The local SDK 0.1.30 offers two workflows: primary video with a browser capability URL, and attached tracks with server helpers for Node.js 22 or later. Keep session IDs and the original file to recover from interruptions.
Primary video from the browser
Section titled “Primary video from the browser”Your backend creates an upload and saves its ID:
const upload = await orilla.uploads.create({ cors_origin: "https://app.example", new_asset_settings: { playback_policies: ["signed"], meta: { title: "My video" }, },});// Give upload.url to the browser; save upload.id in your backend.In the browser, use only that temporary URL and the selected file:
import { uploadFile } from "@orilla-video/sdk/upload";
await uploadFile(uploadURL, file, { signal: abortController.signal, onProgress: (bytes, total) => console.log(bytes, total),});uploadURL comes from the backend, file from a file input, and abortController is an AbortController in your interface. The helper queries the offset and sends 8 MiB chunks by default. After failure, it can be called again with the same URL and original file; it does not verify whether an already uploaded prefix matches a different file chosen by mistake.
Do not give administrative credentials to the browser. Completing the transfer does not mean the asset is ready: poll uploads.retrieve(upload.id) until you receive asset_id, then check the asset status, or use webhooks.
Subtitles and chapters from the dashboard
Section titled “Subtitles and chapters from the dashboard”On a ready video or audio asset, open Subtitles & chapters → Add track → File. Select a UTF-8 SRT/WebVTT file from 1 byte to 5 MiB, type, language, and name. Chapters use WebVTT; CC is supported only for subtitles. The URL option remains available.
An invalid track fails independently. Close stops local work and preserves an already accepted session; Pending upload → Resume upload requests the same file and verifies its name, size, and SHA-256. Retry confirmation recovers completion without uploading the file again. Canceling removes only the track. Readers can view tracks without managing uploads.
Text with the server SDK
Section titled “Text with the server SDK”With orilla configured in your backend and assetId from ready content:
import { randomUUID } from "node:crypto";import { readFile, writeFile } from "node:fs/promises";
const original = await readFile("en.vtt");const idempotencyKey = randomUUID();await writeFile("text-request-id.txt", idempotencyKey, { mode: 0o600 });
const result = await orilla.trackUploads.uploadText( assetId, original, { filename: "en.vtt", contentType: "text/vtt", text_type: "subtitles", language_code: "en", name: "English", }, { idempotencyKey, onSession: async (session) => { await writeFile("text-upload-id.txt", session.uploadId, { mode: 0o600 }); }, },);console.log(result.trackId, result.status);In production, save the UUID and session in durable storage. Reuse the UUID when recovering a reservation whose response was lost. With the persisted ID and the same original:
const uploadId = (await readFile("text-upload-id.txt", "utf8")).trim();await orilla.trackUploads.resumeText(uploadId, original, { filename: "en.vtt",});Attached audio with the SDK
Section titled “Attached audio with the SDK”For large files, use a file-backed Blob in your backend:
import { openAsBlob } from "node:fs";import { randomUUID } from "node:crypto";import { writeFile } from "node:fs/promises";
const original = await openAsBlob("en.wav");const idempotencyKey = randomUUID();await writeFile("audio-request-id.txt", idempotencyKey, { mode: 0o600 });const result = await orilla.trackUploads.uploadAudio( assetId, original, { filename: "en.wav", contentType: "audio/wav", language_code: "en", name: "English", }, { idempotencyKey, onSession: async (session) => { await writeFile("audio-upload-id.txt", session.uploadId, { mode: 0o600 }); }, },);console.log(result.trackId, result.status);resumeAudio(uploadId, original, { filename: 'en.wav' }) resumes with the persisted ID. The helper accepts Blob/Uint8Array from 1 byte to 5 GiB, calculates the full SHA-256, and transfers parts sequentially. The dashboard uses a different audio fingerprint: resuming across dashboard and SDK is not promised. Each asset allows up to ten additional audio tracks; primary audio is required and group names must be unique.
Status and errors
Section titled “Status and errors”Track helpers return status: 'completed' when the upload is accepted. Query assets.retrieve(assetId).tracks to follow ready or errored. The primary content’s status is not reset.
onSession and onProgress can be asynchronous; the SDK waits for them. Progress counts accepted bytes, not worker progress, and can reach the total before confirmation fails. signal aborts local work while preserving the session. Canceling requires trackUploads.cancel(uploadId).
There are no automatic background retries. timeoutMs limits each request; fetch in helper options replaces only storage transport. Do not add Basic Authorization globally to a wrapper: S3 receives only the signed capability, without cookies or administrative credentials. Redirects are rejected. The low-level APIs createText, createAudio, retrieve, prepare, sign, complete, and cancel remain available.