From ed59531f7861f88f0c088966572afb2a342aa2d6 Mon Sep 17 00:00:00 2001 From: mister-ben Date: Thu, 3 Nov 2016 19:39:09 +0000 Subject: [PATCH] fix: Suppress Infinity duration on Android Chrome before playback (#3476) HTML5 tech will return NaN instead of Infinity if playback has not started. Fires a durationupdate event once the reported duration can be believed if the duration is still Infinity, so controls can update. Fixes #3079. --- src/js/tech/html5.js | 25 ++++++++++++++++++++++++- test/unit/tech/html5.test.js | 19 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/js/tech/html5.js b/src/js/tech/html5.js index 969dd62c3..368aa40b6 100644 --- a/src/js/tech/html5.js +++ b/src/js/tech/html5.js @@ -428,7 +428,30 @@ class Html5 extends Tech { * @return {Number} */ duration() { - return this.el_.duration || 0; + // Android Chrome will report duration as Infinity for VOD HLS until after + // playback has started, which triggers the live display erroneously. + // Return NaN if playback has not started and trigger a durationupdate once + // the duration can be reliably known. + if (this.el_.duration === Infinity && + browser.IS_ANDROID && browser.IS_CHROME) { + if (this.el_.currentTime === 0) { + // Wait for the first `timeupdate` with currentTime > 0 - there may be + // several with 0 + const checkProgress = () => { + if (this.el_.currentTime > 0) { + // Trigger durationchange for genuinely live video + if (this.el_.duration === Infinity) { + this.trigger('durationchange'); + } + this.off(this.player_, 'timeupdate', checkProgress); + } + }; + + this.on(this.player_, 'timeupdate', checkProgress); + return NaN; + } + } + return this.el_.duration || NaN; } /** diff --git a/test/unit/tech/html5.test.js b/test/unit/tech/html5.test.js index 270d879f7..01644205b 100644 --- a/test/unit/tech/html5.test.js +++ b/test/unit/tech/html5.test.js @@ -562,3 +562,22 @@ QUnit.test('Exception in play promise should be caught', function() { tech.el_ = oldEl; }); + +test('When Android Chrome reports Infinity duration with currentTime 0, return NaN', function() { + const oldIsAndroid = browser.IS_ANDROID; + const oldIsChrome = browser.IS_CHROME; + const oldEl = tech.el_; + + browser.IS_ANDROID = true; + browser.IS_CHROME = true; + + tech.el_ = { + duration: Infinity, + currentTime: 0 + }; + ok(Number.isNaN(tech.duration()), 'returned NaN with currentTime 0'); + + browser.IS_ANDROID = oldIsAndroid; + browser.IS_CHROME = oldIsChrome; + tech.el_ = oldEl; +});