Implementing Chapter Markers in a Day

In November JW Player launched a new feature in 6.7 for chapter markers within the timeline. Using a simple file to define the location of the marker and a title that appears on hover, the timeline will show little dots when those markers are. For long form content like music concerts this was a highly desired feature since it allows viewers, mostly students in the ensemble, to jump right to the piece they want.

With 300 some videos now online it wasn’t something we could just make individual files for one at a time. Luckily we had already been doing something like chapters using JW’s seek API. However that seek scrip was offset in SECONDS, and the new markers required HH:MM:SS:MMM.

Step one was to create an ExpressionEngine plugin that would convert total seconds to HH:MM:SS for the older entries. A quick search of
devot-ee.com EE add-on repository found Video Length by Michael Leigeber:

http://devot-ee.com/add-ons/video-length

{exp:video_length seconds="125"} outputs 02:05

Step two involved improving workflow. When we make chapter markers in Final Cut we get timecode, then have to do math to convert to seconds and place that number into a field in ExpressionEngine. That’s a pain, and now redundant. So first I created a new Matrix column to accept the new HH:MM:SS format. When students complete the form they now just copy and paste that timecode, no math screwups.

Creating new fieldWhat a live entry looks like with field

However the Chapters function still needs total seconds from the beginning. So I made a 3 line plugin that did the math:

{exp:timetoseconds:convert time=“5:00”} would output 300

On the player page the Chapters drop down code then looks like this:

{ondemand_chapters}
	Check if either are filled out.
	{if chapter_location OR chapter_location_human}
	<li>
	<a href="#" onclick=“jwplayer().seek(
		First see if we put the time in the easy way:
		{if chapter_location_human}
			Do the math to changes to seconds:
			{exp:timetoseconds:convert time=“{chapter_location_human}"}
		{if:else}
			This will already have the math done.
			{chapter_location}
		{/if}
	);”>
	Use the row count for track number, then the name of the piece from the Matrix field.
	{row_count} {name_of_piece}
	</a>
	</li>
	{/if}
{/ondemand_chapters}
<br>

On Demand Player Page

With the old chapter markers system ready to go I moved to implementing the new JW Chapters feature. First step was making the webvtt file as a template and referencing that location in the JW setup script. This was a bit tricky since JW requires the .vtt extension and you can’t make a template in EE have that kind of extension and have the entries loop know what entry to load. The trick was to still put the entry ID in the URL, and tell the entries loop which segment to look for. The tag and template will ignore everything else after. The link was then:

The Tag:

{entry_id_path=media/web}/whatever.vtt

Outputted:

/media/webvtt/1234/chapters.vtt

And matching with EE’s segment variables:

{segment_1} = media

{segment_2} = webvtt

{segment_3} = 1234

{segment_4} = chapters.vtt

Then in the webvtt template use this channel entries loop:

{exp:channel:entries channel="live" entry_id=“{segment_3}"}

Within the webvtt template the syntax is straightforward:

Chapter X

HH:MM:SS:MMM —> HH:MM:SS:MMM

Name that Appears on Hover

Using existing fields and the converter plugins the template looks like this:

Track listing loop

{ondemand_chapters}
	Chapter {row_count}
	{if chapter_location_human}
		{chapter_location_human}.000 --> {chapter_location_human}.999
	{if:else}
		{exp:video_length seconds="{chapter_location}"}.000 --> {exp:video_length seconds=“{chapter_location}"}.999
	{/if}
	{name_of_piece} by {name_of_composer}
{/ondemand_chapters}

There are a few extra plugins I wrap this template in so it filters out weird things like HTML, converts special characters, line breaks and extra spaces. Omitted above just for clarity.

Leave a Reply

Your email address will not be published. Required fields are marked *