Video streaming, simplified

Upload, transcode, and stream video with adaptive HLS. Your source files are never modified - xform handles transcoding and delivery so you don't have to.
<iframe src="https://acme.xform.media/_embed/intro">
Your video, your player, your domain
1:24 / 4:12
720p1x
How It Works

From upload to playback in minutes

The xform video pipeline handles transcoding, storage, and delivery so you can focus on building your product.
1
Ingest

Point xform at a video in your source (S3, R2, etc.) or upload directly to xform via a presigned URL if you don't need the source file in your own storage.

2
Transcode

xform automatically transcodes your video into multiple HLS quality levels (1080p, 720p, 480p) plus an MP4 download, thumbnail, and optional captions.

3
Stream

Serve adaptive bitrate HLS from the edge. Embed the player with a single line of code or use the raw HLS manifest directly in your own player.

4
Analyze

Built-in analytics track views, watch duration, completion rates, quality distribution, and referrers - no third-party scripts needed.

Embed Player

A fully-featured player you can embed anywhere

The xform player ships as a self-contained HTML page with no external dependencies beyond hls.js. Embed it via iframe or use the HLS manifest in your own player.
Adaptive bitrate
Automatically adjusts quality based on network conditions using hls.js.
Quality selector
Let viewers choose between 1080p, 720p, 480p, or auto quality.
Speed controls
Playback speed from 0.5x to 2x for education, tutorials, and presentations.
Captions
WebVTT caption support with on/off toggle and styled overlay display.
Caption search
Fuzzy search through captions to jump to any moment in the video.
Share with timestamp
Copy a link that starts playback at the current position.
Fullscreen
Native fullscreen support with keyboard shortcut (F).
Keyboard shortcuts
Space/K to play, arrows to seek, M to mute, C for captions.
Auto thumbnail
Poster image extracted automatically during transcoding.
Customizable
Set accent color, logo, title overlay, and control visibility.
Iframe embed
One-line embed code via SDK or direct URL with query parameters.
Mobile-ready
Works on all devices with native HLS fallback for Safari and iOS.

Embed with the SDK

import { XformClient } from '@xformmedia/sdk'

const client = new XformClient({ ... })

// Returns an iframe HTML string
const html = client.embed('intro', {
  autoplay: false,
  quality: 'auto',
  captions: true,
  color: '6366f1'
})

Or link directly

<!-- Embed player via iframe -->
<iframe
  src="https://acme.xform.media/_embed/intro?captions=1"
  width="100%"
  height="100%"
  frameborder="0"
  allowfullscreen
></iframe>

<!-- Or use HLS directly -->
<!-- https://acme.xform.media/_v/intro.m3u8 -->
Transcoding

Automatic multi-quality transcoding

Every video is transcoded into multiple HLS renditions, an MP4 for download, a thumbnail, and optional captions.

Quality levels

QualityBitrateNotes
1080p4 MbpsOnly if source is 1080p or higher
720p2 MbpsOnly if source is 720p or higher
480p800 kbpsAlways included (minimum)
H.264
Video codec
6 sec
HLS segment length

What you get per video

HLS master + rendition playlists

Adaptive bitrate M3U8 manifests for seamless quality switching.

MP4 download

Progressive download with faststart for instant playback.

Thumbnail

Auto-extracted poster image at 1280px wide.

Captions

VTT extraction from source or manual upload via SDK.

Renditions are automatically filtered - xform never upscales. A 720p source produces 720p and 480p, not 1080p.

SDK

Full control via the xform SDK

Manage the entire video lifecycle programmatically - from upload to analytics.
MethodDescription
client.createUploadUrl()Get a presigned URL to upload directly to xform (not your source)
client.ingest({ key })Trigger transcoding for an uploaded video
client.events()Real-time SSE stream of video status changes
client.embed(videoKey)Generate an iframe embed code
client.videos.list()List all videos with pagination
client.videos.get(key)Get video metadata, status, and renditions
client.videos.analytics()Query view counts, engagement, and quality metrics
client.videos.uploadCaptions()Upload or replace WebVTT captions
client.videos.delete(id)Delete video and all transcoded assets

Install

npm install @xformmedia/sdk

Quick example

const client = new XformClient({
  sourceId: 'src_...',
  organizationId: 'org_...',
  apiKey: 'xfm_...',
  baseUrl: 'https://admin.xform.media',
  streamBaseUrl: 'https://acme.xform.media'
})

const { key } = await client.createUploadUrl({
  filename: 'demo.mp4',
  contentType: 'video/mp4'
})

const { videoKey } = await client.ingest({ key })
Events & Insights

Webhooks and built-in analytics

Know when your videos are ready and understand how they're being watched.

Webhook events

video.ready

Transcoding completed - includes stream URL, duration, dimensions, and thumbnail.

video.failed

Transcoding failed after 3 retry attempts - includes error message.

video.renamed

Video display name was changed.

HMAC-SHA256 signature verification
3 retry attempts with exponential backoff
Per-video callback URL or source-level webhook
Real-time SSE events via SDK

Analytics dashboard

Views

Total views, unique sessions, and daily trends.

Engagement

Average watch time, completion rate, and event breakdown.

Quality

Quality distribution and automatic switching patterns.

Referrers

See which domains and pages drive the most views.

Analytics are collected automatically by the embed player - no extra scripts or configuration needed.

Ownership

Your source files, untouched

xform reads from your source to transcode - your originals are never modified, moved, or deleted.
Any source provider

Your videos live in S3, R2, or any supported storage. xform reads from your source and stores transcoded files on our infrastructure.

Your domain

Serve video from your own subdomain. Custom domains work for both images and video.

Your API keys

Source-scoped API keys give you fine-grained control. Credentials are encrypted at rest.

Ready to stream?

Add video streaming to your app with the xform SDK. Upload, transcode, embed - done.