Playing video from Javascript function in iOS

I’m having problems getting video clips to play in iOS Safari on an iPad. I note the warnings about not being able to autoplay a video in iOS, but what does mean exactly? I’ve got a START button that runs a JS function. That function (among other things) includes a call to play() a video element. By my understanding that’s not autoplay, because the user has interacted with the start button. But the video won’t play in iOS (fine in macOS in both Chrome and Safari). Is my problem this autoplay limitation or is it likely to be something else?

… To be clear … the START button runs timeline that (among other things) includes an action to call a JS function. And that function calls the video play().

It might be a video format issue – can you share your document?

I think I’ve found the problem. There’s a warning in Hype that, for mobile Safari 7.2, videos without controls are unplayable on an iPad, though I can’t get it to play on the iPhone either (both running Safari 13). It seems bit of a savage restriction. I’ll have to rethink the structure of the project.

The warning is that if your video is not autoplayable then without controls users will simply have no way to start.

To make an autoplayable video on iOS it must be muted to start and also set to play inline. If you do not do either of these then you won’t be able to autoplay or use the .play() that is not in the context of a user click/tap.

Maybe you can post a zip sample of your document? It isn’t clear to me exactly what you are hitting.

I can’t see any way of avoiding this problem. I should have done more reading before I started. I think Apple says it won’t let videos load(), let alone play(), on iOS without the specific press of a control button because it could accidentally consume lots of the user’s 3G or 4G data. Understandable, I guess.

The project plays a short video clip, which then freezes into a 24-piece child’s jigsaw (it’s for my 3-year old grandson, locked down at home due to Covid19). The jigsaw then breaks up and the user is invited to assemble it. When the jigsaw is correctly assembled it carries on from where it left off with a second short video clip.

I guess I’ll have to build two versions of the project and insert a bit of code to detect the platform, cutting out the video bits for an iOS device and just leaving the jigsaw bit.

However, there is one remaining problem even in macOS (forgetting about iOS for the moment), and that is, although it works faultlessly in Chrome on my Mac (including the video clips), it sometimes fails to play the video clips in Safari, displaying the error message “Unhandled Promise Rejection” when play() is called.

I would much appreciate any insight into this problem. Unfortunately I can’t attach the Hype project to this post as, at 14MB, it exceeds the Forum’s upload limit.

Many thanks.

Do you need audio? If not, you can just mute it and then it will allow playback without interaction.

This is the result of trying to autoplay a non-muted video. Hype's runtime code for autoplay specifically deals with this, so perhaps this example is useful:

if(animation["${type}"] == kAnimationTypeVideo && timelineRun.isPlaying == true) {
	var autoplay = _scenes[_currentSceneIndex]["${initialValues}"][oid]['${Autoplay}'];
	var element = getElementByHypeOid(oid);
	if(autoplay == true && element.play) {
		element.autoplay = true;
		var playPromise = element.play();
		// silence a DOMException if trying to autoplay back but not muted
		// Safari throws anyways based on setting autoplay
		// it may be a good idea to log this if there's a debug runtime
		if (playPromise !== undefined) {
			playPromise['catch'](function() {});
		}
	}
}

I think the check for element.play is also extra protection as I seem to recall there may have been some cases where the element was not fully loaded and the .play() function would likewise throw a sort of DOM error... but I'm a little hazy on this; it may have been for another reason.

You are always welcome to supply a dropbox link or host the file on another server.

Thanks for that. Yes, I guess it could run muted on iPad/iPhone – not ideal, but better than no video at all. I’ll look into that. Also, I’ll look at the example you give on catching a play() promise.

Meanwhile, if you fancy a glimpse of what I’m trying to do, here’s a Dropbox link to the project. To see it as it should work (only a few little tidy-ups needed), run it in macOS in a Chrome browser. Safari is unreliable for this project even in macOS (it fails 4 times out of 5 to show the video clips – with the play() promise error). Running it on an iPad is bit of a disaster at the moment, but I’ve got the project to recognise what platform it’s on, so I could progress it along the lines you suggest.

Many thanks. Much appreciated.

Specifically the code is really more for silencing the log than fixing the problem.

Thanks - I can see this is definitely because of trying to autoplay video that includes audio. I'm surprised it ever works, but maybe the inconsistency is there's some way in which Safari gets allowed through a user action in one session and that happens to persist depending on how it is reloaded.