Skip to content

README Alternative setup breaks HLS playback in Chrome 147 on macOS and Android #7827

Description

@karlhorky

What version of Hls.js are you using?

1.6.15

What browser (including version) are you using?

Chrome 147.0.7727.117 on macOS, Chrome 147.0.7727.111 on Android

What OS (including version) are you using?

macOS Tahoe 26.4.1 (25E253), Android 16

Test stream

I tested a number of .m3u8 streams on Vimeo - but I guess it is actually any .m3u8 stream

Configuration

{}

Additional player setup steps

This is not a report that playback fails when using HLS.js directly. Playback works when using hls.js@1.6.15.

The issue is with the README "Alternative setup":

https://github.com/video-dev/hls.js/#alternative-setup

The Alternative setup checks native HLS support before Hls.isSupported():

if (video.canPlayType('application/vnd.apple.mpegurl')) {
  video.src = videoSrc;
} else if (Hls.isSupported()) {
  var hls = new Hls();
  hls.loadSource(videoSrc);
  hls.attachMedia(video);
}

In Chrome 147, this check from the README returns "maybe":

video.canPlayType('application/vnd.apple.mpegurl');
// "maybe"

So the Alternative setup chooses Chrome's native HLS path instead of HLS.js. In Chrome 147, that native path fails on macOS and Android.

The default HLS.js-first setup works.

Checklist

Steps to reproduce

  1. Use the README Alternative setup:

    var video = document.getElementById('video');
    var videoSrc = '<m3u8 URL>';
    
    if (video.canPlayType('application/vnd.apple.mpegurl')) {
      video.src = videoSrc;
    } else if (Hls.isSupported()) {
      var hls = new Hls();
      hls.loadSource(videoSrc);
      hls.attachMedia(video);
    }
  2. Use an .m3u8 URL.

  3. Open the page in Chrome 147.0.7727.117 on macOS or Chrome 147.0.7727.111 on Android.

  4. Observe that this branch is selected:

    if (video.canPlayType('application/vnd.apple.mpegurl')) {
      video.src = videoSrc;
    }

    because:

    video.canPlayType('application/vnd.apple.mpegurl');
    // "maybe"
  5. Observe that the video does not load or play, but instead shows an "empty" broken player like this:


    Chrome on macOS: Image


    Chrome on Android: Image

Expected behaviour

The README Alternative setup does not break HLS playback in Chrome 147 on macOS or Android.

What actually happened?

The README Alternative setup breaks HLS playback in Chrome 147 on macOS or Android.

Console output

Chrome 147 returns "maybe" for the exact MIME type used in the README Alternative setup:

video.canPlayType('application/vnd.apple.mpegurl')
// "maybe"

Other HLS MIME type / codec combinations also return "maybe" or "probably":

video.canPlayType('application/vnd.apple.mpegURL')
// "maybe"

video.canPlayType('audio/mpegurl')
// "maybe"

video.canPlayType('application/vnd.apple.mpegURL; codecs="avc1.42E01E,mp4a.40.2"')
// "probably"

video.canPlayType('application/x-mpegURL; codecs="avc1.42E01E"')
// "probably"

Safari 26.4 (21624.1.16.11.4) on macOS:

  1. returns the same values for these checks
  2. plays the stream successfully

Because of this, the README Alternative setup chooses native Chrome HLS playback and never initializes HLS.js.

In Chrome 147, the video appears as a gray, empty, unplayable video. Neither audio nor video plays.

Previous versions of Chrome played the stream (this appears to be a regression):

  • Good: Chrome 146.0.7680.178 on macOS
  • Bad: Chrome 147.0.7727.117 on macOS
  • Bad: Chrome 147.0.7727.111 on Android

The same stream works when routed through hls.js@1.6.15.

A few more runtime tests from Chrome 147.0.7727.117 on macOS:

const video = document.querySelector('video');

console.log('error.code', video.error?.code);
// error.code 4

console.log('error.message', video.error?.message);
// error.message PipelineStatus::DEMUXER_ERROR_COULD_NOT_PARSE

console.log('networkState', video.networkState);
// networkState 3

console.log('readyState', video.readyState);
// readyState 0

console.log('currentSrc', video.currentSrc);
// currentSrc https://vod-adaptive-ak.vimeocdn.com/exp=...

Chrome media internals output

{
  "cause": {
    "cause": {
      "code": 1,
      "data": {},
      "group": "HlsDataSourceProvider::ReadStatus::1",
      "message": "",
      "stack": [
        "media/filters/hls_data_source_provider_impl.cc#193",
        "media/filters/hls_manifest_demuxer_engine.cc#627",
        "media/filters/hls_manifest_demuxer_engine.cc#689"
      ]
    },
    "code": 11,
    "data": {},
    "group": "HlsDemuxerStatus::Network read stopped",
    "message": "",
    "stack": [
      "media/filters/hls_demuxer_status.h#136"
    ]
  },
  "code": 13,
  "data": {},
  "group": "PipelineStatus::DEMUXER_ERROR_COULD_NOT_PARSE",
  "message": "",
  "stack": [
    "media/filters/hls_manifest_demuxer_engine.cc#158",
    "media/filters/manifest_demuxer.cc#491",
    "media/filters/manifest_demuxer.cc#443"
  ]
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions