Output Assets
HLS streams, MP4 downloads, preview clips, auto-thumbnails, and subtitles from every upload.
Every video you upload to Rad TV is automatically processed into multiple formats optimized for different use cases — streaming, downloading, sharing, and embedding. After transcoding completes, you get all of these without any extra work.
Querying Output Assets
curl -X POST https://api.rad.live/graphql \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"query": "{ me { channel { features(first: 5) { edges { node { id metadata { title } outputAssets { encoderType video { hls download preview } audio { download } images { thumbnails { urlFormat count } videoThumbnails { urlFormat count } } subtitles { srt vtt } } } } } } } } }"
}'const response = await fetch('https://api.rad.live/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_API_KEY',
},
body: JSON.stringify({
query: `{
me {
channel {
features(first: 5) {
edges {
node {
id
metadata { title }
outputAssets {
encoderType
video { hls download preview }
audio { download }
images {
thumbnails { urlFormat count }
videoThumbnails { urlFormat count }
}
subtitles { srt vtt }
}
}
}
}
}
}
}`,
}),
});
const { data } = await response.json();
data.me.channel.features.edges.forEach(({ node: f }) => {
console.log(f.metadata.title, f.outputAssets?.encoderType);
});import requests
response = requests.post(
"https://api.rad.live/graphql",
headers={
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_KEY",
},
json={
"query": """
{
me {
channel {
features(first: 5) {
edges {
node {
id
metadata { title }
outputAssets {
encoderType
video { hls download preview }
audio { download }
images {
thumbnails { urlFormat count }
videoThumbnails { urlFormat count }
}
subtitles { srt vtt }
}
}
}
}
}
}
}
"""
},
)
edges = response.json()["data"]["me"]["channel"]["features"]["edges"]
for edge in edges:
f = edge["node"]
oa = f.get("outputAssets")
if oa:
print(f["metadata"]["title"], oa["encoderType"])What You Get
Video
| Field | Description | Use For |
|---|---|---|
hls | Adaptive streaming manifest (.m3u8) | In-app video players, web embeds |
download | Full MP4 file | Offline viewing, archival, redistribution |
preview | Short 10-30 second clip | Social media teasers, content previews |
Audio
| Field | Description | Use For |
|---|---|---|
download | Separate audio track | Podcast feeds, audio-only playback |
Images
| Field | Description | Use For |
|---|---|---|
thumbnails | Auto-generated static frame captures | Video players, content grids, social sharing |
videoThumbnails | Animated preview clips at key moments | Hover previews, rich thumbnails |
Each thumbnail set gives you a urlFormat (URL template) and count (how many). See Thumbnail Expansion below.
Subtitles
| Field | Description | Use For |
|---|---|---|
srt | SubRip subtitle file | Desktop players, editing tools |
vtt | WebVTT subtitle file | Web video players, accessibility |
Thumbnail URL Expansion
Thumbnails use a compact urlFormat with placeholder digits that you expand client-side. The format depends on the encoder type.
Standard Encoder (7-digit, 0-based)
urlFormat: "https://cdn.rad.live/.../thumbnail_XXXXXXX.jpg"
count: 50Replace XXXXXXX with zero-padded indices from 0000000 to 0000049:
https://cdn.rad.live/.../thumbnail_0000000.jpg
https://cdn.rad.live/.../thumbnail_0000001.jpg
...
https://cdn.rad.live/.../thumbnail_0000049.jpgRad Encoder (2-digit, 1-based)
urlFormat: "https://cdn.rad.live/.../thumbnail_XX.jpg"
count: 20Replace XX with indices from 01 to 20:
https://cdn.rad.live/.../thumbnail_01.jpg
https://cdn.rad.live/.../thumbnail_02.jpg
...
https://cdn.rad.live/.../thumbnail_20.jpgExpansion Example
function expandThumbnails(urlFormat, count, encoderType) {
const thumbnails = [];
const isRadEncoder = encoderType === 'RAD_ENCODER';
const startIndex = isRadEncoder ? 1 : 0;
const placeholder = isRadEncoder ? 'XX' : 'XXXXXXX';
const padLength = isRadEncoder ? 2 : 7;
for (let i = startIndex; i < startIndex + count; i++) {
const index = String(i).padStart(padLength, '0');
thumbnails.push(urlFormat.replace(placeholder, index));
}
return thumbnails;
}Encoder Types
The encoderType field tells you which encoder processed the content:
| Value | Description |
|---|---|
MEDIA_CONVERT | Standard transcoding |
RAD_ENCODER | AI-enhanced transcoding (Creator+ and enhance: true) |
Nullability
outputAssets is null on Content when transcoding hasn't started or is still in progress. Always check for null before accessing nested fields. Once transcoding completes, all sub-fields (video, audio, images) are non-null.
Next steps
- Publish to Rad — The full publishing pipeline
- AI Upscaling — Get enhanced output with Real-ESRGAN
- Transcoding — GraphQL reference for transcode job management