feat(intro): v2 — cities, accelerating sweep, detections, thriller sound design

- City engine: Esri ground, OSM buildings that rise with the scan, road
  ribbons carrying modelled traffic coloured by congestion, NYC DOT cameras,
  real ADS-B, MBTA GTFS lines + realtime vehicles, LAX runways with approach
  strobes, Fort Bragg restricted volumes, Everest terrain with contours.
- Indexing keeps accelerating into a 260-capture global sweep while the
  planet whips a full turn.
- The eye opens: aperture blades, sensor array waking, optics calibration,
  radar sweep, orbiting coordinate ring.
- Camera wall with YOLOv8n detections and a city-pulse trace.
- Ends on GOD'S EYE VIEW / OMNISCIENCE.
- audio/sfx.py: sound design only, built to sit under a music track.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01KqP857pippaUs6konSDfe8
This commit is contained in:
Claude committed 2026-10-19 01:10:39 +00:00
1 parent e9ddc37788
commit 02e535cb55
30 files changed
+8921 -1442

No files matched your search

@@ -0,0 +1,82 @@
"""MBTA static GTFS -> city/boston/transit.json (subway, Mattapan, commuter rail, bus).
usage: python3 build_transit.py <dir with routes.txt shapes.txt trips.txt>"""
import csv, json, math, os, sys
from collections import defaultdict
sys.path.insert(0, os.path.dirname(__file__))
from common import SCENES, enu
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
G = sys.argv[1]
H = SCENES['boston'][2]; M = H + 1000
def rdp(pts, eps):
if len(pts) < 3: return pts
keep = [False] * len(pts); keep[0] = keep[-1] = True
stack = [(0, len(pts) - 1)]
while stack:
a, b = stack.pop()
ax, ay = pts[a]; bx, by = pts[b]; dx, dy = bx - ax, by - ay; L = math.hypot(dx, dy)
best, bi = -1, -1
for i in range(a + 1, b):
px, py = pts[i]
d = abs(dy * (px - ax) - dx * (py - ay)) / L if L else math.hypot(px - ax, py - ay)
if d > best: best, bi = d, i
if best > eps:
keep[bi] = True; stack += [(a, bi), (bi, b)]
return [p for p, k in zip(pts, keep) if k]
def length(p): return sum(math.hypot(p[i+1][0]-p[i][0], p[i+1][1]-p[i][1]) for i in range(len(p)-1))
routes = {}
for r in csv.DictReader(open(os.path.join(G, 'routes.txt'), encoding='utf-8-sig')):
t = int(r['route_type'])
if t not in (0, 1, 2, 3): continue
if 'Replacement' in r['route_desc'] or r['route_id'].startswith('Shuttle'): continue
name = r['route_short_name'] or r['route_long_name']
if t == 3 and r['route_short_name'] and r['route_long_name']:
name = f"{r['route_short_name']} {r['route_long_name']}"
routes[r['route_id']] = {'name': name, 'color': '#' + (r['route_color'] or '888888').upper(), 'type': t}
shape_rd = {}
for t in csv.DictReader(open(os.path.join(G, 'trips.txt'), encoding='utf-8-sig')):
if t['route_id'] in routes and t['shape_id']:
shape_rd.setdefault(t['shape_id'], (t['route_id'], t['direction_id']))
shapes = defaultdict(list)
for s in csv.DictReader(open(os.path.join(G, 'shapes.txt'), encoding='utf-8-sig')):
if s['shape_id'] in shape_rd:
shapes[s['shape_id']].append((int(s['shape_pt_sequence']), float(s['shape_pt_lat']), float(s['shape_pt_lon'])))
best = {} # (route, dir) -> (len_in_square, segments)
for sid, pts in shapes.items():
pts.sort()
xy = [enu('boston', la, lo) for _, la, lo in pts]
if not any(abs(x) <= H and abs(y) <= H for x, y in xy): continue # must pass within the square
segs, cur = [], []
for i, (x, y) in enumerate(xy):
if abs(x) <= M and abs(y) <= M:
if not cur and i > 0: cur.append(xy[i-1]) # carry edge point
cur.append((x, y))
elif cur:
cur.append((x, y)); segs.append(cur); cur = []
if cur: segs.append(cur)
segs = [rdp(s, 2.0) for s in segs if len(s) > 1]
L = sum(length(s) for s in segs)
key = shape_rd[sid]
if key not in best or L > best[key][0]: best[key] = (L, segs)
out_shapes, seen = [], set()
for (rid, d), (L, segs) in sorted(best.items()):
for s in segs:
flat = tuple(round(v, 1) for p in s for v in p)
if (rid, flat) in seen: continue
seen.add((rid, flat))
out_shapes.append([rid] + list(flat))
used = {s[0] for s in out_shapes}
out = {'routes': {k: v for k, v in routes.items() if k in used}, 'shapes': out_shapes,
'source': 'MBTA GTFS ' + open(os.path.join(G, 'feed_info.txt')).read().splitlines()[1].split(',"')[1].split('"')[0]}
json.dump(out, open(os.path.join(ROOT, 'city', 'boston', 'transit.json'), 'w'), separators=(',', ':'))
bytype = defaultdict(int)
for k in used: bytype[routes[k]['type']] += 1
print('routes', len(used), dict(bytype), 'shapes', len(out_shapes), 'pts', sum((len(s)-1)//2 for s in out_shapes))
print('rail routes:', sorted(k for k in used if routes[k]['type'] != 3))
print('missing requested:', [k for k in ['Red','Orange','Blue','Green-B','Green-C','Green-D','Green-E','Mattapan'] if k not in used])
+15
View File
@@ -0,0 +1,15 @@
import math
SCENES = {
'nyc': (40.7400, -73.9900, 3500),
'boston': (42.3555, -71.0605, 3200),
'lax': (33.9425, -118.4081, 3500),
'bragg': (35.1580, -79.0090, 6000),
}
def enu(slug, lat, lon):
lat0, lon0, _ = SCENES[slug]
x = (lon - lon0) * math.cos(math.radians(lat0)) * 111320
y = (lat - lat0) * 110540
return round(x, 1), round(y, 1)
def inside(slug, x, y, margin=0.0):
h = SCENES[slug][2] + margin
return abs(x) <= h and abs(y) <= h
+76
View File
@@ -0,0 +1,76 @@
"""YOLOv8n (ONNX, CPU) over cctv/cam_*.jpg and cctv/nyc/*.jpg -> cctv/detections.json.
Model auto-downloads to tools/live/models/yolov8n.onnx (git-ignored)."""
import glob, json, os, sys, time, requests
import numpy as np, onnxruntime as ort
from PIL import Image, ImageDraw
from collections import Counter
HERE = os.path.dirname(os.path.abspath(__file__)); ROOT = os.path.abspath(os.path.join(HERE, '..', '..'))
MODEL = os.path.join(HERE, 'models', 'yolov8n.onnx')
MODEL_URL = 'https://huggingface.co/Kalray/yolov8/resolve/main/yolov8n.onnx'
KEEP = {0: 'person', 1: 'bicycle', 2: 'car', 3: 'motorcycle', 5: 'bus', 7: 'truck', 9: 'traffic light', 11: 'stop sign'}
CONF, IOU, S = 0.16, 0.45, 640
if not os.path.exists(MODEL):
os.makedirs(os.path.dirname(MODEL), exist_ok=True)
open(MODEL, 'wb').write(requests.get(MODEL_URL, timeout=120).content)
sess = ort.InferenceSession(MODEL, providers=['CPUExecutionProvider'])
inp = sess.get_inputs()[0].name
def nms(b, s, thr):
order = s.argsort()[::-1]; keep = []
while order.size:
i = order[0]; keep.append(i)
xx0 = np.maximum(b[i, 0], b[order[1:], 0]); yy0 = np.maximum(b[i, 1], b[order[1:], 1])
xx1 = np.minimum(b[i, 2], b[order[1:], 2]); yy1 = np.minimum(b[i, 3], b[order[1:], 3])
inter = np.clip(xx1 - xx0, 0, None) * np.clip(yy1 - yy0, 0, None)
a = (b[:, 2] - b[:, 0]) * (b[:, 3] - b[:, 1])
iou = inter / (a[i] + a[order[1:]] - inter + 1e-9)
order = order[1:][iou <= thr]
return keep
def detect(path):
im = Image.open(path).convert('RGB'); W, H = im.size
r = min(S / W, S / H); nw, nh = round(W * r), round(H * r); px, py = (S - nw) // 2, (S - nh) // 2
canvas = Image.new('RGB', (S, S), (114, 114, 114)); canvas.paste(im.resize((nw, nh), Image.BILINEAR), (px, py))
x = np.asarray(canvas, dtype=np.float32).transpose(2, 0, 1)[None] / 255.0
p = sess.run(None, {inp: x})[0][0].T # 8400 x 84
sc = p[:, 4:]; cls = sc.argmax(1); conf = sc.max(1)
m = (conf >= CONF) & np.isin(cls, list(KEEP))
p, cls, conf = p[m], cls[m], conf[m]
if not len(p): return []
b = np.stack([p[:, 0] - p[:, 2] / 2, p[:, 1] - p[:, 3] / 2, p[:, 0] + p[:, 2] / 2, p[:, 1] + p[:, 3] / 2], 1)
out = []
for c in np.unique(cls): # class-wise NMS
idx = np.where(cls == c)[0]
for k in nms(b[idx], conf[idx], IOU):
j = idx[k]; x0, y0, x1, y1 = b[j]
x0 = min(max((x0 - px) / r / W, 0), 1); x1 = min(max((x1 - px) / r / W, 0), 1)
y0 = min(max((y0 - py) / r / H, 0), 1); y1 = min(max((y1 - py) / r / H, 0), 1)
if x1 - x0 > 0 and y1 - y0 > 0:
out.append([round(float(x0), 4), round(float(y0), 4), round(float(x1), 4), round(float(y1), 4), round(float(conf[j]), 3), KEEP[int(c)]])
return sorted(out, key=lambda d: -d[4])
COL = {'person': (255, 60, 60), 'car': (60, 200, 255), 'truck': (255, 180, 0), 'bus': (255, 0, 255), 'bicycle': (0, 255, 120),
'motorcycle': (180, 255, 0), 'traffic light': (255, 255, 255), 'stop sign': (255, 0, 0)}
def render(path, dets, dst):
im = Image.open(path).convert('RGB'); W, H = im.size; d = ImageDraw.Draw(im)
for x0, y0, x1, y1, c, n in dets:
d.rectangle([x0 * W, y0 * H, x1 * W, y1 * H], outline=COL[n], width=2)
d.text((x0 * W + 2, max(0, y0 * H - 11)), f'{n} {c:.2f}', fill=COL[n])
im.save(dst, quality=90)
if __name__ == '__main__':
files = sorted(glob.glob(os.path.join(ROOT, 'cctv', 'cam_*.jpg'))) + sorted(glob.glob(os.path.join(ROOT, 'cctv', 'nyc', '*.jpg')))
res, tot, t0 = {}, Counter(), time.time()
for f in files:
rel = os.path.relpath(f, os.path.join(ROOT, 'cctv'))
res[rel] = detect(f); tot.update(d[5] for d in res[rel])
dt = time.time() - t0
json.dump(res, open(os.path.join(ROOT, 'cctv', 'detections.json'), 'w'), separators=(',', ':'))
print('images', len(files), 'secs', round(dt, 1), 'ms/img', round(1000 * dt / max(1, len(files))))
print('totals', dict(tot.most_common()), 'all', sum(tot.values()))
print('nyc totals', dict(Counter(d[5] for k, v in res.items() if k.startswith('nyc/') for d in v)))
picks = sys.argv[1:] or [max((k for k in res if k.startswith('nyc/')), key=lambda k: len(res[k])),
max((k for k in res if not k.startswith('nyc/')), key=lambda k: len(res[k])),
max(res, key=lambda k: sum(d[5] == 'person' for d in res[k]))]
for i, k in enumerate(picks, 1):
render(os.path.join(ROOT, 'cctv', k), res[k], os.path.join(HERE, f'det_check_{i}.jpg')); print('render', i, k, len(res[k]))
+72
View File
@@ -0,0 +1,72 @@
"""Poll live ADS-B (adsb.lol, fallback adsb.fi) around each scene 3x, 20 s apart.
Writes city/<slug>/air.json with latest sample per aircraft + short track history."""
import json, os, sys, time, requests
sys.path.insert(0, os.path.dirname(__file__))
from common import SCENES, enu
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
RAD = {'nyc': 25, 'lax': 25, 'bragg': 25, 'boston': 20}
HELI_TYPES = {'EC35','EC30','EC45','EC55','EC20','EC25','EC75','EC13','EC40','AS50','AS55','AS65','AS32','AS3B','H125','H130','H135','H145','H160','H175','B06','B06T','B407','B412','B427','B429','B430','B47G','B505','B212','B222','B230','B105','BK17','R22','R44','R66','S76','S92','S61','S64','S70','H60','UH60','MH60','HH60','H47','CH47','H53','A109','A119','A139','A169','A189','AW09','MI8','MI17','UH1','UH1Y','AH1','AH64','H64','V22','MV22','CABR','G2CA','EN28','EN48','H269','H500','MD52','MD60','NH90','LYNX','PUMA','GAZL','EH10','H1','B505'}
H = {'User-Agent': 'gods-eye-view-intro/1.0 (film research)'}
def fetch(slug):
lat, lon, _ = SCENES[slug]; nm = RAD[slug]
for url, key in ((f'https://api.adsb.lol/v2/point/{lat}/{lon}/{nm}', 'ac'),
(f'https://opendata.adsb.fi/api/v2/lat/{lat}/lon/{lon}/dist/{nm}', 'aircraft')):
try:
r = requests.get(url, headers=H, timeout=20); r.raise_for_status(); j = r.json()
ac = j.get('ac') or j.get('aircraft') or []
now = j.get('now') or time.time() * 1000
return url, now / 1000 if now > 1e11 else now, ac
except Exception as e:
print(slug, 'fail', url, e, file=sys.stderr)
return None, time.time(), []
def num(v):
try: return float(v)
except Exception: return None
def conv(slug, a):
lat, lon = num(a.get('lat')), num(a.get('lon'))
if lat is None or lon is None:
lp = a.get('lastPosition') or {}
lat, lon = num(lp.get('lat')), num(lp.get('lon'))
if lat is None: return None
x, y = enu(slug, lat, lon)
ab = a.get('alt_baro')
if ab == 'ground': alt = 0.0
else:
v = num(ab)
if v is None: v = num(a.get('alt_geom'))
alt = round(v * 0.3048, 1) if v is not None else None
trk = num(a.get('track')); trk = num(a.get('true_heading')) if trk is None else trk
gs = num(a.get('gs')); gs = round(gs * 0.514444, 1) if gs is not None else None
vr = num(a.get('baro_rate')); vr = num(a.get('geom_rate')) if vr is None else vr
vr = round(vr * 0.00508, 2) if vr is not None else None
return [x, y, alt, trk, gs, vr, (a.get('flight') or '').strip(), a.get('t') or '', a.get('category') or '']
def main():
polls = {s: [] for s in SCENES}
for i in range(3):
t0 = time.time()
for s in SCENES:
url, t, ac = fetch(s); polls[s].append((url, t, ac)); print(i, s, len(ac), url, flush=True)
if i < 2: time.sleep(max(0, 20 - (time.time() - t0)))
summary = {}
for s in SCENES:
latest, tracks, src = {}, {}, set()
tlast = 0
for url, t, ac in polls[s]:
if url: src.add(url.split('/')[2])
tlast = max(tlast, t)
for a in ac:
hx = a.get('hex'); row = conv(s, a)
if not hx or row is None: continue
if (num(a.get('seen_pos')) or 0) > 60: continue
latest[hx] = row
tr = tracks.setdefault(hx, [])
p = [row[0], row[1], row[2]]
if not tr or tr[-1][:2] != p[:2]: tr.append(p)
heli = [h for h, r in latest.items() if r[8] == 'A7' or r[7] in HELI_TYPES]
out = {'t': int(tlast), 'source': sorted(src), 'radius_nm': RAD[s], 'hex': list(latest.keys()),
'a': list(latest.values()), 'tracks': {h: v for h, v in tracks.items() if len(v) > 1}}
json.dump(out, open(os.path.join(ROOT, 'city', s, 'air.json'), 'w'), separators=(',', ':'))
summary[s] = {'aircraft': len(latest), 'with_track': len(out['tracks']), 'heli': len(heli),
'heli_list': [[latest[h][6], latest[h][7], latest[h][8], latest[h][2]] for h in heli]}
print(json.dumps(summary, indent=1))
if __name__ == '__main__': main()
@@ -0,0 +1,21 @@
"""Live MBTA vehicle positions -> city/boston/vehicles.json (square + 1 km)."""
import json, os, sys, requests
from collections import Counter
sys.path.insert(0, os.path.dirname(__file__))
from common import enu, inside
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
j = requests.get('https://cdn.mbta.com/realtime/VehiclePositions_enhanced.json', timeout=30).json()
rows, total = [], 0
for e in j['entity']:
v = e.get('vehicle') or {}; p = v.get('position') or {}
if 'latitude' not in p: continue
total += 1
x, y = enu('boston', p['latitude'], p['longitude'])
if not inside('boston', x, y, 1000): continue
rid = (v.get('trip') or {}).get('route_id', '')
lab = (v.get('vehicle') or {}).get('label') or (v.get('vehicle') or {}).get('id', '')
sp = p.get('speed'); rows.append([x, y, p.get('bearing'), round(sp, 2) if sp is not None else None, rid, lab])
out = {'t': int(j['header']['timestamp']), 'source': 'cdn.mbta.com VehiclePositions_enhanced.json', 'v': rows}
json.dump(out, open(os.path.join(ROOT, 'city', 'boston', 'vehicles.json'), 'w'), separators=(',', ':'))
c = Counter(r[4].split('-')[0] if r[4].startswith(('Green', 'CR')) else ('bus' if r[4][:1].isdigit() or r[4][:2] in ('SL','CT') else r[4]) for r in rows)
print('t', out['t'], 'feed total', total, 'in square+1km', len(rows), dict(c))
@@ -0,0 +1,53 @@
"""NYC DOT TMC cameras -> city/nyc/cameras.json + current stills for ~24 nearest cams."""
import hashlib, io, json, os, sys, time, requests
import numpy as np
from PIL import Image, ImageOps
from collections import Counter
sys.path.insert(0, os.path.dirname(__file__))
from common import enu, inside
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
OUT = os.path.join(ROOT, 'cctv', 'nyc'); DBG = os.path.join(os.path.dirname(__file__), 'nyc_rejects')
os.makedirs(OUT, exist_ok=True); os.makedirs(DBG, exist_ok=True)
H = {'User-Agent': 'gods-eye-view-intro/1.0'}
cat = requests.get('https://webcams.nyctmc.org/api/cameras', headers=H, timeout=30).json()
cams = []
for c in cat:
if str(c.get('isOnline')).lower() != 'true': continue
try: lat, lon = float(c['latitude']), float(c['longitude'])
except Exception: continue
x, y = enu('nyc', lat, lon)
if inside('nyc', x, y): cams.append((x, y, c['id'], c['name'].strip(), lat, lon))
json.dump([[x, y, i, n] for x, y, i, n, _, _ in cams], open(os.path.join(ROOT, 'city', 'nyc', 'cameras.json'), 'w'), separators=(',', ':'))
print('catalog', len(cat), 'online in square', len(cams))
cams.sort(key=lambda c: c[0]**2 + c[1]**2)
for f in os.listdir(OUT):
if f.startswith('cam_') and f.endswith('.jpg'): os.remove(os.path.join(OUT, f))
idx, rejects, hashes, raw_imgs = [], Counter(), Counter(), []
fetched_utc = time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())
for x, y, cid, name, lat, lon in cams[:80]:
if len(raw_imgs) >= 40: break
try:
r = requests.get(f'https://webcams.nyctmc.org/api/cameras/{cid}/image', headers=H, timeout=20)
r.raise_for_status(); im = Image.open(io.BytesIO(r.content)).convert('RGB')
except Exception as e:
rejects['error'] += 1; continue
h = hashlib.md5(r.content).hexdigest(); hashes[h] += 1
g = np.asarray(im.convert('L'), dtype=np.float32)
raw_imgs.append(dict(x=x, y=y, id=cid, name=name, lat=lat, lon=lon, im=im, h=h, mean=float(g.mean()), std=float(g.std()), size=im.size, n=len(r.content)))
n = 0
for d in raw_imgs:
reason = None
if hashes[d['h']] > 1: reason = 'duplicate/placeholder'
elif d['mean'] < 14: reason = 'black'
elif d['std'] < 10: reason = 'flat'
elif d['size'][0] < 200: reason = 'tiny'
if reason:
rejects[reason] += 1; d['im'].save(os.path.join(DBG, f"{reason.split('/')[0]}_{d['id'][:8]}.jpg")); continue
if n >= 24: break
n += 1; fn = f'cam_{n:03d}.jpg'
ImageOps.fit(d['im'], (640, 360), Image.LANCZOS).save(os.path.join(OUT, fn), quality=88)
idx.append({'file': fn, 'id': d['id'], 'name': d['name'], 'x': d['x'], 'y': d['y'], 'lat': d['lat'], 'lon': d['lon'],
'orig_size': list(d['size']), 'fetched_utc': fetched_utc, 'source': 'NYC DOT TMC webcams.nyctmc.org'})
print(fn, d['name'], d['size'], round(d['mean']), round(d['std']), round((d['x']**2+d['y']**2)**.5))
json.dump(idx, open(os.path.join(OUT, 'index.json'), 'w'), indent=1)
print('saved', n, 'rejects', dict(rejects), 'tried', len(raw_imgs))