Skip to content
Back to skills

Urban Safari

ASecurity

FIT ride pipeline for map views and video sync — urban safari content pipeline. Bosch Flow, XOSS G adapters, GeoJSON web contract, ffprobe video keyframes.

  • 56 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 6, 2026
toolspythonshellbashgit

Works with

  • cli

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 20 files and shows the line behind each finding

Scanned October 6, 2026

npx -y skills add SimHacker/moollm --skill urban-safari --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Urban Safari?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Urban Safari
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/simhacker-urban-safari/badge)](https://www.skillsdirectory.com/skills/simhacker-urban-safari)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: urban-safari
description: FIT ride pipeline for map views and video sync — urban safari content pipeline. Bosch Flow, XOSS G adapters, GeoJSON web contract, ffprobe video keyframes.
allowed-tools: [Shell, Read, Write]
related: [change-name, simulation]
tags: [gps, fit, video, ebike, map, pipeline]
---

# Urban Safari — ride map + video sync pipeline

Lifted from the Marconistraat25 private ebike workflow into a shareable MOOLLM skill. FIT files
in, static JSON for a map app out, optional video clips synced to GPS with frame paths drawn
over the track.

Part of [MOOLLM](../../README.md). See [skills/README.md](../README.md).

## Quick start

```bash
cd skills/urban-safari
pip install fitparse

# Any FIT files in ./rides/
python scripts/build_web_assets.py --trips-dir ./rides --out ./web/data

# Bosch Flow iPhone (USB)
pip install pymobiledevice3
python scripts/pipeline.py --sync --trips-dir ./rides --out ./web/data \
  --home-label "Your Home" --home-lat 52.33 --home-lon 4.78

# Video sync (needs ffprobe)
python scripts/sync_video.py --videos-dir ./videos --data-dir ./web/data
```

Synthetic demo (no real GPS): [examples/demo/web/data/](examples/demo/web/data/).

## Protocol

### SYNC — pull rides from device

| Device | Command |
|--------|---------|
| Bosch Flow (iPhone USB) | `sync_flow_trips.py --dest ./rides` |
| XOSS G (BLE) | [enhanced_xoss_sync](https://github.com/molleraj/enhanced_xoss_sync) → `./rides` |
| Manual | copy `.fit` into `./rides/` |

### BUILD — FIT → web JSON

`build_web_assets.py` writes `manifest.json` + per-trip GeoJSON, series, meta.
Bosch duplicate rows merged per timestamp (see `bosch-fit-quirks.md`).

### INSPECT — diagnose a FIT

```bash
python scripts/inspect_fit.py ride.fit
```

### SYNC_VIDEO — align clips to trips

1. `ffprobe` reads video `creation_time` and duration
2. Auto-match picks trip with best wall-clock overlap
3. Interpolate GPS from trip series at each video second
4. Write `videos/{id}.track.json` + `videos/{id}.geojson` (frame path)

```bash
python scripts/sync_video.py --video clip.mp4 --trip-id my-ride --data-dir ./web/data
python scripts/sync_video.py --videos-dir ./videos --data-dir ./web/data  # auto-match all
python scripts/sync_video.py --video clip.mp4 --offset-s 2.5 --data-dir ./web/data  # clock skew
```

**Calibration trick:** film your bike computer clock for one second at ride start; measure
offset between video frame and FIT timestamp; pass `--offset-s`.

### MAP_TRANSCRIPT — words on the map, clustered

Requires synced video track (`SYNC_VIDEO`). Whisper transcribes the clip; each segment gets
GPS from the video keyframe at its temporal midpoint; nearby segments merge into readable
labels.

```bash
python scripts/map_transcript.py --video-id img-0679 --data-dir ./web/data \
  --video ~/Movies/IMG_0679.MOV \
  --cluster-radius-m 40 --cluster-gap-s 20 --min-words 3
```

Clustering merges segments when within **40 m** and **20 s** (defaults). Tune for urban
density: tighter radius in old city centers, wider on open dike roads.

Or full pipeline with transcription:

```bash
python scripts/pipeline.py --sync --videos-dir ./videos --out ./web/data --map-transcripts
```

Output: `videos/{id}.transcript.json` + Point GeoJSON for map labels. See
[DATA-CONTRACT.md](DATA-CONTRACT.md#transcript-on-the-map-clustered).

### MATCH — map UI integration

Read [DATA-CONTRACT.md](DATA-CONTRACT.md). Load `manifest.json`, fetch trip GeoJSON for all
rides, union bounds for overview map. On video play, scrub marker along `keyframes[]`.

## Web app sketch (SvelteKit + MapLibre)

1. Static copy of `web/data/` → `static/safari/data/`
2. `fetch('/safari/data/manifest.json')`
3. Draw all `trips[].geojson` as layers (color by trip)
4. For selected trip + video: draw video track LineString; `<video>` `timeupdate` → marker

## Privacy

FIT and video contain exact GPS. Do not commit real tracks to public repos. Use
`examples/demo/` for public demos; trekify before sharing.

## Device adapters

See [adapters/README.md](adapters/README.md). XOSS integration is a natural collaboration
with Abraham Moller — his BLE sync lands FITs; this skill builds the shared map + video layer.

## See also

- [DATA-CONTRACT.md](DATA-CONTRACT.md)
- [bosch-fit-quirks.md](bosch-fit-quirks.md)
- [simulation/examples/urban-safari-ride-game.yml](../simulation/examples/urban-safari-ride-game.yml)

Files in this skill

  • CARD.yml2.2 KB
  • DATA-CONTRACT.md5.2 KB
  • GLANCE.yml777 B
  • README.md2 KB
  • SKILL.md4.3 KB
  • adapters/README.md1.5 KB
  • bosch-fit-quirks.md1.5 KB
  • examples/demo/README.md396 B
  • examples/demo/web/data/manifest.json842 B
  • examples/demo/web/data/trips/demo-loop.geojson9.5 KB
  • examples/demo/web/data/trips/demo-loop.meta.json282 B
  • examples/demo/web/data/trips/demo-loop.series.json31.2 KB
  • scripts/build_web_assets.py5.5 KB
  • scripts/fit_io.py3.9 KB
  • scripts/inspect_fit.py5.1 KB
  • scripts/map_transcript.py4.8 KB
  • scripts/pipeline.py3.9 KB
  • scripts/sync_flow_trips.py2.2 KB
  • scripts/sync_video.py7.4 KB
  • scripts/transcript_cluster.py5.4 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…