HTML5 Video and Safari

Hey all!

I am having some Meteor trouble. I am adding an MP4 video to a website, and it works in all browsers except Safari. Both on iOS and MAC Desktop the videos are there when I inspect them, but regardless of any css etc I cannot get them to show up…on any page.

I have tried other formats (webm etc) and even other videos that work from other non-Meteor websites but those do not work either. I AM using the playsinline property.

I have actually tried this on other Meteor apps I have also, and it seems to have the same problem. I simply cannot get an inline html5 video to show up in Safari on ANY Meteor application.

Here is the basic html5 video code I have been adding:

    <video class="bgVid" playsinline autoplay muted loop id="bgvid">
      <source src="/video/FaceBook_Banner_Video_FINAL_Opt.webm" type="video/webm" />
      <source src="/video/FaceBook_Banner_Video_FINAL_Opt.mp4" type="video/mp4" />
    </video>

Has anyone run into this before? Any solutions? I am using Blaze which I have moved away from on newer apps…but really cant just convert this one simply because of one video.

1 Like

Hi @jhochgreve,
I think your trouble is not with Meteor but with HTML5 and browser support.
Did this help when your searched the net looking for a fix? https://stackoverflow.com/questions/20347352/html5-video-tag-not-working-in-safari-iphone-and-ipad.
Also, the way your paths look like, I presume you have a video folder under your Meteor project public folder.
If you use React (or not) and your videos are large, best would be to convert to HLS and deliver via something like react-player (which also offers a clean JS version). When I say best, I mean if you have multiple videos and you need to have them starting right away without buffering and … old internet user experience.

Hey @paulishca as mentioned in my post, I have tried the video on every other platform and it loads just fine. Even when using a fresh Meteor install without any modifications, the video does not display.

I would encourage you to try the same. Install Meteor fresh, add any html5 video to the initial page Meteor ships with. Use ANY combination of accepted HTML5 video parameters, it wont load…but only in Safari. Take that same code and add it to a static HTML5 boilerplate, and open it in safari…it will work fine.

You are correct though, I am loading the video from the local meteor /public folder; however, I have tried loading videos from other accepted sources such as this: https://www.w3schools.com/html/html5_video.asp and still it will not load via Meteor.

Unfortunately, I do believe the bug resides within Meteor…somehow.

I just successfuly embedded this video on a page in a Meteor project.

Maybe your problem is with /public and the asset is not being copied into .meteor/local/build/programs/web.browser/app because of its size?

1 Like

Hey @jamgold I just tried the same video like so:

<video playsinline autoplay muted loop> <source src="https://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_2mb.mp4" type="video/mp4" /> </video>

In a brand new fresh Meteor install, popped it open in Safari, and nothing…nada…no video. It is there in the DOM, but it does not actually display on screen.

Did you try looking in Safari?

I should also mention that I AM able to open my local video hosted in /public by navigating directly to it. It is only 10MB in size.

Holy crap, you are right. I forgot that I had switched my default browser from Safari to Chrome. It doesn’t work in Safari with Meteor (static web-page with the same video markup works).

Interestingly enough, when looking at the video in the static web-page, it magically starts playing on the meteor site as well.

Adding the controls parameter fixed it in my project. Looks like autoplay in Safari isn’t working before the video has loaded …

<video class=" img-fluid rounded-pill" controls>{{!playsinline autoplay loop}}
  <source src="https://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_2mb.mp4" type="video/mp4" />
</video>

The weirdness continues. I was able to crash Safari several times when trying to play via javascript. This is how I got it to work in Safari/Chrome/Firefox … this can’t be the last of it, someone has got to have a better way of doing this

<template name="video">
 <div id="video-parent"></div>
</template>
Template.video.onRendered(function () {
  const instance = this
  const parent = instance.find('#video-parent')
  instance.video = document.createElement('video')
  instance.video.classList.add('rounded-lg')
  instance.video.classList.add('img-fluid')
  instance.video.src = 'https://www.sample-videos.com/video123/mp4/720/big_buck_bunny_720p_2mb.mp4'
  instance.video.addEventListener('canplaythrough', () => {
    console.log(instance.video)
    instance.video.controls = true
    //Meteor.setTimeout(()=>{
    //  instance.video.play()
    //}, 500)
  })
  parent.append(instance.video)
})
Template.video.onDestroyed(function () {
  const instance = this
  instance.video.pause()
  instance.video.remove()
})
2 Likes

@jamgold haha NICE!

While you were doing that, I went ahead and added video.js (GitHub - videojs/video.js: Video.js - open source HTML5 video player) and used it as a solution. Viola that worked too.

Having used and built apps with Meteor since the beginning myself, I was totally SHOCKED to discover this bug!

Your solution is at least a solution in the sense that it is using native html5 video.

I did post an issue on meteor here: Safari HTML5 Video Issue · Issue #10887 · meteor/meteor · GitHub

Perhaps they will address. :slight_smile:

1 Like

HCR (Hot Code Refresh) also seems involved.

On Safari you get this error when on the page with video during HCR and the video doesn’t play or show.

Unhandled Promise Rejection: NotAllowedError: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.

Other browsers show a similar error, but at least show the <video> element.

1 Like

I’m pretty sure this is a Safari bug (feature?) to protect users from downloading large files and from autoplay.
Our Video component file is jsut over 500 lines to deal with issues like this. I definitely recommend using tools like VideoJS to handle cross browser inconsistencies.

Apple gave us a new present recently with the new iOS safari changing the user agent string to look like desktop safari, even though the render rules are different and incompatible :scream: so now we use a combination of user agent and feature sniffing to differentiate between iPads, iPhones, different versions of iOS and everything else.
Funny that everything else works exactly as the spec describes and it’s just the various iterations of Safari that need weird overrides.

The workaround relevant to your case is that iOS won’t load videos automatically anymore, so we call:
video.load() when the component renders to get things moving

2 Likes

@coagmano I agree it is a Safari issue (to an extent); however, the argument could be made that this is still a Meteor issue also. I only say this because the issue does not exist in any other frame work I have tried (REACT, VIEW, NEXT, SVELTE, SAPPER). So while I agree Safari is being pretty goofy by comparison to other browsers, Meteor is also behaving differently than other frameworks.

I only point this out because I absolutely LOVE Meteor and have always been loyal to it. A big part of this is because I trust Meteor. I no longer use BlazeJS, but Meteor ships with it. I want to recommend Meteor to other devs but it gets difficult when the framework it ships with has issues such as this…

Hope noone takes this the wrong way…I say it all out of love.

1 Like

One final item here. In order to get the video to play as we needed in both Safari on MAC OS and iOS we had to modify the code by @jamgold slightly. Unfortunately prior versions of Safari freaked out with VideoJS. Here is the code that seemed to work for all browsers that we could find:

Template.LanderVideo.onRendered(function () {
  const instance = this
  const parent = instance.find('#videoContainer')
  instance.video = document.createElement('video')
  instance.video.setAttribute('id', 'videoID')
  instance.video.setAttribute('playsinline', true)
  instance.video.src = '/video/FaceBook_Banner_Video_FINAL_Opt.mp4'
  parent.append(instance.video)
  instance.video.addEventListener('canplay', () => {
    instance.video.controls = false
    instance.video.playsinline = true
    instance.video.muted = true
    instance.video.loop = true
    instance.video.autoplay = true
    instance.video.play()
  })
  instance.video.load()
})

Template.LanderVideo.onDestroyed(function () {
  const instance = this
  instance.video.pause()
  instance.video.remove()
})

I have started working on a small package to standardize the video across all browsers, and to my surprise, when invoked from within the package the plain <video> tag works, even in Safari. It also seems to depend on where the video is coming from (external website, network speed).

This reminds me of the good old Internet Explorer days … :wink:

1 Like

@jamgold funny enough…I LITERALLY just said the same thing on your reply to my Stackoverflow! I really appreciate your help with this. I see you being super active on here all of the time. Despite the issues I have found with Meteor lately, knowing it still has a great community is super encouraging!

1 Like

I have been working with Meteor since it’s 0.5 (or something) days, and it literally still brings kondo-like joy every time I dive into a new project :smile:

I poured all my attempts into a package blaze-html5video-safari. Feedback welcome

3 Likes

This is quite surprising, would be great to work out how Blaze is different and why that causes this issue here

2 Likes

@jamgold Thanks for this package! I will scope it out here soon! :slight_smile: