mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
The catalog fetch now refuses redirects, cancels rejected bodies and reads through the shared capped JSON reader. Duplicate ids are dropped before prioritization so they cannot use up the per-pack cap. Vendor-generic model strings (PTZ, PTZ IP, BOSCH/PTZ) are treated as no model. Comments and credits say why WSDOT rows are skipped (their frames are WSDOT-hosted, outside the pinned origin) and name Newcastle as the partner city that appears.
355 lines
17 KiB
JavaScript
355 lines
17 KiB
JavaScript
export const DEFAULT_CCTV_SOURCE_FILE = 'config/cctv_sources.austin.json';
|
||
/** Austin Open Data portal endpoint for traffic camera records. */
|
||
export const DEFAULT_AUSTIN_ROWS_URL =
|
||
'https://data.austintexas.gov/api/views/b4k4-adkb/rows.json?accessType=DOWNLOAD';
|
||
/** Default cap on Austin cameras after distance-based prioritization. */
|
||
export const DEFAULT_AUSTIN_MAX_SOURCES = 250;
|
||
/**
|
||
* Catalog-wide safety ceiling on served cameras. Each pack already caps
|
||
* itself (nearest-to-anchor first); this bound only matters when the packs
|
||
* together exceed it, and it is then filled round-robin across packs (see
|
||
* cap.js) so no region is silently dropped. Sized above the sum of the
|
||
* default per-pack caps so a default install never trims.
|
||
*/
|
||
export const DEFAULT_CCTV_MAX_SOURCES = 4000;
|
||
/** Hard upper bound for CCTV_MAX_SOURCES; also sizes the health map. */
|
||
export const CCTV_MAX_SOURCES_CEILING = 5000;
|
||
/** Reference point for Austin camera prioritization (Congress & 6th). */
|
||
export const AUSTIN_DOWNTOWN = { lat: 30.2672, lon: -97.7431 };
|
||
/** Caltrans CCTV: one JSON feed per district, identical schema statewide. */
|
||
/** TxDOT ITS: one keyless JSON catalog per district (25 districts statewide). */
|
||
export const TXDOT_ORIGIN = 'https://its.txdot.gov';
|
||
export const TXDOT_CCTV_STATUS_URL = (district) =>
|
||
`${TXDOT_ORIGIN}/its/DistrictIts/GetCctvStatusListByDistrict?districtCode=${encodeURIComponent(district)}`;
|
||
/** Per-camera frame. Returns JSON `{snippet:<base64 jpeg>}`, not an image body;
|
||
* media.js decodes it (fetchTxdotSnapshot) and only for this origin. */
|
||
export const TXDOT_CCTV_SNAPSHOT_URL = `${TXDOT_ORIGIN}/its/DistrictIts/GetCctvSnapshotByIcdId`;
|
||
/** Valid TxDOT district codes (the ITS map's own districtCodes list). */
|
||
export const TXDOT_DISTRICTS = new Set([
|
||
'ABL',
|
||
'AMA',
|
||
'ATL',
|
||
'AUS',
|
||
'BMT',
|
||
'BWD',
|
||
'BRY',
|
||
'CHS',
|
||
'CRP',
|
||
'DAL',
|
||
'ELP',
|
||
'FTW',
|
||
'HOU',
|
||
'LRD',
|
||
'LBB',
|
||
'LFK',
|
||
'ODA',
|
||
'PAR',
|
||
'PHR',
|
||
'SJT',
|
||
'SAT',
|
||
'TYL',
|
||
'WAC',
|
||
'WFS',
|
||
'YKM',
|
||
]);
|
||
/** Districts fetched by default: Austin (the reference camera city) and San
|
||
* Antonio. A statewide default was rejected: per-pack prioritization is
|
||
* nearest-to-any-anchor, so Dallas's dense core would take most slots.
|
||
* CCTV_TXDOT_DISTRICTS opens up the rest ("AUS,SAT,HOU,DAL,FTW" for the five
|
||
* big metros, or any of the 25 codes). */
|
||
export const DEFAULT_TXDOT_DISTRICTS = 'AUS,SAT';
|
||
export const DEFAULT_TXDOT_MAX_SOURCES = 500;
|
||
/** Prioritization anchors: downtown cores of the metro districts a user can
|
||
* select. Cameras rank by distance to the NEAREST anchor, so a widened
|
||
* CCTV_TXDOT_DISTRICTS still ranks sensibly instead of against Austin alone. */
|
||
export const TXDOT_ANCHORS = [
|
||
{ lat: 30.2672, lon: -97.7431 }, // Austin
|
||
{ lat: 29.4241, lon: -98.4936 }, // San Antonio
|
||
{ lat: 29.7604, lon: -95.3698 }, // Houston
|
||
{ lat: 32.7767, lon: -96.797 }, // Dallas
|
||
{ lat: 32.7555, lon: -97.3308 }, // Fort Worth
|
||
];
|
||
/** Ground-elevation priors in metres, by district. The TxDOT payload carries
|
||
* no elevation, and on a keyless (no-tileset) stack the client's ground snap
|
||
* never fires, so this prior is the only height a camera gets there. Texas
|
||
* spans sea level (Houston) to ~1,140 m (El Paso). */
|
||
export const TXDOT_DISTRICT_ELEVATION_M = Object.freeze({
|
||
ABL: 520,
|
||
AMA: 1099,
|
||
ATL: 105,
|
||
AUS: 149,
|
||
BMT: 5,
|
||
BWD: 425,
|
||
BRY: 111,
|
||
CHS: 250,
|
||
CRP: 7,
|
||
DAL: 131,
|
||
ELP: 1140,
|
||
FTW: 199,
|
||
HOU: 15,
|
||
LRD: 132,
|
||
LBB: 992,
|
||
LFK: 91,
|
||
ODA: 890,
|
||
PAR: 185,
|
||
PHR: 30,
|
||
SJT: 585,
|
||
SAT: 198,
|
||
TYL: 165,
|
||
WAC: 143,
|
||
WFS: 289,
|
||
YKM: 70,
|
||
});
|
||
export const TXDOT_DEFAULT_ELEVATION_M = 150;
|
||
export const CALTRANS_CCTV_URL = (district) =>
|
||
`https://cwwp2.dot.ca.gov/data/d${district}/cctv/cctvStatusD${String(district).padStart(2, '0')}.json`;
|
||
/** Districts fetched by default: SF Bay (4), LA (7), San Diego (11), Sacramento (3). */
|
||
export const DEFAULT_CALTRANS_DISTRICTS = '4,7,11,3';
|
||
export const DEFAULT_CALTRANS_MAX_SOURCES = 300;
|
||
/** Prioritization anchors: downtown cores of the four default metros. */
|
||
export const CALTRANS_ANCHORS = [
|
||
{ lat: 37.7793, lon: -122.4193 }, // San Francisco
|
||
{ lat: 34.0537, lon: -118.2428 }, // Los Angeles
|
||
{ lat: 32.7157, lon: -117.1611 }, // San Diego
|
||
{ lat: 38.5816, lon: -121.4944 }, // Sacramento
|
||
];
|
||
/** TfL JamCams: one keyless list endpoint; frames live on a public S3 bucket. */
|
||
export const TFL_JAMCAM_URL = 'https://api.tfl.gov.uk/Place/Type/JamCam';
|
||
export const TFL_IMAGE_ORIGIN =
|
||
'https://s3-eu-west-1.amazonaws.com/jamcams.tfl.gov.uk/';
|
||
export const DEFAULT_TFL_MAX_SOURCES = 250;
|
||
export const LONDON_CENTER = { lat: 51.5074, lon: -0.1278 };
|
||
/** Ontario 511: keyless CARS/511 camera catalog; frame URLs are still images. */
|
||
export const ONTARIO_511_CAMERAS_URL =
|
||
'https://511on.ca/api/v2/get/cameras?format=json&lang=en';
|
||
export const ONTARIO_511_IMAGE_ORIGIN = 'https://511on.ca/map/Cctv/';
|
||
export const DEFAULT_ONTARIO_MAX_SOURCES = 1000;
|
||
export const ONTARIO_ANCHORS = [
|
||
{ lat: 43.4516, lon: -80.4925 }, // Kitchener
|
||
{ lat: 43.6532, lon: -79.3832 }, // Toronto
|
||
{ lat: 45.4215, lon: -75.6972 }, // Ottawa
|
||
{ lat: 43.2557, lon: -79.8711 }, // Hamilton
|
||
{ lat: 42.9849, lon: -81.2453 }, // London, Ontario
|
||
{ lat: 42.3149, lon: -83.0364 }, // Windsor
|
||
];
|
||
/** Fintraffic road weather cameras (Digitraffic): one keyless GeoJSON list
|
||
* covering all of Finland. Each STATION carries N presets (fixed camera views)
|
||
* that share the station position; one preset is one camera here. */
|
||
export const FINTRAFFIC_STATIONS_URL =
|
||
'https://tie.digitraffic.fi/api/weathercam/v1/stations';
|
||
/** Frames: `<origin><presetId>.jpg`. Preset ids are synthesized into this
|
||
* origin rather than read from the payload, so no upstream field can steer the
|
||
* frame proxy off-host. */
|
||
export const FINTRAFFIC_IMAGE_ORIGIN = 'https://weathercam.digitraffic.fi/';
|
||
/** Digitraffic asks every client to identify itself on API calls. */
|
||
export const DIGITRAFFIC_USER = 'gods-eye-view';
|
||
export const DEFAULT_FINTRAFFIC_MAX_SOURCES = 300;
|
||
/** Ground-elevation prior, in metres, for stations that report no altitude.
|
||
* 228 of 809 stations carry a real metre value (median 94 m); the rest report
|
||
* 0, which means "not reported" rather than sea level — Kouvola (~80 m of real
|
||
* elevation) reports 0. The observed median stands in for those. */
|
||
export const FINTRAFFIC_GROUND_ELEVATION_M = 90;
|
||
/** Prioritization anchors: the population centres strung along Finland's main
|
||
* road spine (vt1 Turku, vt3 Tampere, vt4 Jyväskylä–Oulu–Rovaniemi, vt5
|
||
* Kuopio), so a cap keeps national coverage rather than just the capital. */
|
||
export const FINLAND_ANCHORS = [
|
||
{ lat: 60.1699, lon: 24.9384 }, // Helsinki
|
||
{ lat: 60.4518, lon: 22.2666 }, // Turku
|
||
{ lat: 61.4978, lon: 23.761 }, // Tampere
|
||
{ lat: 62.2426, lon: 25.7473 }, // Jyväskylä
|
||
{ lat: 62.8924, lon: 27.677 }, // Kuopio
|
||
{ lat: 65.0121, lon: 25.4651 }, // Oulu
|
||
{ lat: 66.5039, lon: 25.7294 }, // Rovaniemi
|
||
];
|
||
/** Global cap on total CCTV sources served by the proxy: the default per-pack
|
||
* caps summed (Austin 250 + Caltrans 300 + TfL 250 + DriveBC 250). */
|
||
/** DriveBC highway cameras (British Columbia): the keyless camera list served by
|
||
* the DriveBC.ca site (github.com/bcgov/DriveBC.ca). The DataBC HighwayCams CSV
|
||
* lists the same cameras but still carries retired images.drivebc.ca frame URLs,
|
||
* so frames are built from the numeric camera id on the current image host. */
|
||
export const DRIVEBC_WEBCAMS_URL = 'https://www.drivebc.ca/api/webcams/';
|
||
export const DRIVEBC_IMAGE_URL = (id) =>
|
||
`https://www.drivebc.ca/images/${id}.jpg`;
|
||
export const DEFAULT_DRIVEBC_MAX_SOURCES = 250;
|
||
/** Prioritization anchors: downtown Vancouver and Victoria. */
|
||
export const DRIVEBC_ANCHORS = [
|
||
{ lat: 49.2827, lon: -123.1207 }, // Vancouver
|
||
{ lat: 48.4284, lon: -123.3656 }, // Victoria
|
||
];
|
||
/** Tallinn intersection cameras: curated catalog + public stills on ristmikud.tallinn.ee. */
|
||
export const DEFAULT_TALLINN_SOURCE_FILE = 'config/cctv_sources.tallinn.json';
|
||
export const DEFAULT_TALLINN_MAX_SOURCES = 255;
|
||
export const TALLINN_IMAGE_ORIGIN = 'https://ristmikud.tallinn.ee/';
|
||
export const TALLINN_CENTER = { lat: 59.437, lon: 24.753 };
|
||
/** Transpordiamet / Tarktee road-weather cameras: keyless DATEX2 feeds. */
|
||
export const TARKTEE_LOCATIONS_URL =
|
||
'https://tarktee.transpordiamet.ee/api/v1/datex/roadCameraLocations';
|
||
export const TARKTEE_IMAGES_URL =
|
||
'https://tarktee.transpordiamet.ee/api/v1/datex/roadCameraImages';
|
||
export const TARKTEE_IMAGE_ORIGIN = 'https://tarktee.transpordiamet.ee/images/';
|
||
export const DEFAULT_TARKTEE_MAX_SOURCES = 179;
|
||
export const TARKTEE_ANCHORS = [
|
||
{ lat: 59.437, lon: 24.753 }, // Tallinn
|
||
{ lat: 58.378, lon: 26.729 }, // Tartu
|
||
{ lat: 58.3859, lon: 24.4971 }, // Pärnu
|
||
{ lat: 59.3797, lon: 28.1791 }, // Narva
|
||
];
|
||
/** Warendorf (Germany): the Marktplatz municipal webcam from a curated catalog file. */
|
||
export const DEFAULT_WARENDORF_SOURCE_FILE =
|
||
'config/cctv_sources.warendorf.json';
|
||
export const WARENDORF_IMAGE_ORIGINS = Object.freeze([
|
||
'http://webcam.warendorf.de/',
|
||
'https://www.kreis-warendorf.de/',
|
||
]);
|
||
/** Live Traffic NSW (Transport for NSW): keyless public camera catalog. */
|
||
export const NSW_CAMERAS_URL =
|
||
'https://data.livetraffic.com/cameras/traffic-cam.json';
|
||
export const NSW_IMAGE_ORIGIN = 'https://webcams.transport.nsw.gov.au/';
|
||
export const DEFAULT_NSW_MAX_SOURCES = 250;
|
||
export const SYDNEY_CENTER = { lat: -33.8688, lon: 151.2093 };
|
||
/**
|
||
* The NSW webcam host answers non-browser clients with HTTP 200 and a short
|
||
* HTML body instead of the frame (verified 2026-09-13), so the proxy
|
||
* identifies as a browser for that one host. See media.js.
|
||
*/
|
||
export const NSW_IMAGE_USER_AGENT =
|
||
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';
|
||
/**
|
||
* Longest NSW `view` sentence still usable as a label. NSW occasionally
|
||
* repurposes `view` for a multi-paragraph works notice; real descriptions top
|
||
* out around 120 characters.
|
||
*/
|
||
export const NSW_MAX_VIEW_LABEL = 140;
|
||
/** Open Calgary traffic cameras: one keyless Socrata endpoint for the whole
|
||
* city; frames are stills on a City of Calgary host. */
|
||
export const DEFAULT_CALGARY_ROWS_URL =
|
||
'https://data.calgary.ca/resource/k7p9-kppz.json?$limit=500';
|
||
/** The only origin Calgary camera frames may come from. The catalog publishes
|
||
* most rows as `http://`; that host serves HTTPS and 301-redirects to it, so
|
||
* URLs are upgraded and then pinned here before registration. */
|
||
export const CALGARY_IMAGE_ORIGIN = 'https://trafficcam.calgary.ca/';
|
||
export const DEFAULT_CALGARY_MAX_SOURCES = 220;
|
||
/** Centre Street / 7 Avenue: the prioritization anchor. */
|
||
export const CALGARY_DOWNTOWN = { lat: 51.0461, lon: -114.0626 };
|
||
/** Hard ceiling on the Calgary catalog body. The whole city is ~215 rows and
|
||
* under 100 KB; this only exists so an upstream that streams an unbounded
|
||
* body cannot be buffered without limit. */
|
||
export const CALGARY_MAX_CATALOG_BYTES = 4 * 1024 * 1024;
|
||
|
||
/** Statens vegvesen (Norway) road cameras: the keyless OGC API Features view
|
||
* of the official DATEX 3.1 CCTV site table, one GeoJSON request for the whole
|
||
* country (~900 cameras). The raw DATEX node needs an account; this view does
|
||
* not. Frames are stills on the agency's camera host. */
|
||
export const DEFAULT_VEGVESEN_CCTV_URL =
|
||
'https://ogckart-sn1.atlas.vegvesen.no/ogc/features/v1/collections/datex_3_1:CctvSimple/items?f=application/geo%2Bjson&limit=5000';
|
||
/** The only origin Vegvesen camera frames may come from. */
|
||
export const VEGVESEN_IMAGE_ORIGIN =
|
||
'https://kamera.atlas.vegvesen.no/api/images/';
|
||
/** Live HLS for the ~140 cameras that publish video; only this exact
|
||
* per-camera manifest path is registered. */
|
||
export const VEGVESEN_VIDEO_URL = (cameraId) =>
|
||
`https://kamera.vegvesen.no/public/${cameraId}/manifest.m3u8`;
|
||
/** Above the ~850 working cameras so a default install keeps them all, while
|
||
* staying close to them: the per-pack defaults are meant to sum to no more
|
||
* than DEFAULT_CCTV_MAX_SOURCES. */
|
||
export const DEFAULT_VEGVESEN_MAX_SOURCES = 900;
|
||
/** Hard ceiling on the catalog body. The whole country is ~800 KB. */
|
||
export const VEGVESEN_MAX_CATALOG_BYTES = 8 * 1024 * 1024;
|
||
/** Prioritization anchors: the largest cities from south to north, so a cap
|
||
* keeps national coverage rather than just the capital region. */
|
||
export const NORWAY_ANCHORS = [
|
||
{ lat: 59.9139, lon: 10.7522 }, // Oslo
|
||
{ lat: 60.3913, lon: 5.3221 }, // Bergen
|
||
{ lat: 58.97, lon: 5.7331 }, // Stavanger
|
||
{ lat: 63.4305, lon: 10.3951 }, // Trondheim
|
||
{ lat: 58.1467, lon: 7.9956 }, // Kristiansand
|
||
{ lat: 67.2804, lon: 14.4049 }, // Bodø
|
||
{ lat: 69.6492, lon: 18.9553 }, // Tromsø
|
||
];
|
||
|
||
/** NYC DOT Traffic Management Center cameras: one keyless JSON list for the
|
||
* five boroughs (~980 cameras). Frames are stills synthesized from each
|
||
* camera UUID on the city's webcam host — never taken from the payload. */
|
||
export const NYC_CAMERAS_URL = 'https://webcams.nyctmc.org/api/cameras';
|
||
/** The only origin NYC camera frames may come from. The catalog's `imageUrl`
|
||
* is ignored; the registered path is always this origin plus a validated
|
||
* UUID plus `/image`. */
|
||
export const NYC_IMAGE_ORIGIN = 'https://webcams.nyctmc.org/api/cameras/';
|
||
export const NYC_IMAGE_URL = (id) => `${NYC_IMAGE_ORIGIN}${id}/image`;
|
||
export const NYC_CAMERA_ID_RE =
|
||
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
||
export const DEFAULT_NYC_MAX_SOURCES = 250;
|
||
/** Hard ceiling on the NYC catalog body. The live list is ~980 rows / ~250 KB;
|
||
* this only exists so an upstream that streams an unbounded body cannot be
|
||
* buffered without limit. */
|
||
export const NYC_MAX_CATALOG_BYTES = 4 * 1024 * 1024;
|
||
/** Ground-elevation prior in metres. Matches the New York CITY_POIS prior;
|
||
* the client's one-shot ground snap corrects it wherever 3D tiles load. */
|
||
export const NYC_GROUND_ELEVATION_M = 10;
|
||
/** Prioritization anchors: one per borough so a cap keeps citywide coverage
|
||
* rather than Midtown alone. */
|
||
export const NYC_ANCHORS = [
|
||
{ lat: 40.758, lon: -73.9855 }, // Manhattan (Times Square)
|
||
{ lat: 40.7128, lon: -74.006 }, // Lower Manhattan
|
||
{ lat: 40.6782, lon: -73.9442 }, // Brooklyn
|
||
{ lat: 40.7282, lon: -73.7949 }, // Queens
|
||
{ lat: 40.8448, lon: -73.8648 }, // Bronx
|
||
{ lat: 40.5795, lon: -74.1502 }, // Staten Island
|
||
];
|
||
|
||
/** DelDOT CCTV: one keyless statewide JSON catalog; live video via RTMP-over-HTTP (rtmpt:80). */
|
||
export const DELDOT_CCTV_URL = 'https://tmc.deldot.gov/json/videocamera.json';
|
||
export const DEFAULT_DELDOT_MAX_SOURCES = 300;
|
||
export const DELDOT_ANCHORS = [
|
||
{ lat: 39.7459, lon: -75.5466 }, // Wilmington (New Castle)
|
||
{ lat: 39.1582, lon: -75.5244 }, // Dover (Kent)
|
||
{ lat: 38.6906, lon: -75.3877 }, // Georgetown (Sussex)
|
||
];
|
||
|
||
/** King County, WA road cameras: keyless public ArcGIS FeatureServer layer
|
||
* ("King County and WSDOT Traffic Cameras", King County DOT Road Services).
|
||
* GeoJSON with WGS84 point geometry. `outFields` is an explicit list on
|
||
* purpose: the layer also carries asset-administration columns (including
|
||
* staff names in `ModifiedBy`) that must never be fetched. Uniquely among the
|
||
* packs, the county publishes each camera's hardware `Manufacturer`/`Model`
|
||
* (Cohu 3950/3965, Bosch AUTODOME, Axis Q6135-LE, …), carried through as the
|
||
* source's `model`. */
|
||
export const KING_COUNTY_CAMERAS_URL =
|
||
'https://services.arcgis.com/Ej0PsM5Aw677QF1W/arcgis/rest/services/TRAFFICCAMERA_POINT_2029/FeatureServer/0/query?where=1%3D1&outFields=AssetID,Location,ImageURL,Live,Model,Manufacturer,Owner,CurrentStatus&f=geojson';
|
||
/** Frames come only from the county's own image handler host. */
|
||
export const KING_COUNTY_IMAGE_ORIGIN = 'https://info.kingcounty.gov/';
|
||
/** The whole catalog is ~125 rows (~59 live county cameras); no thinning by
|
||
* default. */
|
||
export const DEFAULT_KING_COUNTY_MAX_SOURCES = 125;
|
||
/** Prioritization anchor: Renton, roughly central to the county road network. */
|
||
export const KING_COUNTY_ANCHORS = [{ lat: 47.4829, lon: -122.2171 }];
|
||
/** Hard ceiling on the King County catalog body. The whole layer is ~125 rows
|
||
* and well under 100 KB; this only exists so an upstream that streams an
|
||
* unbounded body cannot be buffered without limit. */
|
||
export const KING_COUNTY_MAX_CATALOG_BYTES = 1024 * 1024;
|
||
|
||
/** Camera CATALOGS change rarely; 15 min keeps multi-megabyte upstream list refetches (Austin rows.json + 4 Caltrans districts + TfL + Ontario 511) infrequent. Frames are fetched per-request and are unaffected. */
|
||
export const CCTV_SOURCE_CACHE_MS = 15 * 60 * 1000;
|
||
/** Per-provider catalog-fetch timeout. Bounds the worst-case refresh so one
|
||
* stalled upstream can't leave getCctvSources (and thus every CCTV route)
|
||
* pending forever — a hung fetch aborts, the loader returns [], and
|
||
* serve-stale/other packs take over. */
|
||
export const CCTV_SOURCE_FETCH_TIMEOUT_MS = 15 * 1000;
|
||
/** Individual CCTV image fetches must settle before the active 10-second
|
||
* client refresh cadence. A bounded miss can fall through to Street View or
|
||
* the synthetic frame instead of leaving the browser preview pending. */
|
||
export const CCTV_FRAME_FETCH_TIMEOUT_MS = 8 * 1000;
|
||
|
||
/** Maximum buffered snapshot size. */
|
||
export const CCTV_FRAME_MAX_BODY_BYTES = 16 * 1024 * 1024;
|
||
|
||
/** Deadline for upstream response headers; live bodies keep streaming afterward. */
|
||
export const CCTV_MEDIA_FETCH_TIMEOUT_MS = 15 * 1000;
|
||
/** Silence a live body may carry before the relay gives up on it. Twice the
|
||
* header deadline, because a camera that is merely slow between frames is far
|
||
* more common than one that has died mid-stream, and a viewer would rather
|
||
* wait than be dropped. */
|
||
export const CCTV_MEDIA_IDLE_TIMEOUT_MS = 30 * 1000;
|
||
/** Declared size ceiling for fixed media responses. */
|
||
export const CCTV_MEDIA_MAX_BODY_BYTES = 64 * 1024 * 1024;
|