Skip to content

HLS output master playlist emits BANDWIDTH=0 and plain opus CODECS #407

Description

@tamaina

Summary

HlsOutputFormat can generate a master playlist with BANDWIDTH=0 and a plain opus codec string in CODECS.

This appears to cause Safari/iOS to reject the master playlist before requesting the child media playlist.

Example output

Generated master.m3u8:

#EXTM3U

#EXT-X-STREAM-INF:BANDWIDTH=0,CODECS="avc1.640015,opus",RESOLUTION=480x270
playlist-1.m3u8

Problems

There seem to be two compatibility issues here:

  1. BANDWIDTH=0

    HLS clients expect BANDWIDTH to be a positive integer. Safari/iOS appears to reject this master playlist and does not proceed to request playlist-1.m3u8.

  2. CODECS="...,opus"

    For Opus in MP4/CMAF/fMP4 HLS, the codec string should be RFC 6381-compatible. I believe plain opus is not accepted by Safari's HLS parser here, and the expected string is likely mp4a.ad.

Expected behavior

The generated master playlist should use Safari/iOS-compatible attributes, for example:

#EXT-X-STREAM-INF:BANDWIDTH=396000,CODECS="avc1.640015,mp4a.ad",RESOLUTION=480x270
playlist-1.m3u8

More generally:

  • BANDWIDTH should never be 0; it should be a positive estimated peak bitrate.
  • CODECS should contain RFC 6381-compatible codec strings.
  • AVC should remain in full form, such as avc1.640015.
  • Opus in MP4/CMAF HLS should not be emitted as plain opus; it should likely be mp4a.ad.

Environment

  • Mediabunny version: 1.46.0
  • Output format: HlsOutputFormat
  • Segment format: CMAF/fMP4
  • Playback issue observed in Safari/iOS native HLS playback

Additional context

In the consuming app, macOS Safari can play some outputs, but iPhone Safari reports native media failure:

MediaError code 4 / MEDIA_ERR_SRC_NOT_SUPPORTED

The iPhone/Safari player does not appear to request the child media playlist, which suggests the master playlist itself is being rejected.

I worked around this downstream by patching the generated master playlist to:

  • replace BANDWIDTH=0 with a positive estimated aggregate bitrate
  • replace plain opus in CODECS with mp4a.ad

After that patch, the generated master playlist looks like:

#EXT-X-STREAM-INF:BANDWIDTH=473600,CODECS="avc1.64000c,mp4a.ad",RESOLUTION=320x180,AUDIO="audio-3"
playlist-2.m3u8

Possible source locations

From the distributed package, the master playlist writer appears to generate these values around:

  • dist/modules/src/hls/hls-muxer.js
    • writes BANDWIDTH=${Math.ceil(totalPeakBitrate)}
    • writes CODECS="${codecs.join(',')}"

Also, buildAudioCodecString appears to return plain "opus" for Opus, which may be correct in some contexts but seems incompatible with HLS master playlist CODECS for fMP4/CMAF playback in Safari.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions