I have a HTML page including Javascript which is intended to allow a video (actually just audio content in this case) to play using HTTP Live Streaming on any browser. In most cases it uses hls.js
but, in the case of Apple products, I need to do things differently as Safari has native HLS support.
The full page is reproduced below but the important lines are these:
else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = 'music.m3u8';
video.addEventListener('canplay', startPlaying);
//document.addEventListener('DOMContentLoaded', startPlaying);
}
What should happen is that when the canplay
event fires the startPlaying()
function is called and this makes visible a button that the user can press to begin playing the video. However, on my friend's iPhone 8plus (iOS 11.3.1), this doesn't work: no button is ever visible. If, instead, I comment out the video.addEventListener()
line and replace it with the document.addEventListener()
line then it all works fine: the button is made visible and he can play the stream.
Can anyone spot what I'm doing wrong? Could be a rookey mistake as I'm not very experienced with this web/script stuff, gives me nose bleeds... I could, of course, leave it with the DOM load approach but it's not right and I'd rather be right.
<!DOCTYPE html PUBLIC "-//Netscape Comm. Corp.//DTD HTML//EN">
<html>
<script src="hls.js/dist/hls.js"></script>
<head><meta http-equiv="content-type" content="text/html; charset=UTF-8"></head>
<body>
<video id="video"></video>
<button id="play" hidden>Loading</button>
<script>
'use strict';
var video = document.getElementById('video');
var playButton = document.getElementById('play');
function startPlaying() {
// For mobile browsers the start of playing has to
// be performed by a user action otherwise it will
// be ignored
playButton.addEventListener('click', function() {
video.play();
video.muted = false;
video.volume = 1;
playButton.innerHTML = "Playing";
});
playButton.hidden = false;
playButton.innerHTML = "Ready to play";
}
if (Hls.isSupported()) {
var hls = new Hls();
hls.loadSource('music.m3u8');
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, startPlaying);
}
// hls.js is not supported on platforms that do not have Media Source Extensions (MSE) enabled.
// When the browser has built-in HLS support (check using `canPlayType`), we can provide an HLS manifest (i.e. .m3u8 URL) directly to the video element through the `src` property.
// This is using the built-in support of the plain video element, without using hls.js.
else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = 'music.m3u8';
video.addEventListener('canplay', startPlaying);
//document.addEventListener('DOMContentLoaded', startPlaying);
}
</script>
</body>
</html>
From the investigations in the other question, the workaround is to wait on the event loadedmetadata
, so in my case video.addEventListener('loadedmetadata', startPlaying)
, as this is the last event you're going to get from the HTML5 video element on Safari unless you're in the user-controlled white list. Confirmed that this works on iOS 11.3.1.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With