diff --git a/lib/text/text_utils.js b/lib/text/text_utils.js index c4770d795b..eebb7a8871 100644 --- a/lib/text/text_utils.js +++ b/lib/text/text_utils.js @@ -148,7 +148,7 @@ shaka.text.Utils = class { */ static getCuesToFlatten(cues, parentCue) { const result = []; - for (const cue of cues) { + for (const cue of shaka.text.Utils.removeDuplicates(cues)) { if (cue.isContainer) { // Recurse to find the actual text payload cues. result.push(...shaka.text.Utils.getCuesToFlatten(cue.nestedCues, cue)); @@ -162,4 +162,20 @@ shaka.text.Utils = class { } return result; } + + /** + * @param {!Array.} cues + * @return {!Array.} + */ + static removeDuplicates(cues) { + const uniqueCues = []; + for (const cue of cues) { + const isValid = !uniqueCues.some( + (existingCue) => shaka.text.Cue.equal(cue, existingCue)); + if (isValid) { + uniqueCues.push(cue); + } + } + return uniqueCues; + } }; diff --git a/lib/text/ui_text_displayer.js b/lib/text/ui_text_displayer.js index 7b33c48416..1ac76291c3 100644 --- a/lib/text/ui_text_displayer.js +++ b/lib/text/ui_text_displayer.js @@ -11,6 +11,7 @@ goog.require('goog.asserts'); goog.require('shaka.Deprecate'); goog.require('shaka.text.Cue'); goog.require('shaka.text.CueRegion'); +goog.require('shaka.text.Utils'); goog.require('shaka.util.Dom'); goog.require('shaka.util.EventManager'); goog.require('shaka.util.Timer'); @@ -156,7 +157,7 @@ shaka.text.UITextDisplayer = class { // list growing during the comparisons for duplicate cues. // See: https://github.com/shaka-project/shaka-player/issues/3018 const cuesList = [...this.cues_]; - for (const cue of cues) { + for (const cue of shaka.text.Utils.removeDuplicates(cues)) { // When a VTT cue spans a segment boundary, the cue will be duplicated // into two segments. // To avoid displaying duplicate cues, if the current cue list already diff --git a/test/text/ui_text_displayer_unit.js b/test/text/ui_text_displayer_unit.js index ddddf3b00d..b8262374c5 100644 --- a/test/text/ui_text_displayer_unit.js +++ b/test/text/ui_text_displayer_unit.js @@ -412,8 +412,8 @@ describe('UITextDisplayer', () => { // be created. const cues = [ new shaka.text.Cue(0, 100, ''), - new shaka.text.Cue(0, 100, ''), - new shaka.text.Cue(0, 100, ''), + new shaka.text.Cue(0, 200, ''), + new shaka.text.Cue(0, 300, ''), ]; for (const cue of cues) { cue.displayAlign = shaka.text.Cue.displayAlign.CENTER; @@ -567,8 +567,8 @@ describe('UITextDisplayer', () => { // be created. const firstBatchOfCues = [ new shaka.text.Cue(0, 100, ''), - new shaka.text.Cue(0, 100, ''), - new shaka.text.Cue(0, 100, ''), + new shaka.text.Cue(0, 200, ''), + new shaka.text.Cue(0, 300, ''), ]; for (const cue of firstBatchOfCues) { cue.displayAlign = shaka.text.Cue.displayAlign.CENTER; @@ -578,8 +578,8 @@ describe('UITextDisplayer', () => { // Another batch for the other region const secondBatchOfCues = [ new shaka.text.Cue(0, 100, ''), - new shaka.text.Cue(0, 100, ''), - new shaka.text.Cue(0, 100, ''), + new shaka.text.Cue(0, 200, ''), + new shaka.text.Cue(0, 300, ''), ]; for (const cue of secondBatchOfCues) { cue.displayAlign = shaka.text.Cue.displayAlign.CENTER;