I am a Cloudflare evangelist. Working on media heavy sites means Cloudflare has become a useful tool to speed up load times and offset bandwidth.

The service isn’t without it quirks. Over the last few months I have found media failing to auto-play in Safari and on iOS.

The problem was seemingly intermittent. As demonstrated above; previously cached mp4 files auto play while newly cached files do not in Safari.

Common Issues with Auto-playing Video

MP4 files are well supported and should auto play across modern browsers and devices, including iOS and mobile when correctly exported.

Typical issues with mp4 auto-play are:

  • Not removing the audio track
  • Not including muted tag within the video element
  • Not including playsinline within the video element.

A correctly formatted mp4 element should look like this.

<video autoplay muted loop playsinline>
    <source src="video.mp4" type="video/mp4" />
</video>

Understanding the Problem

The reason that Cloudflare seems to cause issues is to do with how the video file headers are presented to Safari by Cloudflares server.

I would typically deploy a site with a Page Rule that caches everything within a sites media directory for as long as possible.

https://www.domain.tld/mediapath/*
Browser Cache TTL: a year
Cache Level: Cache Everything
Edge Cache TTL: a month

This means that all assets within that directory are served from Cloudflares edge-servers including video files.

You can check if a file is served by Cloudflare by inspecting the files header.

curl -svo /dev/null https://www.domain.tld/file.mp4 2>&1 | egrep "Date|cf-|HTTP/"

Content cached on Cloudflares edge servers will return

cf-cache-status:HIT

Ordinarily having static contents served from Cloudflare edge servers rather than your origin server is great. It reduces the load on your server and normally speeds up the load time of those assets for your visitors.

However, video files are different to images or other static content. Video doesn’t want to be loaded in one go.

Video should return a 206 Partial Content status in the file header.

The idea behind the 206 status is a file can quickly return a partial request that indicates the files Content Range followed by size.

This allows your browser to process larger files that require split or interrupted downloads with multiple simultaneous streams which improves latency.

The problem appears to be how Cloudflare receives and passes on files from the origin server that use a chunked or stream protocol rather than transmitting a file in full.

As Cloudflare does not receive the whole file so it cannot tell the full size. It isn’t able to pass a 206 status with a full file size.

'Safari Before'

While Chrome and Firefox happily take the 200 code and continue to download the file, streaming the video and allowing the file to play, Safari simply stops loading the video after the initial chunk and does not auto-play the video.

The Solution

We can bypass the problem by stopping Cloudflare caching video files and forcing them to be served by our origin server.

Either —

1) We can rewrite our initial Page Rule to include only JPGs.

https://www.domain.tld/mediapath*/*.jpg*
Browser Cache TTL: a year
Cache Level: Cache Everything
Edge Cache TTL: a month

2) We can leave the initial rule intact and introduce a second rule that explicitly excludes mp4 files. This is preferable as it allows other static files types to be cached.

https://www.domain.tld/mediapath*/*.mp4*
Cache Level: Bypass Cache

By default most video files seem not to be cached by Cloudflare; there is some discussion that now smaller mp4 files do seem to be cached meaning option #2 is the only one that will be guaranteed to force video to be loaded from your origin server

'Safari After'

As mp4 file is being served from your origin server with the correct 206 header it should now auto-play correctly in Safari.

The solution will allow video to autoplay but it is not ideal. The speed and bandwidth benefits of Cloudflare are lost as we end up being forced to serve video assets directly from the origin server.

I will update the article if I find a better solution.

A further run down and discussion of the issue can be found at “MP4 Won’t Load in Safari Using CloudFlare