J1 VideoPlayer is a complete video player engine built on top of VideoJS. It gives every video the same good-looking, skinnable player, and it adds a full playlist on top: a searchable, sortable list of videos that the viewer can play, rate, and continue from where they left off. It plays two kinds of video: native videos (files such as mp4, webm or ogv that you host yourself) and YouTube videos.
How It Works
You do not need to write any JavaScript to use it. You describe your players in a few simple YAML files and J1 builds the HTML for you. You can put multiple players on one page and each one keeps its own separate playlist and its own settings. The rest of this manual explains every setting you can change, the shape of a playlist file, and — for advanced users — the JavaScript methods the module exposes.
Before diving into the settings, it helps to know the four pieces that make up a J1 VideoPlayer. You never touch most of them directly, but knowing they exist makes every later section easier to follow.
- The configuration (YAML)
-
Three small text files describe your players: what they are called, which playlist they load, and how they look and behave. This is the part you edit. It is covered in Configuration.
- The HTML
-
J1 reads your configuration and automatically writes the HTML for each player — the video area, the playlist panel, and the edit panel. You do not write this by hand.
- The JavaScript core
-
A module called
videoPlayerstarts Video.js, wires up the buttons, and manages the playlist. It also loads a few helper plugins (skip buttons, next/previous buttons, zoom). Advanced users can call it directly; see Methods. - The playlist store
-
Each player keeps its playlist in the browser’s local storage. That is why a viewer’s ratings, and the position they stopped at, are still there the next time they open the page.
Native and YouTube Videos
A single playlist can mix both kinds of video:
- Native video
-
A video file that you host on your own web server (for example an
mp4). The player loads it directly. This is the most reliable option and works offline / on private sites. The file address goes in the entry’ssrcfield. - YouTube video
-
A video that lives on YouTube. You give the player the YouTube link and it plays the video through Video.js. The poster image is taken from YouTube automatically.
| Both kinds are configured in one place: the |
Several Players on a Page
You can place as many players on a page as you like. Every player has its own id (a short name such as player_1), its own playlist, and its own settings. Nothing leaks from one player to another: a video you add to player_1 never shows up in player_2, and a setting you change for one player never changes another. Internally each player is a separate instance of the module, created through a factory function — exactly the same idea Video.js uses. This is explained in Notes on Implementation.
Configuration
Almost everything you will ever change lives in YAML configuration files. YAML is a plain-text format for settings: a name, a colon, and a value. You do not need to know any programming to edit it.
Configuration Files
Settings come from three files that are merged together in order. Later files win, so you only have to write down what you want to change.
| File | What it is for |
|---|---|
| The defaults. Every possible option with a sensible value and a comment explaining it. You normally leave this file alone and read it as a reference. |
| Your global settings. Anything you put here overrides the defaults for all players. This is where you switch the module on with |
| Your per-player settings. This file lists each player separately, so you can give every player its own id, its own playlist, and its own look. |
| The merge chain is: defaults → overridden by global settings → overridden by per-player settings. The merge works per key: a per-player |
General Options
These live at the top of the settings and control the module as a whole.
| Option | Default | Description |
|---|---|---|
|
| Master on/off switch for the module. Set it to |
|
| The folder where your ready-made playlist files live. A short file name in a |
|
| The folder the module reads its generated data from. |
UI Elements
The ui_elements: block controls which controls (buttons and switches) of a player are shown at all. Each key stands for one visible element and takes true (show it) or false (hide it).
The two header buttons can be switched on and off per player: set the key in the defaults for everyone, in your global videoPlayer.yml for all players of your site, or inside one player’s entry in videoPlayer_control.yml for that player only. As everywhere else, the most specific setting wins.
| Option | Default | Description |
|---|---|---|
|
| The Show/Hide Playlist button on the left of the header bar. When set to |
|
| The Manage Playlists button on the right of the header bar. When set to |
|
| The search box above the playlist. |
|
| The sort control of the playlist. |
|
| The switch that flips the playlist between the list and the cards layout. |
|
| The merge switch. When on, importing another playlist adds its videos to the current one instead of replacing it. |
|
| The loop switch that repeats the playlist from the top when the last video finishes. |
| The playlist-panel controls (search, sort, and the switches) also manage themselves: they hide automatically while the playlist is empty and appear as soon as it has content. The loop switch is extra careful — it only appears when every item in the list belongs to a series, because looping only makes sense for a complete series. Sort options that would do nothing (for example sorting by rating when no video is rated yet) are hidden as well. |
Playlist Options
The playlist: block controls the playlist panel that sits under each player.
| Option | Default | Description |
|---|---|---|
|
| Show the playlist panel. Turn it off for a plain single-video player. |
|
| Close the playlist panel automatically as soon as a video starts playing. |
|
| Allow picture-in-picture: a small floating video window that keeps playing while the viewer scrolls or switches tabs. |
|
| The starting layout of the playlist: |
|
| How many cards to show per row when the playlist is in cards mode. Each player can have its own value. |
Player Options (videoJS)
The videoJS: block controls the video engine itself: how a video starts, how fast it can play, and how poster (preview) images are made.
| Option | Default | Description |
|---|---|---|
|
| Start playing as soon as a video is loaded. |
|
| Let the browser fetch the video ahead of time so playback starts quickly. |
|
| Offer a speed menu on the player. |
|
| The speeds available in that menu ( |
The players.native block sets the behaviour of the player itself. Despite its name it is used for both video kinds — native files and YouTube videos play through the same settings. The most useful keys are shown below.
| Option | Default | Description |
|---|---|---|
|
| Play as soon as the video is ready. |
|
| Show the player’s control bar. |
|
| Make the player responsive so it fills the width of its container. |
|
| How eagerly to load the video: |
|
| On iPhones, play inside the page instead of forcing full screen. |
|
| The image shown before a video plays, when no other poster is available. |
|
| The order in which video file types are tried. Add more types (for example |
Automatic Poster Images
A poster is the still image shown before a video plays. For native videos, J1 VideoPlayer can create the poster for you by grabbing a frame from the start of the video. This is controlled by videoJS.poster.autoGenerate.
| Option | Default | Description |
|---|---|---|
|
| Turn automatic poster creation on or off. |
|
| Which second of the video to grab the frame from. If this is |
|
| A percentage of the video’s length to use as the capture point (used only when |
|
| The poster is shrunk to at most this many pixels wide (the shape is kept). |
|
| The image type to save: |
|
| Image quality from |
| For YouTube videos you never need this: the poster is fetched straight from YouTube’s own thumbnail service. |
Plugin Options
Video.js gains extra buttons through small plugins. J1 VideoPlayer ships a handful, switched on and off under videoJS.plugins:.
| Plugin | What it does |
|---|---|
| The playlist engine. |
| Adds skip forward and skip back buttons around the play button. |
| Adds next and previous buttons to jump between playlist items. |
| Adds zoom / rotate controls for the video image. |
| Keyboard shortcuts (for example the arrow keys to seek). Off by default. |
Per-Player Settings
The videoPlayer_control.yml file is where you actually create players. It holds a list of players, and each entry describes one player. Keys you do not set fall back to the global settings and then the defaults.
| Key | Description |
|---|---|
| Whether this player is built at all. |
| The player’s unique name (for example |
| A human-friendly label for the player. |
| A list of playlist files to load into this player on page load. A short file name is looked up in |
| Show or hide this player’s controls, for example |
| Any option from the sections above, applied to this player only. |
| Per-player |
A control file with one fully customised player looks like this:
settings:
players:
- player:
enabled: true
id: player_tiny_desk_concerts
description: NPR Tiny Desk Concerts
# hide the edit button for this player only
ui_elements:
edit_playlist_button: false
# this player gets its own speed menu
videoJS:
autoStart: true
playbackRates:
enabled: true
values: [ 0.5, 1, 1.5, 2 ]
playlist:
preload: [ tinydesk-concerts.json ]
cards:
perRow: 4The Player on the Page
You do not write the player’s HTML — J1 generates it from your configuration. Still, it helps to know the parts a viewer sees, because the settings above map onto them.
The Header Bar
Every player has a slim header bar with three slots:
- Show / Hide Playlist button (left)
-
Opens and closes the playlist panel. It is disabled and greyed out until a playlist is loaded.
- Title (centre)
-
A short label, for example the title of the running video.
- Manage Playlists button (right)
-
Opens the edit panel, where the viewer can add, import, export, or clear videos.
Either button can be hidden per player through the ui_elements keys show_playlist_button and edit_playlist_button (see UI Elements). The header keeps its three-slot layout even when a button is hidden, so the title always stays centred.
The Video Area
Below the header is the video itself. Before anything is loaded, a friendly placeholder (the VideoJS logo) is shown in its place.
The Playlist Panel
When opened, the playlist panel shows:
-
a search box to filter the list as you type;
-
a sort control to reorder the list;
-
a list / cards switch to change the layout;
-
a merge switch that decides whether importing adds to or replaces the list;
-
a loop switch to repeat the playlist (shown only for series);
-
the videos themselves, each with its poster, title, author, and a star rating.
Which of these appear depends on the matching options in the ui_elements: block, and the controls hide themselves while the playlist is empty.
The Edit Panel
The edit panel is where content is managed. It offers:
-
a box to paste a video link (for example a YouTube URL) to add one video;
-
an Import control to load a ready-made playlist from the server;
-
Export Playlist to save the current playlist to a file;
-
Import Playlist to load a playlist from a file on the viewer’s computer;
-
Clear Playlist to empty the list.
Playlist Items
A playlist is simply a list of items, and each item is a small block of information about one video. When you write a playlist file by hand, or read one that was exported, this is the shape of each item.
Only videoId is truly required; every other field has a sensible default and can be left out.
| Field | Type | Description |
|---|---|---|
| text | Required. A unique id for this item. For YouTube this is usually the video’s id; for native videos any unique string works. |
| text | The video’s title, shown in the list. |
| text | The channel or author name. |
| text | A longer description. It is searchable. |
| text | A category label used for grouping and search. |
| list | A list of tag words, for example |
| text | The video’s MIME type. Defaults to |
| text | The address of the native video file. Leave empty for YouTube items. |
| text | The canonical link. For YouTube this is the YouTube URL; for native videos it is usually the same as |
| text | An optional link to a page with more information. |
| text | The preview image URL. For YouTube it is filled in automatically; for native videos it can be generated (see Automatic Poster Images). |
| number | The length of the video in seconds. |
| text | The publish date of the video. |
| number | An episode number, if the video is part of a series. |
| number | A series number. |
| number | A star rating from |
| number | The second the viewer last stopped at, so playback can resume there. |
| text | When the item was last watched (set automatically). |
| text | When the item was added (set automatically). |
| text | Always |
A single item in a playlist file looks like this:
{
"videoId": "abcXYZ12345",
"title": "Tiny Desk Concert",
"author": "NPR Music",
"description": "A short live set recorded at the office.",
"category": "music",
"tags": [ "live", "acoustic" ],
"type": "video/mp4",
"videoLink": "https://www.youtube.com/watch?v=abcXYZ12345",
"poster": "",
"duration": 920,
"rating": 0
}| A playlist file may be either a plain array of items ( |
Playlist and Preloading
Ready-made playlist files are ordinary .json files kept in the folder set by playlist_url_base. To have a player load one (or several) on page load, list the file names under that player’s playlist.preload key:
playlist:
preload: [ tinydesk-concerts.json, carpool-karaoke.json ]Preloading is safe to repeat. On every page load the module merges the file into the player’s playlist: it adds any videos that are not there yet and leaves everything else — including the viewer’s own additions, ratings, and watch positions — untouched. Nothing is ever duplicated or overwritten. Preloading only fills the list; it does not start playing on its own.
Methods
Most pages need no JavaScript at all — the configuration files already cover normal use. The methods below are for advanced users who want to build custom controls, load videos after the page has loaded, or read the player’s state. The module follows the same shape as Video.js. You get a player through a factory function, and then work with that player object.
The Module Factory
videoPlayer(id, options) is the main entry point. It creates the player for id the first time you call it and returns the existing one on later calls (this is called "create-or-get"). Options given for a player that already exists are ignored.
// create or fetch the player named 'player_1'
const vp = videoPlayer('player_1', options);| Function | Description |
|---|---|
| Create the player for |
| Return the player for |
| Return the registry object holding every live player, keyed by id. |
| The module’s version string. |
| A direct reference to the same registry |
| Older code may use |
A Player Instance
The object returned by the factory represents one player. It carries a few accessors and, most importantly, its playlistManager.
| Member | Description |
|---|---|
| The player’s id. |
| The options the player was created with. |
| The active player id used internally to scope elements. |
| The object that manages this player’s playlist (see below). |
| Close the playlist panel. |
| Close the edit panel. |
| Remove the player from the registry so its id can be created again. |
Working with Playlists
The playlist is managed by vp.playlistManager. Its methods are grouped below by what they do. Anywhere you see videoId, it is the videoId field of a playlist item.
Adding and Updating Videos
| Method | Description |
|---|---|
| Add a video to the playlist from an item object. |
| Create a playlist item early (from what is known at load time) and store it. |
| Fill in details that only arrive later — the real title, author, poster, or measured length. By default it only fills empty fields; pass |
| Set the star rating ( |
| Remember where the viewer stopped, so playback can resume. |
| Mark an item as watched now. |
| Update several fields of an item at once. |
Removing Videos
| Method | Description |
|---|---|
| Remove a single video from the playlist. |
| Remove every video from the playlist. |
Reading the Playlist
| Method | Description |
|---|---|
| Return the whole playlist as an array of items. |
| Return one item. |
| Return the saved resume position (in seconds) for an item. |
| Return the id of the video that follows the given one. |
Playing Videos
| Method | Description |
|---|---|
| Load and play the given video. |
| Load a video into the player (the lower-level call |
| Load the first item of the playlist automatically when the page reloads. |
Importing, Exporting, and Preloading
| Method | Description |
|---|---|
| Load a playlist file from a web address into the playlist. |
| Load a playlist from a file chosen on the viewer’s computer. |
| Save the current playlist to a |
| Save a backup copy of the current playlist to a file. |
| Merge one or more configured playlist files into the player on load. This is what the |
Searching and Sorting
| Method | Description |
|---|---|
| Build the search index for the current playlist. |
| Filter the playlist by a search term. |
| Clear the current search and show the whole list again. |
| Reorder the list, for example by |
Rendering the Panel
| Method | Description |
|---|---|
| Redraw the playlist panel to match the stored playlist. |
| Mark an item as the one currently playing (it is highlighted). |
| Remove the "currently playing" highlight from all items. |
Setup Methods
These are normally called by the adapter that starts the player. You rarely call them yourself.
| Method | Description |
|---|---|
| Hand the merged configuration to the playlist manager. |
| Tell the manager which player it belongs to, so it uses the right storage and the right HTML elements. |
Notes on Implementation
This section explains a few design choices. You do not need them for daily use, but they help when something behaves unexpectedly on a page with several players.
One Instance Per Player
The module is built the same way as Video.js. Calling videoPlayer(id) returns a separate instance for each id, kept in a shared registry. Each instance owns its own state, its own playlist manager, and its own event handlers. There is no hidden "default" player that everything shares — that older design caused several players to fight over one set of settings, so it was removed.
Per-Player Settings Win
Whenever a player needs one of its videoJS settings, it looks in a fixed order: first the options handed to its own factory call (that is, the merged per-player configuration), then the page-global options, and only then an internal fallback. In short: the setting closest to the player wins. This is why two players on one page can autostart differently, offer different speed menus, or run different plugins.
Each Player Has Its Own Storage
Because every player keeps its playlist in the browser’s local storage, the module gives each player its own storage name by adding the player id to it (for example playlist_player_1). This is why a video added to one player never appears in another. The same scoping applies to the small UI preferences — whether the playlist was last shown as a list or as cards, the merge switch, the loop switch, and the last search mode are all remembered per player.
Native and YouTube Share One Path
Both native and YouTube videos play through the same Video.js player. The module looks at the item’s link to decide which one it is: a YouTube link is recognised and played through YouTube; anything else is treated as a native file and loaded from its src. Posters follow the same rule — YouTube posters come from YouTube, native posters are generated from the video. The player settings for both kinds come from the players.native block.
The Cards View Is a Web Component
The cards layout of the playlist is rendered by a small, modern web component (built with Lit). It draws each video as a card and updates only the card that changed — rating one video or deleting one entry never redraws the whole grid. It renders into the normal page (light DOM), so all existing styles and click handling keep working. You never interact with it directly; the mode switch and playlist.type control it for you.
Preloading Is Non-Destructive
Preloading always merges. It never overwrites the viewer’s existing list, and running it again on the next reload never creates duplicates. This is why it is safe to keep a preload list in your configuration permanently.
Examples
The examples below are complete, working configurations. Copy one into your videoPlayer_control.yml and adjust the ids and playlist file names.
| J1 VideoPlayer is mobile-friendly. On touch devices the player and its buttons respond to taps, and the layout follows the width of the page so it looks right on phones and tablets. |
Player With a Preloaded Playlist
This is the simplest useful setup: a single player that loads a ready-made playlist file on page load and shows it as a grid of cards, four per row.
settings:
players:
# --------------------------------------------------------------------------
# Tiny Desk Concerts
#
- player:
enabled: true
id: player_tiny_desk_concerts
description: NPR Tiny Desk Concerts
ui_elements:
edit_playlist_button: false
videoJS:
autoStart: true
playbackRates:
enabled: true
values: [ 0.5, 1, 1.5, 2 ]
plugins:
playlist:
enabled: true
playlist:
preload: [ tinydesk-concerts.json ]
cards:
perRow: 4Tiny Desk Concerts is a popular, award-winning video series featuring live music performances at an actual office desk, hosted by NPR Music. Started in 2008 by radio host Bob Boilen and producer Stephen Thompson. The show has grown from a small platform for folk and indie artists into a worldwide pop-culture hit.
Multiple Players on a Page
Each player has its own id, its own preloaded playlist, and its own card layout. They do not share anything.
settings:
players:
- player:
enabled: true
id: player_1
description: NPR Tiny Desk Concerts
playlist:
preload: [ tinydesk-concerts.json ]
cards:
perRow: 4
- player:
enabled: true
id: player_2
description: Carpool Karaoke
playlist:
preload: [ carpool-karaoke.json ]
cards:
perRow: 3Hiding a Header Button
A "read-only" player: the viewer can watch and browse the preloaded playlist, but the Manage Playlists button is hidden, so the playlist cannot be changed from the page. The player also gets its own, shorter speed menu.
settings:
players:
- player:
enabled: true
id: player_tiny_desk_concerts
description: NPR Tiny Desk Concerts
ui_elements:
edit_playlist_button: false
videoJS:
autoStart: true
playbackRates:
enabled: true
values: [ 0.5, 1, 1.5, 2 ]
playlist:
preload: [ tinydesk-concerts.json ]
cards:
perRow: 4A Small Playlist File
A playlist file that mixes one YouTube video and one native video. Save it in your playlist_url_base folder and reference it from a preload list.
[
{
"videoId": "abcXYZ12345",
"title": "Live at the Tiny Desk",
"author": "NPR Music",
"description": "A short acoustic set.",
"category": "music",
"tags": [ "live", "acoustic" ],
"videoLink": "https://www.youtube.com/watch?v=abcXYZ12345",
"duration": 920,
"rating": 0
},
{
"videoId": "promo-clip-01",
"title": "Product Tour",
"author": "Our Team",
"description": "A self-hosted introduction video.",
"category": "howto",
"tags": [ "intro" ],
"type": "video/mp4",
"src": "/assets/video/product-tour.mp4",
"videoLink": "/assets/video/product-tour.mp4",
"duration": 140,
"rating": 0
}
]Adding a Video From JavaScript
For a custom button, you can add and play a video yourself. First get the player, then use its playlist manager.
// get the running player named 'player_1'
const vp = videoPlayer.getPlayer('player_1');
if (vp) {
// add a video to the playlist
vp.playlistManager.addEntry({
videoId: 'abcXYZ12345',
title: 'Live at the Tiny Desk',
author: 'NPR Music',
videoLink: 'https://www.youtube.com/watch?v=abcXYZ12345'
});
// then play it
vp.playlistManager.playEntry('abcXYZ12345');
}