video-dev / hls.js

HLS.js is a JavaScript library that plays HLS in browsers with support for MSE.
https://hlsjs.video-dev.org/demo
Other
14.62k stars 2.56k forks source link

HLS video embeds do not load on iphone #4354

Closed oelbaga closed 2 years ago

oelbaga commented 2 years ago

What version of Hls.js are you using?

1.0.11

What browser (including version) are you using?

Safari

What OS (including version) are you using?

IOS 14 & 15

Test stream

https://hls-js.netlify.app/demo/

Configuration

{
  "debug": true,
  "enableWorker": true,
  "lowLatencyMode": true,
  "backBufferLength": 90
}

Additional player setup steps

No response

Checklist

Steps to reproduce

  1. Access the main demo on an iPhone browser: https://hls-js.netlify.app/demo/
  2. Screen is black or video doesnt load

Expected behaviour

Embedded video should play

What actually happened?

Video player doesn't play video

Console output

[Error] Unhandled Promise Rejection: AbortError: The operation was aborted.
    (anonymous function)
    rejectPromise

Chrome media internals output

No response

piyushsharma21 commented 2 years ago

hi facing the same issue, any solution?

dylanjha commented 2 years ago

Hi @oelbaganwg and @piyushsharma21

HLS.js relies on HTML5 video and MediaSource Extensions for playback.

All iPhone browsers (iOS) do not have MediaSourceExtension available, and therefore Hls.js will not work. If you check Hls.isSupported() on an iPhone you will see that function returns false.

Here's an example in the README that shows how to handle this: https://github.com/video-dev/hls.js#embedding-hlsjs,

See this part, in particular:

  if (Hls.isSupported()) {
    var hls = new Hls();
    hls.loadSource(videoSrc);
    hls.attachMedia(video);
  } else if (video.canPlayType('application/vnd.apple.mpegurl')) {
    video.src = videoSrc;
  }
Christopher-Hayes commented 1 year ago

And just to add color to @dylanjha's helpful comment - on iOS you specifically need to NOT initialize Hls.js on the video element. (by checking Hls.isSupported())

iOS can use the normal <video><source></video> HTML since Safari has native HLS support. Initializing Hls.js on the <video> will prevent the native HLS functionality from working at all.

cyango commented 1 year ago

My iPhone 10 does not even work with native HLS, it says not supported. So I have to load the default mp4 video, which is 400Mb and this gives me 206 error...Any clue?

Alex20180512 commented 5 months ago

@piyushsharma21

This solution didn't work for me because Hls.isSupported always returned true. i made the following adjustments to make it work:

import Hls from "hls.js";
import { forwardRef, useEffect, useImperativeHandle, useRef } from "react";

interface PlayerProps {
  src?: string;
  poster: string;
  onPlay(): void;
  onPlayFailed(): void;
}

export const Player = forwardRef<{}, PlayerProps>(({ src, poster, onPlay, onPlayFailed }, ref) => {
  const videoRef = useRef<HTMLVideoElement | null>(null);
  const hlsRef = useRef<Hls | null>(null);

  useEffect(() => {
    if (!src || !videoRef.current) return;
    const supportHLS = Boolean(videoRef.current.canPlayType("application/vnd.apple.mpegurl"));

    if (supportHLS) {
      videoRef.current.src = src;
      videoRef.current.play().then(onPlay).catch(onPlayFailed);
    } else {
      hlsRef.current = new Hls();
      const hls = hlsRef.current;

      hls.on(Hls.Events.MEDIA_ATTACHED, function () {
        videoRef.current!.play().then(onPlay).catch(onPlayFailed);
      });
      hls.loadSource(src);
      hls.attachMedia(videoRef.current);

      return () => {
          hls.destroy();
      };
    }
  }, [src]);

  useImperativeHandle(ref, () => videoRef.current!, []);

  return (
    <video className="w-full h-full object-cover" playsInline ref={videoRef} poster={poster}>
      <source src={src} type="application/x-mpegURL"></source>
    </video>
  );
});
robwalch commented 5 months ago

Hls.isSupported always returned true

iOS versions 17.1 and up are supported since hls.js@v1.5.0 using ManagedMediaSource:

Please file a new bug if isSupported returns true and playback with HLS.js is not comparable to Safari's built-in HLS support.

The latest release of HLS.js as of this writing is v1.5.7.

i made the following adjustments to make it work

This is good if you prefer to use built-in HLS support when available. Note that some platforms with built-in HLS support return true for HTMLMediaElement.canPlayType("application/vnd.apple.mpegurl"), which do not have the same level of HLS support as HLS.js or Safari. Test the built-in HLS support in Android and Edge browsers before using them over HLS.js.

mohammadmansour200 commented 4 months ago

Ok, setting the video element src directly to something like XXXXXXX.m3u8 works, but what if it included multiple quality levels and of course ability to set the level manually is needed? setting it in hls.js is very straightforward, but what about ios devices that doesn't support hls.js?

dylanjha commented 4 months ago

setting it in hls.js is very straightforward, but what about ios devices that doesn't support hls.js?

Unfortunately the native video element on iOS, which supports .m3u8 sources does not have a quality level selector nor an API that I know of to manually set the quality level