Permalink
Browse files

feat: support seeking during live playback via liveui option (#5511)

When liveui is enabled, allow seeking during the live window, add button that allows you to seek to the live edge and that indicates whether you are at the live edge or not.
  • Loading branch information...
BrandonOCasey authored and gkatsev committed Dec 3, 2018
1 parent db1369a commit 2974ad3db727985edcf58599f50712459adf9f32

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Video.js Sandbox</title>
<link href="../dist/video-js.css" rel="stylesheet" type="text/css">
<script src="../dist/video.js"></script>
</head>
<body>
<div style="background-color:#eee; border: 1px solid #777; padding: 10px; margin-bottom: 20px; font-size: .8em; line-height: 1.5em; font-family: Verdana, sans-serif;">
<p>You can use /sandbox/ for writing and testing your own code. Nothing in /sandbox/ will get checked into the repo, except files that end in .example (so don't edit or add those files). To get started make a copy of index.html.example and rename it to index.html.</p>
<pre>cp sandbox/index.html.example sandbox/index.html</pre>
<pre>npm run start</pre>
<pre>open http://localhost:9999/sandbox/index.html</pre>
</div>

<video-js id="vid1" controls preload="auto" width="640" height="264">
<source src="https://akamai-axtest.akamaized.net/routes/lapd-v1-acceptance/www_c4/Manifest.m3u8" type="application/x-mpegURL">
<p class="vjs-no-js">To view this video please enable JavaScript, and consider upgrading to a web browser that <a href="http://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a></p>
</video-js>

<script>
// fake a livestream for easy testing
var vid = document.getElementById('vid1');

var player = videojs(vid);
</script>

</body>
</html>
@@ -0,0 +1,34 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Video.js Sandbox</title>
<link href="../dist/video-js.css" rel="stylesheet" type="text/css">
<script src="../dist/video.js"></script>
</head>
<body>
<div style="background-color:#eee; border: 1px solid #777; padding: 10px; margin-bottom: 20px; font-size: .8em; line-height: 1.5em; font-family: Verdana, sans-serif;">
<p>You can use /sandbox/ for writing and testing your own code. Nothing in /sandbox/ will get checked into the repo, except files that end in .example (so don't edit or add those files). To get started make a copy of index.html.example and rename it to index.html.</p>
<pre>cp sandbox/index.html.example sandbox/index.html</pre>
<pre>npm run start</pre>
<pre>open http://localhost:9999/sandbox/index.html</pre>
</div>

<video-js id="vid1" controls preload="auto" width="640" height="264">
<source src="https://akamai-axtest.akamaized.net/routes/lapd-v1-acceptance/www_c4/Manifest.m3u8" type="application/x-mpegURL">
<p class="vjs-no-js">To view this video please enable JavaScript, and consider upgrading to a web browser that <a href="http://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a></p>
</video-js>

<script>
// fake a livestream for easy testing
var vid = document.getElementById('vid1');
var liveui = true

if (videojs.browser.IS_ANDROID) {
liveui = false;
}
var player = videojs(vid, {liveui: liveui});
</script>

</body>
</html>
@@ -1,5 +1,4 @@
// We are assuming there is no progress bar and using the live display
// to fill in the middle space. Live+DVR will need to adjust this.
// css for the old live ui, assumes that the progress bar is hidden
.video-js .vjs-live-control {
@include display-flex(flex-start);
@include flex(auto);
@@ -12,3 +11,53 @@
width: auto;
text-align: left;
}

// hide the LiveDisplay when not live or when
// the new liveui is in use
.video-js:not(.vjs-live) .vjs-live-control,
.video-js.vjs-liveui .vjs-live-control {
display: none;
}

// css for the new live ui below
.video-js .vjs-seek-to-live-control {
cursor: pointer;
@include flex(none);
display: inline-flex;
height: 100%;
padding-left: 0.5em;
padding-right: 0.5em;
font-size: 1em;
line-height: 3em;
width: auto;
min-width: 4em;
}

.vjs-no-flex .vjs-seek-to-live-control {
display: table-cell;
width: auto;
text-align: left;
}

// hide the SeekToLive button when not live and
// when the liveui is not in use
.video-js.vjs-live:not(.vjs-liveui) .vjs-seek-to-live-control,
.video-js:not(.vjs-live) .vjs-seek-to-live-control {
display: none;
}

// only show as a pointer when we will seek to live edge
.vjs-seek-to-live-control.vjs-control.vjs-at-live-edge {
cursor: auto;
}

.vjs-seek-to-live-control .vjs-seek-to-live-circle {
margin-right: 0.5em;
@extend .vjs-icon-circle;
color: #888;
}

// make the live circle red when at the live edge
.vjs-seek-to-live-control.vjs-control.vjs-at-live-edge .vjs-seek-to-live-circle {
color: red;
}
@@ -17,6 +17,10 @@
display: none;
}

.vjs-liveui .vjs-progress-control {
@include display-flex(center);
}

.vjs-no-flex .vjs-progress-control {
width: auto;
}
@@ -10,6 +10,7 @@ import './time-controls/duration-display.js';
import './time-controls/time-divider.js';
import './time-controls/remaining-time-display.js';
import './live-display.js';
import './seek-to-live.js';
import './progress-control/progress-control.js';
import './fullscreen-toggle.js';
import './volume-panel.js';
@@ -58,6 +59,7 @@ ControlBar.prototype.options_ = {
'durationDisplay',
'progressControl',
'liveDisplay',
'seekToLive',
'remainingTimeDisplay',
'customControlSpacer',
'playbackRateMenuButton',
@@ -54,8 +54,9 @@ class LoadProgressBar extends Component {
* @listens Player#progress
*/
update(event) {
const liveTracker = this.player_.liveTracker;
const buffered = this.player_.buffered();
const duration = this.player_.duration();
const duration = liveTracker.isLive() ? liveTracker.seekableEnd() : this.player_.duration();
const bufferedEnd = this.player_.bufferedEnd();
const children = this.partEls_;

@@ -3,7 +3,6 @@
*/
import Component from '../../component.js';
import * as Fn from '../../utils/fn.js';
import formatTime from '../../utils/format-time.js';

import './time-tooltip';

@@ -55,18 +54,10 @@ class MouseTimeDisplay extends Component {
* from the left edge of the {@link SeekBar}
*/
update(seekBarRect, seekBarPoint) {
const time = seekBarPoint * this.player_.duration();

// If there is an existing rAF ID, cancel it so we don't over-queue.
if (this.rafId_) {
this.cancelAnimationFrame(this.rafId_);
}

this.rafId_ = this.requestAnimationFrame(() => {
const duration = this.player_.duration();
const content = formatTime(seekBarPoint * duration, duration);

this.getChild('timeTooltip').updateTime(seekBarRect, seekBarPoint, time, () => {
this.el_.style.left = `${seekBarRect.width * seekBarPoint}px`;
this.getChild('timeTooltip').update(seekBarRect, seekBarPoint, content);
});
}
}
@@ -3,7 +3,6 @@
*/
import Component from '../../component.js';
import {IS_IOS, IS_ANDROID} from '../../utils/browser.js';
import formatTime from '../../utils/format-time.js';

import './time-tooltip';

@@ -40,24 +39,17 @@ class PlayProgressBar extends Component {
* from the left edge of the {@link SeekBar}
*/
update(seekBarRect, seekBarPoint) {
const timeTooltip = this.getChild('timeTooltip');

// If there is an existing rAF ID, cancel it so we don't over-queue.
if (this.rafId_) {
this.cancelAnimationFrame(this.rafId_);
if (!timeTooltip) {
return;
}

this.rafId_ = this.requestAnimationFrame(() => {
const time = (this.player_.scrubbing()) ?
this.player_.getCache().currentTime :
this.player_.currentTime();
const time = (this.player_.scrubbing()) ?
this.player_.getCache().currentTime :
this.player_.currentTime();

const content = formatTime(time, this.player_.duration());
const timeTooltip = this.getChild('timeTooltip');

if (timeTooltip) {
timeTooltip.update(seekBarRect, seekBarPoint, content);
}
});
timeTooltip.updateTime(seekBarRect, seekBarPoint, time);
}
}

Oops, something went wrong.

0 comments on commit 2974ad3

Please sign in to comment.