This player uses a HTML5 <track> element to display subtitles and a subtitle selection menu in all browsers:

#with-subtitles {
  background-image: url("//");
#with-subtitles.cue6 .fp-captions p {
/* one huge custom subtitle */
  font-size: 40px;

View standalone demo

Setting up

As for video sources we discern 2 installation categories:

Video tag based

In a VIDEO tag based installation subtitles are loaded from TRACK elements as follows:

<div id="with-subtitles" class="flowplayer"

      <source type="application/x-mpegurl"
      <source type="video/mp4"

      <track kind="subtitles" default srclang="en" label="English"
      <track kind="subtitles" srclang="de" label="Deutsch"


Pure JavaScript

The same setup looks like this in a pure JavaScript installation:

flowplayer("#with-subtitles", {
    clip: {
        subtitles: [
            { "default": true, // note the quotes around "default"!
              kind: "subtitles", srclang: "en", label: "English",
              src:  "//" },
            { kind: "subtitles", srclang: "de", label: "Deutsch",
              src:  "//" }
        sources: [
            { type: "video/webm",
              src:  "//" },
            { type: "video/mp4",
              src:  "//" },
            { type: "video/flash", src: "mp4:functional" }
    share: false,
    ratio: 5/12

The subtitles array is the representation the attributes of one or more subtitle TRACK elements of a HTML5 VIDEO tag in JavaScript Object Notation in a similar fashion as the sources array is for video SOURCE elements in a clip object.

VTT file format

A WEBVTT file referenced in the TRACK element has the following structure:


00:00:01.000 --> 00:00:04.000
The first subtitle from 1 seconds to 4 seconds
This is a second line
And a third one

00:00:05.000 --> 00:00:06.000
<b>Bold</b>, <i>italic</i> and <u>underlines</u> are supported


Make sure to save your WebVTT files in UTF-8 format.

Server side

VTT files must be served on a loose cross-origin policy (CORS) with an appropriate Access-Control-Allow-Origin header if they are loaded from a different domain, even a different sub domain.

For instance, in an Apache configuration:

Header set Access-Control-Allow-Origin "*"

Setting the CORS policy for the VTT files is always mandatory when you offer the player for sharing

For more details look up cross-orgin resource sharing.

It is recommended to serve VTT files with a mime type of text/vtt. If you have native subtitles configured this is mandatory.


Player options

On the player configuration level the subtitle extension offers these options:

option default value description
nativesubtitles false HTML5 only. Whether subtitle display is delegated to the native subtitle implementation of the browser or device.
See below for further details.
subtitleParser function (txt) The default subtitle parser can be overridden without the need for a plugin with this option. That way specific subtitle parsers can be implemented not only globally, but for individual players on the page.
It also allows for custom support of non-VTT caption formats.
The function takes one argument which is the complete text of all subtitles.
By definition this option cannot be set as HTML data attribute.
See below for further details.

Support for loading VTT files from a different domain for native subtitle display is broken in most browsers.

Clip options

The subtitles extension provides the following clip configuration option.

property description
subtitles An array of subtitle track objects. Not to be mistaken for the API property holding the array of the currently loaded subtitles.

Video tag based cross origin

In VIDEO tag based installations the crossorigin attribute must be added to the VIDEO tag if (and only if) the VTT file is loaded from a different main domain - here is a demo.

<video crossorigin="anonymous">
   <track kind="subtitles" srclang="en" label="English"
   <!-- sources go here -->

Contrary to the the server side CORS requirement this is not required when the VTT file is loaded from a different sub domain.

Subtitle options

Each member of the subtitles array accepts the following properties:

property default value description
“default” false If set, this track is enabled initially. Only one track can be the "default" track.
Important: This option must be quoted when a track is specified in JSON syntax because default is a reserved word in JavaScript.
Mandatory if a subtitle track should be shown from the start without being selected via the subtitle menu.
kind The kind of this track. Usually subtitle.
label Default (srclang) Label of this track displayed in the subtitle menu.
src Location of the VTT file for this track.
Specifying src is mandatory.
srclang en Language of this subtitle track in 2 letter language code.

All properties can be set as attributes of the same name to a TRACK element in a VIDEO tag based installation.

Custom looks

The first subtitle above would generate the following HTML code:

<div class='fp-captions'>
   <p>The first subtitle from 1 seconds to 4 seconds</p><br>
   <p>This is a second line</p><br>
   <p>And a third one</p><br>

Flowplayer comes with a default look for the subtitles, but are completely customizable via CSS:

/* override default looks */
.flowplayer .fp-captions p {
   font-size: 18px;

/* visible subtitle looks (.fp-shown class) */
.flowplayer .fp-captions.fp-shown { 
   opacity: 0.8;

/* custom looks for 7:th subtitle */
.flowplayer.cue6 .fp-captions p {
   font-size: 40px;

Native subtitles

Currently the TRACK element is supported natively by the following browsers:

  • IE 10 (since November 2011)
  • Google Chrome 18 (since November 2011)
  • Safari 6 (July 2012)
  • Opera 12.5 (August 2012)

Native HTML5 subtitles can only be displayed by the html5 engine.

You can enable native support with nativesubtitles configuration variable and by adding default attribute to the TRACK element. For example:

<div class="flowplayer" data-nativesubtitles="true" data-share="false">
      <source type="application/x-mpegurl" src="//">
      <source type="video/mp4" src="//">
      <track src="/path/to/my-subtitles-en.vtt" default>

Note that we disable sharing because cross domain loading of VTT files generically is broken in most browsers.

After this the subtitle looks are browser dependent and you lose the CSS customization possibilities. Neither will the Flowplayer subtitle menu be shown because native subtitles cannot be governed externally.

Native support is present when is true. For example:

if ( {
   // do your thing

JavaScript API


The subtitles extension provides the following property for the player API:

property kind description
subtitles array The complete list of all currently loaded subtitleobjects. Not to be mistaken for the configured array ofsubtitle track objects.

Like all API properties the subtitles property can be inspected in the browser console:;

Video object

The current video’s subtitle track objects are available as video object properties.

property kind description
subtitles array The list of subtitle tracks for the current clip, in object notation.

To verify whether the subtitle configuration for the current clip works as intended, inspect video.subtitles in the browser console:;

Subtitle object

Each member of the subtitles array has the following properties:

property description
endTime The cuepoint time value when this subtitle ends.
startTime The cuepoint time value when this subtitle is displayed.
text The text of this subtitle.
title The so-called title of this subtitle, usually an integer, incremented by 1 for each subtitle.


The subtitles extension provides the following methods for the player API:

method description
disableSubtitles() Disable subtitle display. Like choosing ‘No subtitles’ from the subtitle menu.
loadSubtitles(index) Loads subtitle track at given index in the configured array of subtitles. Like choosing the track from the subtitle menu at index top down.


There is no “subtitle” event, but for each subtitle 2 cuepoints are generated which mark the time when the subtitle is displayed at the startTime of the subtitle, and the time when the subtitle ends at the endTime of the subtitle.

All subtitle cuepoints at startTime have these properties:

property description
subtitle The subtitle object of this subtitle.
time The time value of this cuepoint which is equal to the startTime value of the subtitle object for this subtitle.
visible This is always false to discern subtitle cuepoints from generated cuepoints.

All subtitle cuepoints at endTime have these properties:

property description
subtitleEnd A string referencing the title property of the subtitle object for this subtitle.
time The time value of this cuepoint which is equal to the endTime value of the subtitle object for this subtitle.
visible This is always false to discern subtitle cuepoints from generated cuepoints.

This results in the following outline for handling subtitles in the JavaScript API:

player.on("cuepoint", function(e, api, cuepoint) {

   // start of a subtitle
   if (cuepoint.subtitle) {


   // end of a subtitle
   if (cuepoint.subtitleEnd) {



CSS classes

The has-menu class is added to the container element if the current clip features subtitles.

As subtitles use the cuepoints mechanism internally cue{index} classes are used here as well. An even cue index indicates that a subtitle is shown, an odd index that currently no subtitle is shown.

<div class="flowplayer cue0 has-menu">
  <!-- the first subtitle is currently displayed -->
<div class="flowplayer cue7 has-menu">
  <!-- the forth subtitle has ended -->

If used in conjunction with cuepoints the cue index includes user configured cuepoints as well and is hardly useable as indicator.

Subtitle parser

An abstract implemenation of a custome subtitleParser option looks like this:

flowplayer("#container", {
  clip: {
    // clip configuration goes here
  subtitleParser: function (txt) {
    // process complete text of a subtitle track

The shipped subtitleParser implementation can be used as guidance. Its code can be found here.

If you decide to write a parser for a non-VTT format, be aware that these captions will not be shown on devices which cannot play video inline. Consider batch converting the caption files to VTT instead.

Known issues and limitations

Flowplayer does not support VTT extra definitions such as text alignment and line position. Style is completely controlled with CSS for full cross browser support.

When using the default attribute on the track element some browsers may show their native controlbar for a short glimpse of time.


Resources about the WebVTT format:

Resources for caption creation / conversion

WebVTT validator