Two ways to embed
The web component. <video-piper> is a drop-in player for developers. It plays the HLS stream (with hls.js loaded only where the browser needs it) or the MP4, shows captions, and refreshes its signed links before they expire, keeping the viewer's position. It is one script of about 3 KB gzipped, with no framework.
The iframe. For a page where you'd rather not write code, open a video's menu, choose Embed and copy the code, with options for autoplay (muted), loop, captions on and a start time.
Example
Your server returns the links for a video (it holds the API key, and can cache them per video). The page needs only the script and the element:
// Your server (Node.js): GET /api/videos/:id/links, cached per video
const cache = new Map();
app.get("/api/videos/:id/links", async (req, res) => {
const hit = cache.get(req.params.id), now = Date.now() / 1000;
if (hit && hit.playbackExpiresAt - now > 0.2 * hit.ttl) return res.json(hit);
const r = await fetch(`${API}/videos/${req.params.id}?linkTtl=86400`, { headers: { Authorization: `Bearer ${API_KEY}` } });
if (!r.ok) return res.status(r.status).end();
const s = await r.json();
const links = { playbackUrl: s.playbackUrl, streamUrl: s.streamUrl, posterUrl: s.posterPlaybackUrl,
captionsUrl: s.captions?.vttUrl, playbackExpiresAt: s.playbackExpiresAt, ttl: s.playbackExpiresAt - now };
cache.set(req.params.id, links);
res.json(links);
});
<script src="https://videopiper.com/player/player.js"></script>
<video-piper links-url="/api/videos/VIDEO_ID/links"></video-piper>
Both snippets come from the documentation, which also has a C# (ASP.NET Core) version of the server code.
Attributes and events
| Attribute | What it does |
|---|---|
links-url | Your endpoint for fresh links (JSON, same names as the status). |
src, stream-src, poster | The MP4 (playbackUrl), the HLS stream (streamUrl, Pro and Scale, preferred when present) and the poster. |
captions, captions-lang, captions-label, cc | A WebVTT file for the MP4 (the stream carries its own subtitle track), and cc shows captions from the start. |
expires-at | Unix time the links expire, so it knows when to refresh. |
autoplay, muted, loop, start, controls="false" | As for <video>; autoplay also mutes, as browsers require; start is in seconds. |
No endpoint? Leave out links-url, listen for the vp-expiring event and call element.setLinks({...}) with fresh links. The element is 16:9 by default and styled like any element (video-piper { width: 100%; }); the inner video is element.video for events like timeupdate and ended.
Control where it plays
- No key in the page. The signed links are all the page holds, and your endpoint decides who gets them.
- Allowed domains. List up to 20 sites, such as
example.comand*.example.com. Links only play there, and the iframe's page can only be framed by them. - Opt-in iframes. Embedding is off for each video until you turn it on. The embed URL carries a random token; turning embedding off revokes it, and turning it on again makes a new one. Changes take up to 5 minutes to reach every viewer, because embed pages are cached.
Plays count as delivery, like any other playback. See the HLS streaming API for signed links and allowed domains in more detail, or the captions API for subtitle files.
Which plans include the player
The web component and the iframe embed work on every plan, playing the signed MP4 playback link. On Pro and Scale they prefer the adaptive HLS stream when there is one. Embeds from Free-plan accounts show a small brand badge.
| Plan | Price | Processing minutes | Max quality | Embeddable player |
|---|---|---|---|---|
| Free | $0/mo | 30 | 720p | Included |
| Starter | $49/mo | 400 | 1080p | Included |
| Pro | $199/mo | 1,500 | 4K | Included |
| Scale | $699/mo | 6,000 | 4K | Included |
Usage beyond a paid plan is billed at $0.09 per processing minute, $0.15 per GB-month of storage and $0.55 per GB of delivery. Full details are on the pricing page.
In the documentation
- The video-piper web component
- Build your own player
- Embedding with an iframe (no code)
- Allowed domains
- Captions
Frequently asked questions
How do I add the player to my page?
Load the one script, player.js, and add a video-piper element whose links-url attribute points at your own endpoint. That endpoint returns the video's playbackUrl, streamUrl, poster and caption links. The component calls it again a few minutes before the links expire.
Does the page need my API key?
No. The signed links are the only thing the player needs. Your API key stays on your server, and you decide who your endpoint answers, for example only signed-in users.
Can I embed without writing code?
Yes. Turn on embedding for a video (Embed in the video's menu, or PUT /videos/{id}/embed) and paste the iframe code. Embedding is off until you enable it, and turning it off revokes the code.
How big is the component?
About 3 KB gzipped. It uses a shadow root and native controls with no framework, and loads hls.js only where the browser needs it.
Can other sites reuse my embed?
Once you set allowed domains, browsers only show the player inside your sites, and playback links only play there. Embedding is not DRM.