Workflows

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

FieldDescriptionUse For
hlsAdaptive streaming manifest (.m3u8)In-app video players, web embeds
downloadFull MP4 fileOffline viewing, archival, redistribution
previewShort 10-30 second clipSocial media teasers, content previews

Audio

FieldDescriptionUse For
downloadSeparate audio trackPodcast feeds, audio-only playback

Images

FieldDescriptionUse For
thumbnailsAuto-generated static frame capturesVideo players, content grids, social sharing
videoThumbnailsAnimated preview clips at key momentsHover previews, rich thumbnails

Each thumbnail set gives you a urlFormat (URL template) and count (how many). See Thumbnail Expansion below.

Subtitles

FieldDescriptionUse For
srtSubRip subtitle fileDesktop players, editing tools
vttWebVTT subtitle fileWeb 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: 50

Replace 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.jpg

Rad Encoder (2-digit, 1-based)

urlFormat: "https://cdn.rad.live/.../thumbnail_XX.jpg"
count: 20

Replace 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.jpg

Expansion 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:

ValueDescription
MEDIA_CONVERTStandard transcoding
RAD_ENCODERAI-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

On this page