homeaboutvideotry it nowpricingdocs
Docs

Getting Started

Play a video

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.

A video that is still encoding answers with a "Video processing" message. The Fileboy player shows a waiting screen until it is ready. Use a webhook if you want to know exactly when.

The Fileboy player

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

innerHTML
or a framework, set themselves up.

index.html
1
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>
. Its
play
,
pause
,
ended
,
timeupdate
and
ratechange
events carry
{ currentTime, duration }
in
event.detail
, and
fileboy-load
fires once the video's data has loaded, or failed to.

JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
const 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")
won't find the video. Use
player.media
instead.

Captions you upload appear in its captions menu as before. You can add more as

<track>
children, and point it at seek-preview thumbnails:

Captions and thumbnails
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()
. The parts are root, video, poster, title, logo, message and controls. For an app-wide look you set once, see Player branding below.

styles.css
1
2
3
4
5
6
7
8
9
fileboy-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-player
and import it once. It is safe to import during server-side rendering. In React:

Lesson.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { 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="" />
}

Player branding

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

playerBranding
to the management API. The dashboard previews the player as you change them.

  • The watch page and iframe embeds use it straight away. Embed parameters still win for one page:

    ?autoplay=0
    turns off autoplay the branding switches on.

  • The web component uses it with the

    branding
    attribute. Without it nothing changes and no extra request is made, so players already on your pages look the same until you opt in. Attributes you set win over the branding.

  • Colours 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.

Branding in your page
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.

GET /videos/:id/player-config
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
curl 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
  }
}

Iframe embed

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.

Embed
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=1
(always muted, as browsers require),
loop=1
,
muted=1
or
t=90
to start 90 seconds in. The watch page takes
t=
too, and its Embed button writes the code for you.

Your own player

The manifest is an ordinary URL. Ask for HLS or DASH explicitly with

type=
, or leave it out and Fileboy picks DASH for Chrome and HLS for everything else. Every request for a manifest counts as a play.

URLs
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
hls.js
1
2
3
4
5
6
7
8
9
10
11
12
import 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.vtt
).

Captions

Captions 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.

Play a video

The Fileboy playerPlayer brandingIframe embedYour own playerCaptions
hello@fileboy.io

Fileboy

HomeAboutPricingChangelog
© Copyright 2026, CD2 Solutions Ltd.
Terms and ConditionsPrivacy Policy