<iframe src="https://acme.xform.media/_embed/intro">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.
xform automatically transcodes your video into multiple HLS quality levels (1080p, 720p, 480p) plus an MP4 download, thumbnail, and optional captions.
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.
Built-in analytics track views, watch duration, completion rates, quality distribution, and referrers - no third-party scripts needed.
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'
})<!-- 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 -->| Quality | Bitrate | Notes |
|---|---|---|
1080p | 4 Mbps | Only if source is 1080p or higher |
720p | 2 Mbps | Only if source is 720p or higher |
480p | 800 kbps | Always included (minimum) |
Adaptive bitrate M3U8 manifests for seamless quality switching.
Progressive download with faststart for instant playback.
Auto-extracted poster image at 1280px wide.
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.
| Method | Description |
|---|---|
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 |
npm install @xformmedia/sdkconst 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 })video.readyTranscoding completed - includes stream URL, duration, dimensions, and thumbnail.
video.failedTranscoding failed after 3 retry attempts - includes error message.
video.renamedVideo display name was changed.
Total views, unique sessions, and daily trends.
Average watch time, completion rate, and event breakdown.
Quality distribution and automatic switching patterns.
See which domains and pages drive the most views.
Analytics are collected automatically by the embed player - no extra scripts or configuration needed.
Your videos live in S3, R2, or any supported storage. xform reads from your source and stores transcoded files on our infrastructure.
Serve video from your own subdomain. Custom domains work for both images and video.
Source-scoped API keys give you fine-grained control. Credentials are encrypted at rest.