@@ -14,6 +14,7 @@ export default class SlideContent {
1414 this . Reveal = Reveal ;
1515
1616 this . startEmbeddedIframe = this . startEmbeddedIframe . bind ( this ) ;
17+ this . ensureMobileMediaPlaying = this . ensureMobileMediaPlaying . bind ( this ) ;
1718
1819 }
1920
@@ -320,6 +321,8 @@ export default class SlideContent {
320321 else if ( isMobile ) {
321322 let promise = el . play ( ) ;
322323
324+ el . addEventListener ( 'canplay' , this . ensureMobileMediaPlaying ) ;
325+
323326 // If autoplay does not work, ensure that the controls are visible so
324327 // that the viewer can start the media on their own
325328 if ( promise && typeof promise . catch === 'function' && el . controls === false ) {
@@ -374,6 +377,40 @@ export default class SlideContent {
374377
375378 }
376379
380+ /**
381+ * Ensure that an HTMLMediaElement is playing on mobile devices.
382+ *
383+ * This is a workaround for a bug in mobile Safari where
384+ * the media fails to display if many videos are started
385+ * at the same moment. When this happens, Mobile Safari
386+ * reports the video is playing, and the current time
387+ * advances, but nothing is visible.
388+ *
389+ * @param {Event } event
390+ */
391+ ensureMobileMediaPlaying ( event ) {
392+
393+ const el = event . target ;
394+
395+ // Ignore this check incompatible browsers
396+ if ( typeof el . getVideoPlaybackQuality !== 'function' ) {
397+ return ;
398+ }
399+
400+ setTimeout ( ( ) => {
401+
402+ const playing = el . paused === false ;
403+ const totalFrames = el . getVideoPlaybackQuality ( ) . totalVideoFrames ;
404+
405+ if ( playing && totalFrames === 0 ) {
406+ el . load ( ) ;
407+ el . play ( ) ;
408+ }
409+
410+ } , 1000 ) ;
411+
412+ }
413+
377414 /**
378415 * Starts playing an embedded video/audio element after
379416 * it has finished loading.
@@ -461,6 +498,10 @@ export default class SlideContent {
461498 if ( ! el . hasAttribute ( 'data-ignore' ) && typeof el . pause === 'function' ) {
462499 el . setAttribute ( 'data-paused-by-reveal' , '' ) ;
463500 el . pause ( ) ;
501+
502+ if ( isMobile ) {
503+ el . removeEventListener ( 'canplay' , this . ensureMobileMediaPlaying ) ;
504+ }
464505 }
465506 } ) ;
466507
0 commit comments