OLOS

Open Live Object Streaming protocol primitives. A generic live object
streaming protocol: a low-latency append-only stream log over plain object
storage (S3, R2, GCS), with CMAF/LL-HLS as its first profile.
Install
npm install @arsenstorm/olos
Imports
import { OLOS_PROTOCOL_NAME, OLOS_WIRE_VERSION } from "@arsenstorm/olos";
import type { Session } from "@arsenstorm/olos/types";
@arsenstorm/olos/runtime | Session routes, publisher loops, HLS serving. |
@arsenstorm/olos/s3 | S3 upload grants, observation, events, recovery, retention. Needs @aws-sdk/client-s3 and @aws-sdk/s3-request-presigner installed by the consumer (optional peer dependencies). |
@arsenstorm/olos/media | CMAF/LL-HLS profile: media session/track/object profiles, validators, schemas, publisher pacing. |
@arsenstorm/olos/hls | HLS rendering and blocking-reload helpers. |
@arsenstorm/olos/protocol | Coordinator stores and adapter conformance. |
@arsenstorm/olos/state | Lower-level state transitions and policies. |
@arsenstorm/olos/schema | JSON Schemas for wire objects. |
@arsenstorm/olos/validation | Runtime payload validators. |
@arsenstorm/olos/types | Public protocol data types. |
@arsenstorm/olos/config | Protocol constants and policy defaults. |
@arsenstorm/olos/conformance | Assertion metadata and store checks. |
Quick start
A complete OLOS endpoint with S3-backed live media (the CMAF/LL-HLS profile):
import {
createMemorySerializedCoordinatorStoreBackend,
createSerializedCoordinatorStore,
} from "@arsenstorm/olos/protocol";
import { createStoredS3CoordinatorRuntimeHandler } from "@arsenstorm/olos/s3";
import { S3Client } from "@aws-sdk/client-s3";
const store = createSerializedCoordinatorStore(
createMemorySerializedCoordinatorStoreBackend()
);
const s3 = new S3Client({ region: "us-east-1" });
const handleOlos = createStoredS3CoordinatorRuntimeHandler({
allowedDeliveryOrigins: ["https://media.example.com"],
bucket: "olos-media",
client: s3,
expiresInSeconds: 5,
providerId: "s3_primary",
store,
});
export default { fetch: (req: Request) => handleOlos(req) };
Publishers create a session, then loop: get a presigned slot, PUT media bytes
to S3, post a commit. Viewers GET HLS manifests. The handler covers it.
A session declares the profile it runs under and a profile per track. Core
treats profile objects as opaque; @arsenstorm/olos/media defines and
validates the CMAF/LL-HLS ones:
import { CMAF_LLHLS_PROFILE_ID } from "@arsenstorm/olos/media";
await fetch("https://olos.example.com/sessions", {
body: JSON.stringify({
deliveryBaseUrl: "https://media.example.com",
session: {
createdAt: new Date().toISOString(),
epoch: 1,
olos: "1.0",
profile: { id: CMAF_LLHLS_PROFILE_ID, partTarget: 0.5, segmentTarget: 2 },
sessionId: "session_1",
state: "live",
tracks: [
{
profile: { bitrate: 5_000_000, codec: "avc1.640028", kind: "video" },
trackId: "v1080",
},
],
},
}),
headers: { "content-type": "application/json" },
method: "POST",
});
Slot requests and commits carry the same kind of opaque profile object
(for LL-HLS: { duration, independent, programDateTime }).
Working setups:
Routes
The handler mounts:
POST | /sessions | Create a session. |
POST | /sessions/:id/s3/slots | Issue a presigned upload slot. |
POST | /sessions/:id/s3/commits | Observe and commit an upload. |
POST | /sessions/:id/s3/events | Accept S3 object-created events. |
POST | /sessions/:id/s3/reconcile-plan | List in-flight slots for recovery. |
POST | /sessions/:id/s3/reconcile | Recover slots after missed events. |
POST | /sessions/:id/s3/retention | Prune retired state and delete retired media. |
POST | /sessions/:id/upload-slots/:slotId/complete | Publisher completion hint (alternative to waiting for events). |
POST | /sessions/:id/transition | Advance session state. |
POST | /sessions/:id/heartbeat | Publisher liveness ping. |
GET | /sessions/:id/health | Live / starting / stale summary. |
GET | /v1/live/:id/master.m3u8 | Master playlist (variants, audio groups). |
GET | /v1/live/:id/.../media.m3u8 | LL-HLS playlist with _HLS_msn blocking reload. |
The /sessions and /v1/live prefixes are the defaults. The handler's
sessionPath and livePath options configure them. Error responses always
carry error.code from the registered OLOS_ERROR_CODES set, next to
error.message.
Layers
OLOS is layered. Core defines the commit semantics. Above it are a profile
(the CMAF/LL-HLS profile ships in @arsenstorm/olos/media and
@arsenstorm/olos/hls), a storage binding (@arsenstorm/olos/s3), a
delivery mapping, the direct-public deployment profile, and runtime
guidance. Spec Section
2
defines the layers and the split between what OLOS owns and what your app
owns.
Further reading
Release check
bun --filter '@arsenstorm/olos' publish:check