@@ -131,6 +131,9 @@ class Html5 extends Tech {
131131 this . proxyNativeTextTracks_ ( ) ;
132132 }
133133
134+ // prevent iOS Safari from disabling metadata text tracks during native playback
135+ this . restoreMetadataTracksInIOSNativePlayer_ ( ) ;
136+
134137 // Determine if native controls should be used
135138 // Our goal should be to get the custom controls on mobile solid everywhere
136139 // so we can remove this all together. Right now this will block custom
@@ -173,6 +176,72 @@ class Html5 extends Tech {
173176 super . dispose ( ) ;
174177 }
175178
179+ /**
180+ * When a captions track is enabled in the iOS Safari native player, all other
181+ * tracks are disabled (including metadata tracks), which nulls all of their
182+ * associated cue points. This will restore metadata tracks to their pre-fullscreen
183+ * state in those cases so that cue points are not needlessly lost.
184+ *
185+ * @private
186+ */
187+ restoreMetadataTracksInIOSNativePlayer_ ( ) {
188+ const textTracks = this . textTracks ( ) ;
189+ let metadataTracksPreFullscreenState ;
190+
191+ // captures a snapshot of every metadata track's current state
192+ const takeMetadataTrackSnapshot = ( ) => {
193+ metadataTracksPreFullscreenState = [ ] ;
194+
195+ for ( let i = 0 ; i < textTracks . length ; i ++ ) {
196+ const track = textTracks [ i ] ;
197+
198+ if ( track . kind === 'metadata' ) {
199+ metadataTracksPreFullscreenState . push ( {
200+ track,
201+ storedMode : track . mode
202+ } ) ;
203+ }
204+ }
205+ } ;
206+
207+ // snapshot each metadata track's initial state, and update the snapshot
208+ // each time there is a track 'change' event
209+ takeMetadataTrackSnapshot ( ) ;
210+ textTracks . addEventListener ( 'change' , takeMetadataTrackSnapshot ) ;
211+
212+ const restoreTrackMode = ( ) => {
213+ for ( let i = 0 ; i < metadataTracksPreFullscreenState . length ; i ++ ) {
214+ const storedTrack = metadataTracksPreFullscreenState [ i ] ;
215+
216+ if ( storedTrack . track . mode === 'disabled' && storedTrack . track . mode !== storedTrack . storedMode ) {
217+ storedTrack . track . mode = storedTrack . storedMode ;
218+ }
219+ }
220+ // we only want this handler to be executed on the first 'change' event
221+ textTracks . removeEventListener ( 'change' , restoreTrackMode ) ;
222+ } ;
223+
224+ // when we enter fullscreen playback, stop updating the snapshot and
225+ // restore all track modes to their pre-fullscreen state
226+ this . on ( 'webkitbeginfullscreen' , ( ) => {
227+ textTracks . removeEventListener ( 'change' , takeMetadataTrackSnapshot ) ;
228+
229+ // remove the listener before adding it just in case it wasn't previously removed
230+ textTracks . removeEventListener ( 'change' , restoreTrackMode ) ;
231+ textTracks . addEventListener ( 'change' , restoreTrackMode ) ;
232+ } ) ;
233+
234+ // start updating the snapshot again after leaving fullscreen
235+ this . on ( 'webkitendfullscreen' , ( ) => {
236+ // remove the listener before adding it just in case it wasn't previously removed
237+ textTracks . removeEventListener ( 'change' , takeMetadataTrackSnapshot ) ;
238+ textTracks . addEventListener ( 'change' , takeMetadataTrackSnapshot ) ;
239+
240+ // remove the restoreTrackMode handler in case it wasn't triggered during fullscreen playback
241+ textTracks . removeEventListener ( 'change' , restoreTrackMode ) ;
242+ } ) ;
243+ }
244+
176245 /**
177246 * Create the `Html5` Tech's DOM element.
178247 *
0 commit comments