{"cors":{"allow_headers":"Content-Type, Range","allow_methods":"GET, OPTIONS, HEAD","allow_origin":"*","enabled":true,"note":"CORS headers are automatically added to all responses. Configure via environment variables: CORS_ALLOW_ORIGIN, CORS_ALLOW_METHODS, CORS_ALLOW_HEADERS"},"endpoints":{"/health":{"description":"Health check","method":"GET"},"/images1":{"config":{"CAMERA_BASE_DIR":"/mnt/storage/guardiao/cameras","CAMERA_PIC_PATH_TEMPLATE":"{camera_id}/pic/{date}/01/processed","note":"Sobrepon\u00edveis em ~/LT-VMS/.env por host. Layouts: 'cameras' (com /processed) ou 'cameras-new' (sem /processed)."},"description":"Devolve as 3 imagens (Base64) seguintes ao filename indicado, lidas de CAMERA_BASE_DIR + CAMERA_PIC_PATH_TEMPLATE. N\u00e3o exp\u00f5e o caminho absoluto na resposta.","method":"GET","parameters":{"camera_ip":"Camera ID (required); usado como `{camera_id}` no template","filename":"Reference filename `<id>-AAAAMMDD-HHMMSS.jpg` (required); o `AAAAMMDD` \u00e9 usado como `{date}` no template"}},"/playlist":{"description":"Generate M3U8 playlist up to a timestamp","example":"/playlist?path_name=SP-JGR-52&timestamp=2025-11-09T19%3A06%3A48.760456Z","example_http":"/playlist?path_name=SP-JGR-52&timestamp=2025-11-09T19%3A06%3A48.760456Z&use_http=true","method":"GET","parameters":{"hours_back":"Optional hours back from timestamp (float)","http_base_url":"Opcional; sen\u00e3o HTTP_BASE_URL ou o url_root do pedido. Atr\u00e1s de proxy, defina HTTP_BASE_URL","path_name":"MediaMTX path name (required)","timestamp":"URL-encoded timestamp in RFC3339 format (required)","use_http":"Optional; true=URLs http(s) para .ts (default env PLAYLIST_USE_HTTP_DEFAULT, true). false=file://"}},"/playlist/range":{"description":"Generate M3U8 playlist for a custom time range","example":"/playlist/range?path_name=SP-JGR-52&start_timestamp=2025-11-09T17%3A00%3A00Z&end_timestamp=2025-11-09T19%3A06%3A48Z","example_http":"/playlist/range?path_name=SP-JGR-52&start_timestamp=2025-11-09T17%3A00%3A00Z&end_timestamp=2025-11-09T19%3A06%3A48Z&use_http=true","method":"GET","parameters":{"end_timestamp":"URL-encoded end timestamp in RFC3339 format (required)","http_base_url":"Opcional; sen\u00e3o HTTP_BASE_URL ou o url_root do pedido. Atr\u00e1s de proxy, defina HTTP_BASE_URL","path_name":"MediaMTX path name (required)","start_timestamp":"URL-encoded start timestamp in RFC3339 format (required)","use_http":"Optional; true=URLs http(s) para .ts (default env PLAYLIST_USE_HTTP_DEFAULT, true). false=file://"}},"/video/<path_name>/<filename>":{"description":"Serve video files via HTTP","example":"/video/SP-JGR-52/2025-11-09_19-06-48-760456.ts","method":"GET","parameters":{"filename":"Video filename (e.g., 2025-11-09_19-06-48-760456.ts)","path_name":"MediaMTX path name (e.g., SP-JGR-52)"}}},"errors":{"error_codes":{"after_last_recording":"HTTP 404 \u2014 janela depois da \u00faltima grava\u00e7\u00e3o, mas n\u00e3o no futuro (gap de grava\u00e7\u00e3o).","before_history":"HTTP 404 \u2014 janela inteiramente anterior \u00e0 grava\u00e7\u00e3o mais antiga.","future_window":"HTTP 422 \u2014 janela inteiramente no futuro do rel\u00f3gio do servidor.","gap_within_history":"HTTP 404 \u2014 janela dentro do hist\u00f3rico mas sem ficheiros (gap entre grava\u00e7\u00f5es).","internal_error":"HTTP 500 \u2014 exce\u00e7\u00e3o a gerar o playlist (ver logs).","invalid_range":"HTTP 400 \u2014 start_timestamp/end_timestamp inv\u00e1lido ou start > end.","no_recordings":"HTTP 404 \u2014 c\u00e2mera sem qualquer grava\u00e7\u00e3o no servidor.","recordings_dir_missing":"HTTP 404 \u2014 diret\u00f3rio /mnt/storage/.../<camera> inexistente."},"fallback_recent_optin":"Para preservar o comportamento at\u00e9 2.4.x (HTTP 200 com 12 segs mais recentes em vez de 4xx), passar `&fallback_recent=true` na URL. \u00datil s\u00f3 para integra\u00e7\u00f5es antigas; quem ler `error_code` deve evitar este opt-in.","note":"A partir da 2.5.0, /playlist e /playlist/range deixam de devolver fallback silencioso (12 segs de 'agora') quando a janela pedida n\u00e3o tem segmentos. Devolvem um JSON estruturado + HTTP 422/404 com error_code est\u00e1vel e mensagem em PT-BR pronta a mostrar ao utilizador final.","payload_shape":{"available":"{earliest_local, earliest_utc, latest_local, latest_utc, count}","error_code":"est\u00e1vel (machine-readable)","message":"PT-BR (mostrar ao utilizador final)","path_name":"string","requested":"{start_local, end_local, start_utc, end_utc, timestamp_local, timestamp_utc, tz_mode}","server":"{now_local, now_utc, tz, tz_offset}"}},"server_time":{"now_local":"2026-05-19T00:38:37.773918","now_utc":"2026-05-19T03:38:37.773918Z","offset":"-03:00","tz":"America/Sao_Paulo"},"service":"\"LT API Eventos\"","tz_modes":{"default":"utc","examples":["/playlist/range?...&start_timestamp=2026-05-05T01:40:00.000Z          \u2192 _22-40-XX.ts (default utc, em host UTC-3)","/playlist/range?...&start_timestamp=2026-05-05T01:40:00.000Z&tz=utc   \u2192 _22-40-XX.ts (idem; expl\u00edcito)","/playlist/range?...&start_timestamp=2026-05-04T22:40:00.000Z&tz=local \u2192 _22-40-XX.ts (Z ignorado)"],"note":"Em /playlist, /playlist/range e /export/range, o par\u00e2metro opcional 'tz' controla como o `Z`/offset na URL \u00e9 interpretado. N\u00c3O altera o nome dos ficheiros (sempre em hora local do servidor).","values":{"local":"Trata data/hora como r\u00f3tulo LITERAL igual ao do nome do ficheiro (ex.: pedir 22:40 \u2192 devolver `_22-40-XX.ts`). Ignora o `Z`/offset. \u00datil para clientes que enviam o valor raw do date-picker com `Z` colado por engano. Em 2.4.0 passa a ser opt-in expl\u00edcito (`&tz=local`).","utc":"Interpreta\u00e7\u00e3o RFC3339 estrita: `Z`/offset \u2192 UTC absoluto. O servidor converte para a TZ local antes da busca. Adequado a clientes que usam Date#toISOString() no browser, ao reverse-proxy SaaS e a qualquer integrador que envie timestamps com `Z`/offset verdadeiros. Default desde 2.4.0."}},"tz_response_headers":{"headers":["X-Time-Mode (ex: 'local' ou 'utc')","X-Server-Timezone (ex: 'America/Sao_Paulo')","X-Server-Tz-Offset (ex: '-03:00')","X-Range-Start-Local / X-Range-Start-Utc","X-Range-End-Local / X-Range-End-Utc","X-Timestamp-Local / X-Timestamp-Utc (apenas /playlist)"],"m3u8_comments":"As mesmas chaves s\u00e3o tamb\u00e9m emitidas ap\u00f3s `#EXTM3U` como coment\u00e1rios '# time-mode: ...', '# server-tz: ...', '# range-start-local: ...' (ignorados por qualquer parser HLS).","note":"Toda resposta de /playlist e /playlist/range inclui estes headers HTTP com a hora local do servidor (TZ onde os ficheiros .ts foram nomeados), o equivalente UTC e o modo aplicado."},"version":"1.5"}
