My aim is to add buttons below my player that jump to specific moments in the video.
There's a demo example that does basically what I want: https://flowplayer.com/demos/using-the-api — however it is based on the cloud player implementation of Flowplayer, and I'm using the Javascript API to embed my player. The basic relevant script is this:
flowplayer.cloud.then(function () {
var api = flowplayer("#player")
seek3.onclick = function() {
api.fas.seek_to('00:01:01:11');
}
});
An example I found of creating buttons using the Javascript API is as follows:
flowplayer(function(opts, root, api) {
// small jQuery-compatible utility built inside the player
var $ = flowplayer.mq;
// render a custom button when the player is mounted
api.on('mount', function() {
var btn = $('<button>').txt('Test Button').on('click', function() {
api.toggleMute();
});
$('.fp-controls', root).append(btn);
});
});
That works fine with my player. When I try to merge the two approaches, though, I fail. Here is the broken code:
flowplayer(function(opts, root, api) {
var api = flowplayer("#flowplayer");
seek3.onclick = function() {
api.fas.seek_to('00:01:01:11');
}
});
I tried also as alternatives
document.getElementById('seek3').onclick = function()
And
$('#seek1').onclick = function() {
(preceded by the additional line of code borrowed from the working example):
var $ = flowplayer.mq;
but with every variation I keep getting the following error: "Uncaught TypeError: Cannot set property 'onclick' of null".
Any help would be much appreciated. I've found the Flowplayer documentation really difficult to use, since in search results it's often hard to even tell which version of the player is being referenced. I would really like to find some basic info about interacting with the API in addition to solving this particular problem.
For anyone else who might be having difficulties interacting with the API, Flowplayer kindly posted a new demo example -- with similar functionality as in the cloudplayer demo, but this one for the javascript player: https://codepen.io/team/flowplayer/pen/KOzWOK
var api = flowplayer("#player",
{ src : "//edge.flowplayer.org/drive.m3u8"
, autoplay : false
, token : "eyJraWQiOiJqOEF6djg5NlJMMWIiLCJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NiJ9.eyJjIjoie1wiYWNsXCI6NixcImlkXCI6XCJqOEF6djg5NlJMMWJcIixcImRvbWFpblwiOltcIm5ncm9rLmlvXCJdfSIsImlzcyI6IkZsb3dwbGF5ZXIifQ.UtJliSh4IcIKs71PVzXWdIrJJ8-1_KRK0hKd7OKp5EJhAdpZStuYbbU4bgDs--C6Gak6OBrb-xQBh6sd4dyrlA"
, muted : true
})
/**
* helper function to seek if possible or
* tell the player to seek when possible
*
* btn {HTMLElement}
* seconds {Number}
*/
function chapter (btn, seconds) {
btn.onclick = function () {
// player is preload=none so we must tell
// the player to seek when it is possible
if (api.readyState == 0) api.setOpts({start_time: seconds})
// player has already started loading content
if (api.readyState > 0) api.currentTime = seconds
// attempt to play content
api.togglePlay(true)
}
}
// bind the buttons to times
chapter(seek1, 20)
chapter(seek2, 45)
chapter(seek3, 60)
My working version includes the following variations on the JS code:
/**
* helper function to seek if possible or
* tell the player to seek when possible
*
* seconds {Number}
*/
function seek_to_cue (seconds) {
//alert('bingo?'); //tft
// player is preload=none so we must tell the player to seek when it is possible
if (api.readyState == 0) {
api.setOpts({start_time: seconds});
}
// player has already started loading content
if (api.readyState > 0) {
api.currentTime = seconds;
}
// attempt to play content
api.togglePlay(true);
}
and in my PHP code which includes the JS player call:
$button_actions .= 'document.getElementById("'.$button_id.'").addEventListener("click", function(){ seek_to_cue('.$start_time_seconds.'); });';