Once a video is ready you can play it with the Fileboy player, a web component that works in any page or framework, or in an iframe, or point any HLS or DASH player at its manifest. Reading a video needs no key.
Add one script tag and use the element anywhere on the page. It is about 20 KB gzipped. Safari and iOS play the stream natively; other browsers download hls.js the first time someone hovers or presses play. Elements added later, for example from
innerHTML1 2 3 4 5 6<script type="module" src="https://cdn.jsdelivr.net/npm/@cd2/fileboy-player@1.2.0/dist/fileboy-player.js" ></script> <fileboy-player video-id="YOUR_VIDEO_ID"></fileboy-player>
The player loads the video, shows the poster until the viewer presses play, and gives them quality, speed and captions menus, volume, fullscreen, picture in picture and lock-screen media controls. It has keyboard shortcuts (space or k, the arrow keys, < and >, m, f, i), labelled controls for screen readers, and debug info on right-click.
Attributes
video-id string, optional
The video id. Give either this or src.
api-url string, optional, default is https://api.fileboy.io
The Fileboy API address, or a proxy in front of it.
signed-query string, optional
For apps that require signed reads: the query string your server makes with signVideo. It is added to every video URL.
autoplay, loop, muted boolean, optional
As on a <video> element. Browsers may block autoplay unless the video is muted. Since 1.2.0, "false" means off, so a page can turn off what the app's branding switches on.
branding boolean, optional
Apply the app's player branding for this video (1.2.0+). See Player branding below.
accent-color, controls-color, background-color string, optional
Hex colours for the progress bar and hovered buttons, for icons and text, and around the video (1.2.0+).
logo, logo-position, logo-link, logo-alt string, optional
A logo image URL, its corner (top-left, top-right, bottom-left, bottom-right), an http(s) link it opens in a new tab, and the name screen readers read (1.2.0+).
hide-controls string, optional
Controls to hide: play, seek, volume, time, captions, speed, quality, pip, fullscreen, download, title, or all (1.2.0+).
download-url string, optional
Shows a download button for this URL (1.2.0+).
preload boolean, optional
Set the stream up before the first click, so playback starts faster.
controls-before-play boolean, optional
Show the control bar before the viewer has pressed play.
poster string, optional
An image URL to show before play instead of the video's poster.
height string, optional
A fixed height such as 360 or 50vh. Without it the player keeps a 16:9 shape.
embed boolean, optional
Fill the parent's height, for full-page and iframe layouts.
default-caption string, optional
The language of the captions to switch on, or off. Without it the viewer's last choice for this video is used.
no-caption-control boolean, optional
Hide the captions menu.
thumbnails string, optional
URL of a WebVTT thumbnails track (sprite.jpg#xywh=x,y,w,h cues) for previews when hovering the seek bar. Without one, the seek bar shows only the time.
src string, optional
Any HLS URL, instead of video-id. With no video-id the player makes no Fileboy API calls; with both, it still loads the video's data but plays this URL.
engine "native" | "hlsjs", optional
For testing only: force native HLS or hls.js instead of the player's own choice.
The element works like a
<video>playpauseendedtimeupdateratechange{ currentTime, duration }event.detailfileboy-load1 2 3 4 5 6 7 8 9 10 11 12const player = document.querySelector("fileboy-player") player.addEventListener("play", e => console.log("playing at", e.detail.currentTime)) player.addEventListener("ended", e => console.log("watched", e.detail.duration, "seconds")) player.addEventListener("fileboy-load", e => console.log(e.detail.status, e.detail.data)) await player.play() player.pause() player.currentTime = 30 player.muted = true player.playbackRate = 1.5 player.media // the underlying <video>, for anything else
The player draws its controls inside its own shadow DOM, so
document.querySelector("video")player.mediaCaptions you upload appear in its captions menu as before. You can add more as
<track>1 2 3 4<fileboy-player video-id="YOUR_VIDEO_ID" thumbnails="/thumbs/video.vtt"> <!-- extra captions, shown in the CC menu next to the video's own transcripts --> <track kind="subtitles" srclang="fr" src="/captions/fr.vtt" default> </fileboy-player>
Style it with CSS custom properties, or reach inside with
::part()1 2 3 4 5 6 7 8 9fileboy-player { --fbp-accent: #ff3e6c; /* progress bar, button hover, selected menu item */ --fbp-radius: 12px; --fbp-font: Inter, sans-serif; } fileboy-player::part(controls) { padding-bottom: 12px; }
In a bundled app,
npm install @cd2/fileboy-player1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17import { useEffect, useRef } from "react" import "@cd2/fileboy-player" export function Lesson({ videoId }: { videoId: string }) { const ref = useRef<HTMLElement>(null) // React 19 passes props and events to custom elements directly. // On React 16 to 18, pass booleans as "" and attach events with a ref. useEffect(() => { const player = ref.current const onEnded = () => console.log("finished") player?.addEventListener("ended", onEnded) return () => player?.removeEventListener("ended", onEnded) }, []) return <fileboy-player ref={ref} video-id={videoId} default-caption="English" preload="" /> }
Give the player your accent and other colours, a logo with a link, the controls you want, and autoplay, muted and loop defaults. Set them once for every video of an app in its dashboard settings, change them for one video in its Share & embed tab, or send
playerBrandingThe watch page and iframe embeds use it straight away. Embed parameters still win for one page:
?autoplay=0The web component uses it with the
brandingColours stay readable: icons on the accent switch to black or white, and where the accent is text or a focus ring it is lightened to 4.5:1 contrast. The dashboard warns about colours the player can't fix, such as an accent too dark to see on dark video.
Hiding a control also turns off its keyboard shortcut (hiding play turns off space and k); only m to mute always works. Hiding play hides every play button, and viewers can still click the video to play it. Download, off by default, offers the original file you uploaded.
The player never shows a Fileboy logo, on any plan. The watch page has a small "Powered by Fileboy" link below the video.
1 2 3 4 5 6 7 8 9 10 11 12 13<!-- the branding you set in the dashboard or the management API --> <fileboy-player video-id="YOUR_VIDEO_ID" branding></fileboy-player> <!-- or set it in the page, with no extra request --> <fileboy-player video-id="YOUR_VIDEO_ID" accent-color="#ff3e6c" logo="https://example.com/logo.png" logo-position="top-right" logo-link="https://example.com" logo-alt="Acme" hide-controls="pip speed" ></fileboy-player>
Any player can read the branding for a video. It is the app's with the video's own on top, with the logo as an image URL sized for a player. In an app that requires signed reads it needs the video's signature, and the logo and download URLs come back signed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21curl https://api.fileboy.io/videos/VIDEO_ID/player-config { "data": { "accentColor": "#ff3e6c", "controlsColor": null, "backgroundColor": null, "logo": { "url": "https://api.fileboy.io/images/get/LOGO_ID?transform=resize:_x96~upscale:false", "position": "top-right", "link": "https://example.com", "alt": "Acme" }, "controls": { "play": true, "seek": true, "volume": true, "time": true, "captions": true, "speed": true, "quality": true, "pip": false, "fullscreen": true, "download": true, "title": true }, "downloadUrl": "https://api.fileboy.io/files/get/ORIGINAL_ID?download=1", "autoplay": false, "muted": false, "loop": false } }
To put a video on a page you do not control the code of, such as a CMS, a newsletter tool or a docs site, use the embed page. Each video's page in the dashboard gives you this code ready to copy.
1 2 3 4 5 6 7 8<iframe src="https://fileboy.io/video/embed/YOUR_VIDEO_ID" width="560" height="315" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" allowfullscreen ></iframe>
Add
?autoplay=1loop=1muted=1t=90t=The manifest is an ordinary URL. Ask for HLS or DASH explicitly with
type=1 2 3 4 5 6 7 8 9 10 11# a manifest for your own player https://api.fileboy.io/videos/VIDEO_ID/manifest?type=hls https://api.fileboy.io/videos/VIDEO_ID/manifest?type=dash https://api.fileboy.io/videos/VIDEO_ID/manifest # auto # the poster image https://api.fileboy.io/videos/VIDEO_ID/poster # a page to share, with share and embed buttons https://fileboy.io/video/watch/VIDEO_ID https://fileboy.io/video/watch/VIDEO_ID?t=90 # start 90 seconds in
1 2 3 4 5 6 7 8 9 10 11 12import Hls from "hls.js" const video = document.querySelector("video")! const src = "https://api.fileboy.io/videos/VIDEO_ID/manifest?type=hls" if (video.canPlayType("application/vnd.apple.mpegurl")) { video.src = src // Safari plays HLS natively } else if (Hls.isSupported()) { const hls = new Hls() hls.loadSource(src) hls.attachMedia(video) }
The Fileboy player itself uses hls.js, or native HLS on Safari. Any player that can play HLS or DASH can use the manifest. For previews over the progress bar, point your player at the video's seek-preview thumbnails (
/videos/:id/thumbnails.vttCaptions you upload for a video appear in the player's captions menu automatically. See Upload and process for how to add them and the captions guide for a worked example.