homeaboutvideotry it nowpricingdocs
Guide

Stream video with HLS without running ffmpeg

Upload a video, get adaptive streaming and a poster image, and play it with one tag.

Why a plain video file is not enough

Putting an MP4 behind a <video> tag works for a short clip on a fast connection. For anything longer it means every viewer downloads the same large file whatever their bandwidth, and seeking depends on how the file was encoded.

HLS fixes this by splitting a video into short segments at several quality levels, plus a manifest that lists them. The player picks a quality that suits the connection and switches as it changes. The catch is producing those renditions: normally an ffmpeg job, a queue, somewhere to run it, and a way to know when it has finished.

What Fileboy does for you

You upload the original file. Fileboy encodes it into the renditions, generates a poster image, and serves a manifest. HLS is available, and DASH is too. When you ask for an auto manifest it chooses between them.

Upload from the Videos page of your app dashboard. Processing is not instant, and a video that is still encoding reports that status rather than failing, so a player shows a friendly message until it is ready.

Video counts against your plan's video limit, separately from files. The free plan includes three videos, which is enough to try this end to end. See pricing.

Play it on your page

Each video has an ID, shown in the dashboard. Load the player script once and give <fileboy-player> the ID. The player loads the stream, shows the poster until the viewer presses play, and offers quality, speed and captions menus.

index.html
<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>

Useful attributes: autoplay, loop, preload (set up the stream before the first click) and poster to override the poster. The element fires play, pause, timeupdate and ended events with { currentTime, duration } in event.detail, for progress tracking.

Play it in React

npm install @cd2/fileboy-player

The player is a web component, so React renders it like any other element. Import the package once to register it.

Lesson.tsx
import { useEffect, useRef } from "react"
import "@cd2/fileboy-player"

export function Lesson({ videoId }: { videoId: string }) {
  const ref = useRef<HTMLElement>(null)

  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} />
}

On React 16 to 18, pass boolean attributes as an empty string (preload="") and listen for events with a ref, as above. React 19 passes both through directly.

Or use an iframe

On a page where you cannot add scripts, paste an iframe. The dashboard gives you the embed code on each video's page, and it looks like this:

<iframe
  src="https://fileboy.io/video/embed/YOUR_VIDEO_ID"
  width="560"
  height="315"
  frameborder="0"
  allow="autoplay; fullscreen; picture-in-picture"
  allowfullscreen
></iframe>

Upload from your server

Uploads from a script or backend use the same API. The Ruby, Python and PHP libraries wrap it, and the HTTP call is shown too. The shared demo key cannot upload video.

// Video upload is part of the HTTP API. The SDKs for Ruby, Python and PHP wrap it:
// see the Ruby, Python or PHP tab, or upload from the dashboard.

Transcripts attach to a video as WebVTT or plain text, one per language:

id = fileboy.upload_video_transcript(video.id, "./clips/launch.vtt", language: "English")
text = fileboy.fetch_video_transcript(video.id, id)

Use your own player instead

The manifest is a normal URL, so Safari can play it natively and other browsers can use a library such as hls.js or Shaka Player. Ask for the HLS manifest explicitly with type=hls.

https://api.fileboy.io/videos/YOUR_VIDEO_ID/manifest?type=hls

# a poster image for the video
https://api.fileboy.io/videos/YOUR_VIDEO_ID/poster

Where this stops

This is streaming of video you upload. It is not live streaming, and it does not do per-viewer rendering, in-video editing or a content moderation pipeline. If video is the centre of your product, compare the options before committing: see Fileboy vs Cloudinary for an honest account of where a larger platform is the better call.

Checked against the current libraries in November 2026. Found something that no longer works? Tell us.

Go deeper

Still choosing a tool?

Fileboy is small on purpose. This comparison says where it fits and where another option is the better call.

Fileboy vs Mux · All comparisons

Try it

The free plan needs no card and includes 1,000 files, so you can run every example above.

More guides: How to add image upload to a React app · Resize images on the fly with a URL · Add captions and subtitles to a video · Embed a video on any website · All guides

Add Fileboy to your next project

We built Fileboy to stop rebuilding file handling for every app. Create an app, paste your key and upload a file. The free plan needs no card.