Skip to content

Core Concepts

Content is the unified abstraction over live and recorded content (broadcasts, archives, scheduled broadcasts, and clips). It is modeled as a discriminated union with a type field.

const content = await client.resolve(url);
if (content.type === "broadcast") {
console.log(content.viewerCount); // number
console.log(content.startedAt); // Date
}
if (content.type === "archive") {
console.log(content.duration); // seconds
console.log(content.viewCount); // number
console.log(content.publishedAt); // Date
}

Use the Content companion object for type narrowing:

import { Content } from "@unified-live/core";
if (Content.isBroadcast(content)) {
// content is narrowed to Broadcast
console.log(content.viewerCount);
}
if (Content.isArchive(content)) {
// content is narrowed to Archive
console.log(content.duration);
}

All content types (Broadcast, Archive, ScheduledBroadcast, Clip) share these fields:

FieldTypeDescription
idstringPlatform-specific content ID
platformstring"youtube", "twitch", or "twitcasting"
titlestringContent title
descriptionstringContent description
tagsstring[]Content tags
urlstringURL to the content
thumbnailThumbnailThumbnail image with url, width, height
channelChannelRefChannel reference with id, name, url
sessionIdstring?Links a live broadcast to its archive (see below)
languageCodestring?Language code of the content
rawunknownOriginal API response — cast to the platform’s native type for advanced use

A Channel represents a streaming channel or user account:

const channel = await client.getChannel("youtube", "UC_x5XG1OV2P6uZZ5FSM9Ttw");
console.log(channel.id); // "UC_x5XG1OV2P6uZZ5FSM9Ttw"
console.log(channel.platform); // "youtube"
console.log(channel.name); // Channel name
console.log(channel.url); // Channel URL
console.log(channel.thumbnail); // Thumbnail (optional)

The client can auto-detect the platform from a URL:

// YouTube
const content = await client.resolve("https://www.youtube.com/watch?v=abc123");
// Twitch
const content = await client.resolve("https://www.twitch.tv/videos/123456");
// TwitCasting
const content = await client.resolve("https://twitcasting.tv/user/movie/123");
// Check without fetching
const resolved = client.match("https://www.youtube.com/watch?v=abc123");
// { platform: "youtube", type: "content", id: "abc123" }
const resolved = client.match("https://www.twitch.tv/username");
// { platform: "twitch", type: "channel", id: "username" }

YouTube:

  • youtube.com/watch?v=VIDEO_ID
  • youtu.be/VIDEO_ID
  • youtube.com/channel/CHANNEL_ID
  • youtube.com/@handle
  • youtube.com/live/VIDEO_ID

Twitch:

  • twitch.tv/videos/VIDEO_ID
  • twitch.tv/USERNAME

TwitCasting:

  • twitcasting.tv/USER_ID/movie/MOVIE_ID
  • twitcasting.tv/USER_ID

sessionId links a live broadcast to its archive. On some platforms (YouTube, TwitCasting), the live and archive share the same ID. On Twitch, they have different IDs, but sessionId provides a stable link.

// During live
const live = await client.resolve("https://youtube.com/watch?v=abc123");
console.log(live.sessionId); // "abc123"
// After the stream ends, the archive has the same sessionId
const archive = await client.resolve("https://youtube.com/watch?v=abc123");
console.log(archive.sessionId); // "abc123"