{"record":{"id":"78c1c8bca63844ea","repo":"immich-app/immich","slug":"real-time-transcoding-is-not-enabled","errorCode":null,"errorMessage":"Real-time transcoding is not enabled","messagePattern":"Real-time transcoding is not enabled","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"server/src/services/hls.service.ts","lineNumber":51,"sourceCode":"    }\n  }\n\n  @OnEvent({ name: 'HlsSessionEnd', server: true, workers: [ImmichWorker.Api] })\n  onSessionEnd({ sessionId }: ArgOf<'HlsSessionEnd'>) {\n    this.sessions.delete(sessionId);\n    this.pendingSegments.rejectByPrefix(`${sessionId}:`, 'Session ended');\n  }\n\n  @OnEvent({ name: 'HlsSegmentResult', server: true, workers: [ImmichWorker.Api] })\n  onSegmentResult(event: ArgOf<'HlsSegmentResult'>) {\n    this.pendingSegments.complete(this.getSegmentKey(event), event);\n  }\n\n  async getMainPlaylist(auth: AuthDto, assetId: string) {\n    await this.requireAccess({ auth, permission: Permission.AssetView, ids: [assetId] });\n    const { ffmpeg } = await this.getConfig({ withCache: true });\n    if (!ffmpeg.realtime.enabled) {\n      throw new BadRequestException('Real-time transcoding is not enabled');\n    }\n\n    const asset = await this.videoStreamRepository.getForMainPlaylist(assetId);\n    if (!asset) {\n      throw new NotFoundException('Asset metadata is not yet ready for streaming');\n    }\n\n    // Sharing the sessionId allows only one microservices worker to successfully insert to the session table.\n    // The microservices worker that creates a session owns the transcoding lifecycle for it.\n    const sessionId = this.cryptoRepository.randomUUID();\n    this.websocketRepository.serverSend('HlsSessionRequest', { sessionId, assetId, ownerId: auth.user.id });\n    await this.pendingSessions.wait(sessionId);\n    this.trackSession(sessionId);\n\n    return this.generateMainPlaylist(sessionId, ffmpeg, asset);\n  }\n\n  async getMediaPlaylist(auth: AuthDto, assetId: string, sessionId: string, variantIndex: number, position?: number) {","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/services/hls.service.ts#L33-L69","documentation":"getMainPlaylist serves HLS playlists for real-time transcoded playback. If the server config has ffmpeg.realtime.enabled=false, streaming playlists are not produced, so the endpoint rejects with 400 BadRequestException before touching the asset.","triggerScenarios":"Requesting GET /assets/:id/video/master.m3u8 (or equivalent playlist route) while the transcoding settings use the default non-realtime (throttled/after-upload) transcode mode.","commonSituations":"Mobile/web client attempting HLS streaming playback when admin left transcoding policy at default; config reset after restore; custom settings disabling realtime.","solutions":["Enable real-time transcoding: set transcoding policy/realtime in the admin Transcoding settings (or ffmpeg.realtime.enabled=true in config) and restart.","Use normal progressive playback endpoints instead of the HLS playlist routes.","Upgrade the clients to a version that only requests HLS when realtime is enabled."],"exampleFix":"// before\nffmpeg: { realtime: { enabled: false }, ... }\n// after\nffmpeg: { realtime: { enabled: true, crf: 23 }, ... }","handlingStrategy":"try-catch","validationCode":"const config = await api.getConfig();\nif (!config.ffmpeg.realtime.enabled) console.warn('HLS realtime endpoints unavailable; use progressive playback');","typeGuard":null,"tryCatchPattern":"try {\n  const playlist = await api.getMainPlaylist(assetId);\n} catch (e) {\n  if (/Real-time transcoding is not enabled/.test(e.message)) {\n    fallbackToProgressivePlayback(assetId);\n  } else throw e;\n}","preventionTips":["Check ffmpeg.realtime.enabled in server config before using HLS routes.","Keep client and server versions aligned on transcoding features.","Document that streaming playback requires enabling realtime in admin settings."],"tags":["hls","streaming","config","feature-disabled"],"backgroundTag":"feature-not-enabled","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"}