From ecfd3cf38528c020732dd902444422b5e3d443f1 Mon Sep 17 00:00:00 2001 From: dwithana Date: Tue, 5 Mar 2024 16:59:42 -0500 Subject: [PATCH 1/4] Remove duplicated caption overlays in iPads --- src/components/MediaPlayer/MediaPlayer.js | 5 +++-- src/components/MediaPlayer/VideoJS/VideoJSPlayer.js | 5 ++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/MediaPlayer/MediaPlayer.js b/src/components/MediaPlayer/MediaPlayer.js index 8dd1006b..78c1dc77 100644 --- a/src/components/MediaPlayer/MediaPlayer.js +++ b/src/components/MediaPlayer/MediaPlayer.js @@ -343,9 +343,9 @@ const MediaPlayer = ({ enableFileDownload = false, enablePIP = false }) => { sources: isMultiSource ? playerConfig.sources[srcIndex] : playerConfig.sources, - // Enable native text track functionality in iPhones and iPads when not using HLS streams + // Enable native text track functionality in iPhones and iPads html5: { - nativeTextTracks: IS_MOBILE && !isStream && !IS_ANDROID + nativeTextTracks: IS_MOBILE && !IS_ANDROID }, // Setting this option helps to override VideoJS's default 'keydown' event handler, whenever // the focus is on a native VideoJS control icon (e.g. play toggle). @@ -464,6 +464,7 @@ const MediaPlayer = ({ enableFileDownload = false, enablePIP = false }) => { trackScrubberRef={trackScrubberRef} scrubberTooltipRef={timeToolRef} tracks={playerConfig.tracks} + isStream={isStream} {...videoJsOptions} /> diff --git a/src/components/MediaPlayer/VideoJS/VideoJSPlayer.js b/src/components/MediaPlayer/VideoJS/VideoJSPlayer.js index 00700237..d555a942 100644 --- a/src/components/MediaPlayer/VideoJS/VideoJSPlayer.js +++ b/src/components/MediaPlayer/VideoJS/VideoJSPlayer.js @@ -39,6 +39,7 @@ function VideoJSPlayer({ trackScrubberRef, scrubberTooltipRef, tracks, + isStream, ...videoJSOptions }) { const playerState = usePlayerState(); @@ -622,7 +623,8 @@ function VideoJSPlayer({ onTouchStart={saveTouchStartCoords} onTouchEnd={mobilePlayToggle} > - {tracks?.length > 0 && ( + {/* Omit building tracks for mobile devices when using HLS stream media */} + {tracks?.length > 0 && (IS_MOBILE && !IS_ANDROID && !isStream) && ( tracks.map(t => Date: Wed, 6 Mar 2024 16:50:38 -0500 Subject: [PATCH 2/4] Only use IIIF manifest captions, remove HLS caption filters --- src/components/MediaPlayer/MediaPlayer.js | 6 +-- .../MediaPlayer/VideoJS/VideoJSPlayer.js | 21 ++++----- src/services/iiif-parser.js | 11 +---- src/services/iiif-parser.test.js | 44 ------------------- 4 files changed, 13 insertions(+), 69 deletions(-) diff --git a/src/components/MediaPlayer/MediaPlayer.js b/src/components/MediaPlayer/MediaPlayer.js index 78c1dc77..080a7f03 100644 --- a/src/components/MediaPlayer/MediaPlayer.js +++ b/src/components/MediaPlayer/MediaPlayer.js @@ -37,7 +37,6 @@ const MediaPlayer = ({ enableFileDownload = false, enablePIP = false }) => { const [isMultiCanvased, setIsMultiCanvased] = React.useState(false); const [lastCanvasIndex, setLastCanvasIndex] = React.useState(0); const [isVideo, setIsVideo] = React.useState(); - const [isStream, setIsStream] = React.useState(); const { canvasIndex, @@ -132,14 +131,12 @@ const MediaPlayer = ({ enableFileDownload = false, enablePIP = false }) => { mediaType, canvas, error, - isHLS } = getMediaInfo({ manifest, canvasIndex: canvasId, srcIndex, }); setIsVideo(mediaType === 'video'); - setIsStream(isHLS); manifestDispatch({ canvasTargets, type: 'canvasTargets' }); manifestDispatch({ canvasDuration: canvas.duration, @@ -345,7 +342,7 @@ const MediaPlayer = ({ enableFileDownload = false, enablePIP = false }) => { : playerConfig.sources, // Enable native text track functionality in iPhones and iPads html5: { - nativeTextTracks: IS_MOBILE && !IS_ANDROID + nativeTextTracks: (IS_MOBILE && !IS_ANDROID) }, // Setting this option helps to override VideoJS's default 'keydown' event handler, whenever // the focus is on a native VideoJS control icon (e.g. play toggle). @@ -464,7 +461,6 @@ const MediaPlayer = ({ enableFileDownload = false, enablePIP = false }) => { trackScrubberRef={trackScrubberRef} scrubberTooltipRef={timeToolRef} tracks={playerConfig.tracks} - isStream={isStream} {...videoJsOptions} /> diff --git a/src/components/MediaPlayer/VideoJS/VideoJSPlayer.js b/src/components/MediaPlayer/VideoJS/VideoJSPlayer.js index d555a942..f88cee5a 100644 --- a/src/components/MediaPlayer/VideoJS/VideoJSPlayer.js +++ b/src/components/MediaPlayer/VideoJS/VideoJSPlayer.js @@ -39,7 +39,6 @@ function VideoJSPlayer({ trackScrubberRef, scrubberTooltipRef, tracks, - isStream, ...videoJSOptions }) { const playerState = usePlayerState(); @@ -259,14 +258,17 @@ function VideoJSPlayer({ playerDispatch({ isEnded: false, type: 'setIsEnded' }); let textTracks = player.textTracks(); - // Filter the duplicated tracks by HLS manifest, these doesn't have a src attribute - let duplicatedTracks = textTracks.tracks_.filter(rt => rt.src === undefined); - // Remove the duplicated tracks from the captions/subtitles menu - if (tracks.length != textTracks.length && duplicatedTracks?.length > 0) { - for (let i = 0; i < duplicatedTracks.length; i++) { - player.textTracks().removeTrack(duplicatedTracks[i]); + /* + Filter the text track Video.js adds with an empty label and language + when nativeTextTracks are enabled for iPhones and iPads. + */ + textTracks.on('addtrack', () => { + for (let i = 0; i < textTracks.length; i++) { + if (textTracks[i].language === '' && textTracks[i].label === '') { + player.textTracks().removeTrack(textTracks[i]); + } } - } + }); // Turn captions on indicator via CSS on first load, when captions are ON by default player.textTracks().tracks_?.map((t) => { if (t.mode == 'showing') { @@ -624,7 +626,7 @@ function VideoJSPlayer({ onTouchEnd={mobilePlayToggle} > {/* Omit building tracks for mobile devices when using HLS stream media */} - {tracks?.length > 0 && (IS_MOBILE && !IS_ANDROID && !isStream) && ( + {tracks?.length > 0 && ( tracks.map(t => application/x-mpegURL or vnd.apple.mpegURL - */ - const isHLS = sources - .map(s => (/m3u8/i).test(s.src) || (/(application\/x-mpegURL)|(vnd.apple.mpegURL)/i).test(s.type)) - .every(f => f === true); - // Read supplementing resources fom annotations const supplementingRes = readAnnotations({ manifest, @@ -210,7 +202,6 @@ export function getMediaInfo({ manifest, canvasIndex, srcIndex = 0 }) { ...mediaInfo, error: null, mediaType, - isHLS, }; } } catch (error) { diff --git a/src/services/iiif-parser.test.js b/src/services/iiif-parser.test.js index 056f2299..e142e253 100644 --- a/src/services/iiif-parser.test.js +++ b/src/services/iiif-parser.test.js @@ -176,50 +176,6 @@ describe('iiif-parser', () => { expect(sources[2].selected).toBeTruthy(); }); - describe('identifies media as stream', () => { - it('with src ending .m3u8', () => { - const { isHLS } = iiifParser.getMediaInfo({ - manifest: singleSrcManifest, - canvasIndex: 1, - }); - expect(isHLS).toBeTruthy(); - }); - - it('with src media fragment with .m3u8', () => { - const { isHLS } = iiifParser.getMediaInfo({ - manifest: playlistManifest, - canvasIndex: 1, - }); - expect(isHLS).toBeTruthy(); - }); - - it('with media format as vnd.apple.mpegURL', () => { - const { isHLS } = iiifParser.getMediaInfo({ - manifest: singleSrcManifest, - canvasIndex: 0, - }); - expect(isHLS).toBeTruthy(); - }); - }); - - describe('identifies media as non-stream', () => { - it('with src ending .mp4', () => { - const { isHLS } = iiifParser.getMediaInfo({ - manifest: lunchroomManifest, - canvasIndex: 0, - }); - expect(isHLS).toBeFalsy(); - }); - - it('with media fragment with .mp4', () => { - const { isHLS } = iiifParser.getMediaInfo({ - manifest: playlistManifest, - canvasIndex: 2, - }); - expect(isHLS).toBeFalsy(); - }); - }); - it("selects the first source when quality 'auto' is not present", () => { const { sources } = iiifParser.getMediaInfo({ manifest: lunchroomManifest, From f8fa8a982b47b60a7af0c784ca4ba8be6208536f Mon Sep 17 00:00:00 2001 From: dwithana Date: Thu, 14 Mar 2024 10:24:02 -0400 Subject: [PATCH 3/4] Cleanup code --- src/components/MediaPlayer/MediaPlayer.js | 2 +- src/components/MediaPlayer/VideoJS/VideoJSPlayer.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/MediaPlayer/MediaPlayer.js b/src/components/MediaPlayer/MediaPlayer.js index 080a7f03..87c7d1d6 100644 --- a/src/components/MediaPlayer/MediaPlayer.js +++ b/src/components/MediaPlayer/MediaPlayer.js @@ -342,7 +342,7 @@ const MediaPlayer = ({ enableFileDownload = false, enablePIP = false }) => { : playerConfig.sources, // Enable native text track functionality in iPhones and iPads html5: { - nativeTextTracks: (IS_MOBILE && !IS_ANDROID) + nativeTextTracks: IS_MOBILE && !IS_ANDROID }, // Setting this option helps to override VideoJS's default 'keydown' event handler, whenever // the focus is on a native VideoJS control icon (e.g. play toggle). diff --git a/src/components/MediaPlayer/VideoJS/VideoJSPlayer.js b/src/components/MediaPlayer/VideoJS/VideoJSPlayer.js index f88cee5a..f82c6812 100644 --- a/src/components/MediaPlayer/VideoJS/VideoJSPlayer.js +++ b/src/components/MediaPlayer/VideoJS/VideoJSPlayer.js @@ -261,6 +261,8 @@ function VideoJSPlayer({ /* Filter the text track Video.js adds with an empty label and language when nativeTextTracks are enabled for iPhones and iPads. + Related links, Video.js => https://github.com/videojs/video.js/issues/2808 and + in Apple => https://developer.apple.com/library/archive/qa/qa1801/_index.html */ textTracks.on('addtrack', () => { for (let i = 0; i < textTracks.length; i++) { @@ -625,7 +627,6 @@ function VideoJSPlayer({ onTouchStart={saveTouchStartCoords} onTouchEnd={mobilePlayToggle} > - {/* Omit building tracks for mobile devices when using HLS stream media */} {tracks?.length > 0 && ( tracks.map(t => Date: Thu, 14 Mar 2024 15:50:37 -0400 Subject: [PATCH 4/4] Fix caption building for mobile devices --- .../MediaPlayer/VideoJS/VideoJSPlayer.js | 49 ++++++++++++++++--- src/services/utility-helpers.js | 2 +- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/src/components/MediaPlayer/VideoJS/VideoJSPlayer.js b/src/components/MediaPlayer/VideoJS/VideoJSPlayer.js index f82c6812..d5408b34 100644 --- a/src/components/MediaPlayer/VideoJS/VideoJSPlayer.js +++ b/src/components/MediaPlayer/VideoJS/VideoJSPlayer.js @@ -264,13 +264,22 @@ function VideoJSPlayer({ Related links, Video.js => https://github.com/videojs/video.js/issues/2808 and in Apple => https://developer.apple.com/library/archive/qa/qa1801/_index.html */ - textTracks.on('addtrack', () => { - for (let i = 0; i < textTracks.length; i++) { - if (textTracks[i].language === '' && textTracks[i].label === '') { - player.textTracks().removeTrack(textTracks[i]); + if (IS_MOBILE && !IS_ANDROID) { + textTracks.on('addtrack', () => { + for (let i = 0; i < textTracks.length; i++) { + if (textTracks[i].language === '' && textTracks[i].label === '') { + player.textTracks().removeTrack(textTracks[i]); + /* + Turn off the consecutive `textTrack.change` event, + which turns off default captions in the controls + */ + textTracks.off('change'); + } + if (i == 0) { textTracks[i].mode = 'showing'; } } - } - }); + }); + } + // Turn captions on indicator via CSS on first load, when captions are ON by default player.textTracks().tracks_?.map((t) => { if (t.mode == 'showing') { @@ -614,6 +623,30 @@ function VideoJSPlayer({ } else { videoClass = "video-js vjs-big-play-centered"; }; + const buildTrack = (t, index) => { + if (index == 0) { + return ( + + ); + } else { + return ( + + ); + } + }; return ( @@ -628,14 +661,14 @@ function VideoJSPlayer({ onTouchEnd={mobilePlayToggle} > {tracks?.length > 0 && ( - tracks.map(t => + tracks.map((t, index) => ) )} diff --git a/src/services/utility-helpers.js b/src/services/utility-helpers.js index 3064e0df..72a2aaac 100644 --- a/src/services/utility-helpers.js +++ b/src/services/utility-helpers.js @@ -402,7 +402,7 @@ function getResourceInfo(item, motivation) { }; if (motivation === 'supplementing') { // Set language for captions/subtitles - s.srclang = item.getProperty('language') || 'en'; + s.srclang = item.getProperty('language') || 'eng'; // Specify kind to subtitles for VTT annotations. Without this VideoJS // resolves the kind to metadata for subtitles file, resulting in empty // subtitles lists in iOS devices' native palyers