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-subtitle p {
/* one huge custom subtitle */
font-size: 40px;


view standalone page

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: "/standalone/basics/subtitles-en.vtt" },
{ kind: "subtitles", srclang: "de", label: "Deutsch",
src: "/standalone/basics/subtitles-de.vtt" }
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


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 "*"


  • Important 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:

optiondefault valuedescription
nativesubtitlesfalseHTML5 only. Whether subtitle display is delegated to the native subtitle implementation of the browser or device.
See below for further details.
subtitleParserfunction (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.
  • Warning 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.

subtitlesAn 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:

propertydefault valuedescription
"default"falseIf 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.
kindThe kind of this track. Usually subtitle.
labelDefault (srclang)Label of this track displayed in the subtitle menu.
srcLocation of the VTT file for this track.
Specifying src is mandatory.
srclangenLanguage 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-subtitle'>
<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-subtitle p {
font-size: 18px;
/* visible subtitle looks (.fp-active class) */
.flowplayer .fp-subtitle.fp-active { 
opacity: 0.8;
/* custom looks for 7:th subtitle */
.flowplayer.cue6 .fp-subtitle 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)
  • Important 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:

subtitlesarrayThe complete list of all currently loaded subtitle objects. Not to be mistaken for the configured array of subtitle 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.

subtitlesarrayThe 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:

endTimeThe cuepoint time value when this subtitle ends.
startTimeThe cuepoint time value when this subtitle is displayed.
textThe text of this subtitle.
titleThe 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:

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:

subtitleThe subtitle object of this subtitle.
timeThe time value of this cuepoint which is equal to the startTime value of the subtitle object for this subtitle.
visibleThis is always false to discern subtitle cuepoints from generated cuepoints.

All subtitle cuepoints at endTime have these properties:

subtitleEndA string referencing the title property of the subtitle object for this subtitle.
timeThe time value of this cuepoint which is equal to the endTime value of the subtitle object for this subtitle.
visibleThis 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 -->

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