fix(cctv): key-gate Ottawa, opt-in Québec video, keep shared slots

Review fixes for #1506.

- Ottawa: use the documented camera list and the city's Traffic Camera
  Images API. The pack is skipped with no request unless
  OTTAWA_CAMERA_CERTIFICATE is set; the certificate is added only at
  fetch time inside the pinned /opendata/ path, and each camera is
  fetched at most once a minute through the shared frame cache.
- Québec 511 video is opt-in (CCTV_QUEBEC_VIDEO_ENABLED=1) and loads
  only after the viewer presses Play; selection, auto-hop, scenes and
  voice no longer contact Québec 511. Credit splits locations (MTQ,
  CC BY 4.0) from video (Québec 511). Interrupted play() is no longer
  reported as an unavailable source; the per-frame listener runs only
  while a Québec camera is selected and the canvas rect is cached.
- Catalog cap: reserved Québec and World slots come only from capacity
  above the 4,000 shared slots, so a lower CCTV_MAX_SOURCES thins every
  pack instead of starving the existing ones. dev-fresh and
  .env.example default to 7,516.
- Throttled frames (World, Ottawa): inside the refresh floor with no
  cached frame the proxy serves the placeholder, never Street View; a
  failed fetch backs off for a minute; the cache is bounded by bytes.
- MJPEG first-frame extraction runs only for sources registered as
  MJPEG (Taiwan Highway Bureau), caps a frame at 2 MB, reads in linear
  time, accepts a CRLF preamble and a boundary that already starts with
  "--", and ends a part without Content-Length at the next delimiter.
  THB hosts are registered in the redirect pin list.
- Tests: World loader policy, Québec loader and opt-in, proxy cooldown
  without Street View, Ottawa signing, cap reservations at 7,516, 4,000
  and 48, overlay Play gate, refresh, visibility and teardown. Guard
  tests check the 4,000 shared slots again.
- Remove the unused standalone Québec preview module and public page.
- Docs: DATA_SOURCES, SECURITY, CURRENT-STATE, CCTV_INTEGRATION, README,
  .env.example, changelog fragment renamed to its full scope.
This commit is contained in:
Said Turksever committed 2026-11-03 15:31:08 +00:00
1 parent fa4ce4b2a5
commit db8afbae81
43 files changed
+1327 -1110

No files matched your search

-151
View File
@@ -1,151 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="color-scheme" content="dark" />
<title>Québec 511 · Camera 3735 preview</title>
<style>
:root {
color-scheme: dark;
font-family: Inter, 'Segoe UI', sans-serif;
background: #060a0e;
color: #e7f5fb;
}
* {
box-sizing: border-box;
}
body {
min-height: 100vh;
margin: 0;
padding: clamp(20px, 5vw, 56px);
background:
radial-gradient(
ellipse at 12% 0%,
rgba(0, 181, 216, 0.13),
transparent 45%
),
#060a0e;
}
main {
width: min(100%, 1024px);
margin: 0 auto;
}
.eyebrow,
.meta,
.notice,
.source-link {
font-family: 'Cascadia Code', Consolas, monospace;
}
.eyebrow {
margin: 0 0 12px;
color: #5bd8f2;
font-size: 12px;
letter-spacing: 0.16em;
text-transform: uppercase;
}
h1 {
margin: 0;
font-size: clamp(28px, 5vw, 48px);
line-height: 1.08;
font-weight: 650;
}
.meta {
margin: 14px 0 28px;
color: #92a9b4;
font-size: 13px;
}
.player {
overflow: hidden;
border: 1px solid rgba(91, 216, 242, 0.3);
border-radius: 14px;
background: #020405;
box-shadow: 0 20px 70px rgba(0, 0, 0, 0.45);
}
video {
display: block;
width: 100%;
aspect-ratio: 16 / 9;
background: #020405;
}
.notice {
margin: 18px 0;
padding: 14px 16px;
border-left: 2px solid #e9b95f;
background: rgba(233, 185, 95, 0.08);
color: #d8cba9;
font-size: 12px;
line-height: 1.6;
}
.source-link {
display: inline-flex;
align-items: center;
gap: 8px;
color: #71def5;
font-size: 13px;
text-decoration: none;
}
.source-link:hover {
color: #c2f5ff;
text-decoration: underline;
}
.source-link:focus-visible {
outline: 2px solid #71def5;
outline-offset: 4px;
}
</style>
</head>
<body>
<main>
<p class="eyebrow">God’s Eye View · Single-camera preview</p>
<h1>Route 136 at Rue Panet</h1>
<p class="meta">MTQ camera 3735 · Montréal · 45.51651, −73.55020</p>
<section class="player" aria-label="Québec 511 camera video">
<video controls autoplay muted playsinline preload="metadata">
<source
src="https://www.quebec511.info/Carte/Fenetres/camera.ashx?id=3735&format=mp4"
type="video/mp4"
/>
Your browser cannot play this Québec 511 camera feed.
</video>
</section>
<p class="notice">
This page plays the official feed in the browser. God’s Eye shows a
separate paused browser video at the camera’s map position; Québec 511
does not grant pixel access, so it is not a Cesium texture. Location
data: Ministère des Transports et de la Mobilité durable,
<a
href="https://www.donneesquebec.ca/recherche/dataset/camera-de-circulation"
>Caméra de circulation (CC BY 4.0)</a
>.
</p>
<a class="source-link" href="/?welcome=0">
Open God’s Eye CCTV cameras <span aria-hidden="true">↗</span>
</a>
<br />
<a
class="source-link"
href="https://www.quebec511.info/Carte/Fenetres/FenetreVideo.html?id=3735"
target="_blank"
rel="noopener noreferrer"
>
Open official Québec 511 viewer <span aria-hidden="true">↗</span>
</a>
</main>
</body>
</html>