Video is not working on iphones, but on all other devices it works

I have a website that is streaming videos. It works with all devices except iphones.

Any idea what could be the problem?

I found the following solutions, but they are not working in my case:
a) set the right video tags

I am using:

<video autoplay loop muted playsinline controls="true" id="my-video" class="video-js"  width="640" height="264" data-setup="{}">

b) use other encoding than mp4

I didn’t implement that yet, any experience if that helps?

Here is how I stream the videos:

  def send_video(conn, headers, video) do
    video_path = build_video_path(video)
    offset = get_offset(headers)
    file_size = get_file_size(video_path)
    |> Plug.Conn.put_resp_header("content-type", video.content_type)
    |> Plug.Conn.put_resp_header("content-range", "bytes #{offset}-#{file_size-1}/#{file_size}")
    |> Plug.Conn.send_file(206, video_path, offset, file_size - offset)

  def get_offset(headers) do
    case List.keyfind(headers, "range", 0) do
      {"range", "bytes=" <> start_pos} ->
        String.split(start_pos, "-") |> hd |> String.to_integer
      nil ->

  def get_file_size(path) do
    {:ok, %{size: size}} = File.stat path

Many thanks for any help!


Is that video file playable on iOS devices?

You can try to play the video with plain HTML only, without streaming code. Like this:

<video controls src="url/to/video/file"></video>

If not, try to convert the video file into a widely supported format. Then, try to play it again.

1 Like

What is your use case? A single video embedded in your app or a video platform (or something else?) And how long are the videos? This may affect the answers you get here. For example, if it is a single video of moderate length I’d be inclined to encode and package it to support multiple devices - fe.g. mp4, dash and hls - and then use something like video.js where you can set multiple sources for a single video. Getting a single video format that is universally supported still seems to be harder than it should be.

Our platform will use a fair bit of video and we have decided to use mux to host it, video.js to play it and liveview to lookup the right video and create the right auth tokens. There’s a cost involved, but they handle all the encoding and packaging to target pretty well any browser/platform.

1 Like

Any chance you are using VP9 codec? Apple doesn’t support it.


Yes, that’s a good point. To determine the codec use ffprobe:

ffprobe -v quiet -show_entries stream=index,codec_name,height -of json h264-file.mp4


    "programs": [

    "streams": [
            "index": 0,
            "codec_name": "h264",
            "height": 1920
            "index": 1,
            "codec_name": "aac"

To convert from vp09 to h264(lightweight transcode):

ffmpeg -fflags +genpts -i vp09-input.mp4 -r 24 h264-output.mp4

Many thanks for all the replies, I will try out the different proposal over these weekend, I will keep you posted on what worked in my case.

Many thanks for all the help, it is really a great community in this forum!

Here is my final solution:

# check codec
sudo apt install ffmpeg
ffprobe -v quiet -show_entries stream=index,codec_name,height -of json die-3-hauptmodelle

# codex is okay

# final solution: play the video with plain HTML only,
 <video controls src="url/to/video/file"></video>

# add video folder to endpoint.ex
plug Plug.Static,
  at: "/", from: :video_page, gzip: false,
  only: ~w( ... videos)

# video_controller.ex
  def show(conn, params) do
  |> render("show.html",..., video: video)

# adjust show.html 
  <video controls src="<%= static_path(@conn, "/videos/"<> @video.filename) %>" controls="true" id="my-video" class="video-js"  width="640" height="264"></video>

# works now with iphone as well

1 Like