#7784·PeerTube

HLS manifest declares mp4a.40.2 for any unrecognised audio codec, making the stream unplayable

Author: vinybrunCreated Sep 10, 2026Updated Sep 11, 2026

Disclaimer: the issue was AI generated, but I support it to enable FLAC audio streaming in the web player.

Describe the current behavior

getAudioStreamCodec() in server/core/helpers/ffmpeg/codecs.ts maps an audio codec name to the CODECS attribute written into the HLS master playlist. It knows four codecs and falls back to AAC for everything else:

typescript
if (audioCodecName === 'opus') return 'opus'
if (audioCodecName === 'vorbis') return 'vorbis'
if (audioCodecName === 'aac') return 'mp4a.40.2'
if (audioCodecName === 'mp3') return 'mp4a.40.34'

logger.warn('Cannot get audio codec of %s.', path, { audioStream })

return 'mp4a.40.2' // Fallback

That value is written verbatim into #EXT-X-STREAM-INF:...,CODECS="..." in server/core/lib/hls.ts. When an audio rendition holds any other codec, the manifest tells the player the audio is AAC when it is not. hls.js creates a SourceBuffer for mp4a.40.2, appending the real segments fails, and playback stops.

With a FLAC audio rendition, the file on disk is correct:

$ ffprobe -select_streams a:0 -show_entries stream=codec_name,channels,bit_rate ...-0-fragmented.mp4
codec_name=flac
channels=2
bit_rate=194386

while the manifest describes it as AAC:

#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="Audio",AUTOSELECT=YES,DEFAULT=YES,URI="....m3u8"
#EXT-X-STREAM-INF:BANDWIDTH=923594,RESOLUTION=1280x720,FRAME-RATE=30,CODECS="avc1.64001f,mp4a.40.2",AUDIO="audio"

and the player fails:

HLS.js error: mediaError - fatal: false - bufferAppendingError
HLS.js error: mediaError - fatal: false - bufferAppendError
VIDEOJS: ERROR: (CODE:4 MEDIA_ERR_SRC_NOT_SUPPORTED) The media could not be loaded,
either because the server or network failed or because the format is not supported.

Everything else in the chain works: ffmpeg muxes FLAC into fMP4 without complaint, the transcoding job completes, the video is published, and the video renditions are unaffected. Only the codec string is wrong, and the fallback is silent apart from a logger.warn, so the failure surfaces only in the browser.

Note that stock PeerTube cannot currently produce a non-AAC HLS audio rendition: the audio encoders are libfdk_aac and aac, and canDoQuickAudioTranscode() requires the source to be AAC. Today this is reached through a transcoding plugin whose audio builder returns copy: true for a non-AAC stream, which the plugin API explicitly allows. The same silent breakage would apply to any codec added later.

Steps to reproduce

  1. Register a transcoding plugin whose audio builder returns { copy: true } for a non-AAC source.
  2. Upload a video whose audio track is FLAC, stereo, 44.1 kHz, with HLS enabled.
  3. Open the video once transcoding finishes.

Describe the expected behavior

The manifest describes the codec the rendition actually contains, and the browser plays it. Chromium supports FLAC in MP4, including through Media Source Extensions, which is what hls.js uses:

javascript
document.createElement('video').canPlayType('audio/mp4; codecs="flac"')  // "probably"
MediaSource.isTypeSupported('audio/mp4; codecs="flac"')                  // true
MediaSource.isTypeSupported('audio/mp4; codecs="fLaC"')                  // true

Adding the mapping would be enough for this case:

typescript
if (audioCodecName === 'flac') return 'fLaC'

fLaC is the ISO BMFF sample entry name for FLAC; Chromium accepts either spelling.

Separately, and independent of FLAC: returning a wrong codec string as a fallback guarantees an unplayable stream, whereas CODECS is an optional attribute in the HLS specification. Returning '' for an unknown codec — which hls.ts already filters out of the joined list — would let the player work it out instead of being told something false, so any unrecognised codec would fail softly rather than fatally.

Additional information

  • PeerTube instance:

    • URL: local test instance, not publicly reachable
    • Version: 8.2.4
    • NodeJS version: v22.23.2
    • Ffmpeg version: 7.1.5-0+deb13u1 (as shipped in chocobozzz/peertube:v8.2.4-trixie)
  • Browser name, version and platforms on which you could reproduce the bug: Chromium 151.0.7922.173, Linux

  • Link to browser console log if relevant: quoted above — bufferAppendError from hls.js, followed by MEDIA_ERR_SRC_NOT_SUPPORTED from video.js

  • Link to server log if relevant: the transcoding job logs no error; it completes normally and publishes the video

Configuration: HLS enabled with split audio and video.