{"record":{"id":"df3c7d1564da3bd4","repo":"immich-app/immich","slug":"codec-codec-does-not-support-hls-codec-strings","errorCode":null,"errorMessage":"Codec '${codec}' does not support HLS codec strings","messagePattern":"Codec '(.+?)' does not support HLS codec strings","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/src/utils/media.ts","lineNumber":64,"sourceCode":"const pickLevel = (levels: CodecLevel[], frame: number, rate: number) =>\n  levels.find((level) => frame <= level.maxFrame && rate <= level.maxRate) ?? levels.at(-1)!;\n\nexport const getCodecString = (codec: VideoCodec, width: number, height: number, fps: number): string => {\n  switch (codec) {\n    case VideoCodec.H264: {\n      const macroblocks = Math.ceil(width / 16) * Math.ceil(height / 16);\n      return `avc1.6400${pickLevel(H264_LEVELS, macroblocks, macroblocks * fps).token}`;\n    }\n    case VideoCodec.Hevc: {\n      const samples = width * height;\n      return `hvc1.1.6.${pickLevel(HEVC_LEVELS, samples, samples * fps).token}.B0`;\n    }\n    case VideoCodec.Av1: {\n      const samples = width * height;\n      return `av01.0.${pickLevel(AV1_LEVELS, samples, samples * fps).token}.08`;\n    }\n    default: {\n      throw new Error(`Codec '${codec}' does not support HLS codec strings`);\n    }\n  }\n};\n\nexport class BaseConfig implements VideoCodecSWConfig {\n  readonly presets = ['veryslow', 'slower', 'slow', 'medium', 'fast', 'faster', 'veryfast', 'superfast', 'ultrafast'];\n  protected constructor(\n    protected config: ConfigFFmpegDto,\n    protected tune: VideoTuning = { strictGop: false, lowLatency: false },\n  ) {}\n\n  static create(config: ConfigFFmpegDto, interfaces: VideoInterfaces, tune?: VideoTuning) {\n    if (config.accel === TranscodeHardwareAcceleration.Disabled) {\n      return BaseConfig.getSWCodecConfig(config, tune);\n    }\n    return BaseConfig.getHWCodecConfig(config, interfaces, tune);\n  }\n","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/utils/media.ts#L46-L82","documentation":"getCodecString builds the HLS CODECS attribute string for a target video codec, but only H.264, HEVC, and AV1 have defined codec-string builders. Other codecs (e.g. VP9 or unknown values) cannot be represented in this HLS string, so the default branch throws.","triggerScenarios":"Transcoding configured with targetVideoCodec set to a codec without an HLS codec-string case (e.g. VideoCodec.Vp9) while generating HLS output.","commonSituations":"Choosing VP9 as the target codec expecting it to work everywhere; config from experimental versions; enum value drift after codec additions/removals.","solutions":["Switch targetVideoCodec to H.264, HEVC, or AV1 for HLS transcoding","If VP9 output is required, use a non-HLS delivery path (e.g. MP4/WebM progressive)","Upgrade Immich if a newer version added codec-string support for your codec"],"exampleFix":"// before\nconfig.targetVideoCodec = VideoCodec.Vp9;\nconst str = getCodecString(config.targetVideoCodec, w, h, fps);\n// after\nconfig.targetVideoCodec = VideoCodec.Hevc;\nconst str = getCodecString(config.targetVideoCodec, w, h, fps);","handlingStrategy":"validation","validationCode":"const HLS_CODECS = ['h264', 'hevc', 'av1'];\nif (!HLS_CODECS.includes(config.targetVideoCodec)) {\n  throw new Error(`${config.targetVideoCodec} cannot be used for HLS; pick h264/hevc/av1`);\n}","typeGuard":"const supportsHls = (c) => c === 'h264' || c === 'hevc' || c === 'av1';","tryCatchPattern":"try {\n  const s = getCodecString(config.targetVideoCodec, w, h, fps);\n} catch (e) {\n  if (/does not support HLS codec strings/.test(e.message)) {\n    // fall back to a supported codec or non-HLS delivery\n  }\n}","preventionTips":["Restrict codec selection UI to HLS-capable codecs when generating HLS","Keep config enum values synced with the server version","Test transcode configs in a staging instance"],"tags":["video","ffmpeg","hls","codec"],"backgroundTag":"invalid-enum-value","analyzedSha":"e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c","analyzedAt":"2026-09-15T07:20:19.675Z","contentChangedAt":"2026-09-15T07:20:19.675Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}