Skip to content

A demo Space that processes the duck's camera, and what it measured - #223

Closed
pierre-rouanet wants to merge 12 commits into
mainfrom
vision-demo
Closed

pierre-rouanet wants to merge 12 commits into
mainfrom
vision-demo

Conversation

@pierre-rouanet

Copy link
Copy Markdown
Member

Everything after #219 merged. A Gradio Space on Hugging Face hardware consumes the robot's camera through the rendezvous and runs OpenCV over each frame — and on its first run it measured the thing nothing else could.

The measurement

the rendezvous welcomed this consumer as 9d3a17dd (PierreRouanet)
found olducky (8a73eda9), asking for a session
session 4c7e9c60 started; waiting for the robot's offer
peer connection connecting (ice checking)
the session ended: the robot ended the session      ← 8s later
peer connection failed (ice failed)

Signalling crosses perfectly and no candidate pair works. Three data points now instead of one: a browser on the robot's LAN connects on host candidates, a 4G phone fails and CGNAT was the suspicion, and a Hugging Face Space fails too — and a Space is not behind CGNAT. So TURN is not a fallback for awkward networks; it is the requirement for every consumer that is not on the robot's own wifi, which is every cloud backend and therefore anything doing perception off-robot. §6 carries the log.

Nothing in the demo needs changing for it: it will connect the day the robot can offer a relay candidate.

The consumer is ours

reachy_mini[central-consumer] proved the transport — it was the first non-browser client to pull frames out of a duck — and was the wrong dependency, three times over. reachy_mini/__init__.py imports the daemon's world, so a consumer drags in PyGObject: a source build wanting a C compiler and cairo headers for GStreamer bindings it never touches. It pins starlette<1.0.0, which no current Gradio can satisfy (ResolutionImpossible, correctly). And it ignores a data channel labelled control, so the camera geometry cannot be asked for.

spaces/vision-demo/consumer.py is 300 lines: SSE in, POST /send out, aiortc answering the robot's offer, frames as numpy. Verified against olducky:

frame 8: (720, 1280, 3) uint8
media.video: {'width': 1280, 'height': 720, 'rotate': 90,
              'intrinsics': {'fx': 1809.52, 'cx': 640.0, 'calibrated': False}}
pc_state: connected  ice_state: completed  control: True

That second line is the payoff: the intrinsics come from the robot, so the demo's geometry overlay uses published numbers rather than repeating the arithmetic. The fifteen lines that make DTLS complete against GStreamer's webrtcsink are copied from their consumer with the credit and the upstream link (aiortc PR #1392) — they are the reason this took an afternoon rather than a week.

Six dependencies instead of 117: aiortc, av, httpx, gradio[oauth], opencv-python-headless, numpy.

What the Space is

spaces/vision-demo, deployed by scripts/publish-space.sh — source in-repo for §5's reason, since a consumer tracks the rendezvous protocol, this project's method names and the camera's geometry. Docker rather than sdk: gradio, because a Gradio Space cannot choose its Gradio version and 6.26 is the one version that cannot work here.

Five filters — raw, Canny edges, motion diff, sparse Lucas–Kanade flow, and an intrinsics overlay — with the pixels in filters.py importing only OpenCV and numpy, so every one is exercised on a synthetic sideways frame pair without a WebRTC stack, a robot or a token.

It authenticates with an HF_TOKEN secret and must stay private. A visitor's own OAuth token would be better and would make it publishable; two attempts failed on platform behaviour rather than code — a static Space never injected the client id (§5.0), and a Docker Space does not put OAUTH_CLIENT_ID in the environment either, so Gradio mocks OAuth and refuses to start. A demo that will not start is worse than a demo with one credential.

Four bugs of mine, three of them the same bug

A hand-kept list that has to match reality, failing silently in the direction of looking fine: cp "$SOURCE"/* published whatever was lying around, git diff --quiet reported "already serves this" for a file that was only ever added, and COPY app.py filters.py built a perfect image without consumer.py in it. All three now ask git or the filesystem what is actually there.

The fourth: stop() posted its farewell after cancelling the event stream, which the service refuses with a 400. I had diagnosed that exact bug in their consumer an hour earlier and said ours could not have it — true of the Rust relay, not of the Python I had yet to write. The ordering is a docstring now.

`gr.LoginButton` raises `Cannot initialize OAuth due to a missing library`
without the `oauth` extra, and `requirements.txt` asked for bare `gradio`. It
would have worked anyway: a Hugging Face Space installs `gradio[oauth,mcp]` of
its own accord, which is visible in the build log — so the app was standing on
somebody else's default and would have broken the first time it ran anywhere
else.

Found by building the UI against the version the Space actually installs, with
the consumer stubbed: `gradio[oauth]==6.26.0`, OpenCV, numpy, and a fake
`ReachyCentralConsumer`. That exercises the import, the Blocks construction, the
four states the status panel distinguishes and every filter through the render
path — all without a robot, a token or a three-minute Space build. Everything
Gradio 6 was checked for still exists under the same names, `height` included.

Assisted-by: Claude:claude-opus-5[1m]
`cp "$SOURCE"/*` published whatever was lying around, and something always is:
running the app from its own directory leaves a `__pycache__` beside it, which is
a directory, which `cp` without `-r` refuses, which stopped the script after it
had cloned and before it had pushed.

Listing tracked files fixes both halves. Bytecode and scratch files cannot reach
a Space, and a Space always corresponds to a commit here — a file that has not
been committed does not deploy, which is the answer to "which version is live"
the first time somebody asks.

Assisted-by: Claude:claude-opus-5[1m]
…environment

`ResolutionImpossible`, and the resolver is right:

    gradio 6.26   needs starlette >=1.0.1, huggingface-hub >=1.16
    reachy-mini   needs starlette <1.0.0          — every version, 1.10 included

A Gradio Space installs `gradio[oauth,mcp]==6.26.0` of its own accord, so the one
version that cannot coexist with this consumer is the one version such a Space
has. Not a matter of waiting for an upgrade either: the constraint is on every
`reachy-mini` release, not the current one.

Gradio 5.23 resolves with the same consumer in 117 packages, so the version is
the thing to control — which a Docker Space can and a Gradio Space cannot. That
is the second Space in this branch where the managed environment was the obstacle
rather than the shortcut; the console reached `sdk: docker` from the other
direction, an OAuth client id a static Space would not inject.

The pin is written down with the reason, because `gradio[oauth]>=5,<6` looks like
timidity and is arithmetic.

Assisted-by: Claude:claude-opus-5[1m]
Both of them are Docker now, so the parting line about Gradio installing
requirements was wrong twice over — and the build log is the thing worth pointing
at anyway.

Assisted-by: Claude:claude-opus-5[1m]
`reachy_mini[central-consumer]` proved the transport and was the wrong
dependency, three times over: `reachy_mini/__init__.py` imports the daemon's
world, so a consumer drags in PyGObject — a source build wanting a C compiler and
cairo headers for GStreamer bindings it never touches — and the package pins
`starlette<1.0.0`, which no current Gradio can satisfy, and it ignores a data
channel labelled `control`, so the camera geometry could not be asked for at all.

We wrote the robot half of this protocol. The client half is 300 lines and
smaller than the workarounds: SSE in, `POST /send` out, aiortc answering the
robot's offer, frames as numpy. Verified against `olducky`:

    frame 8 (720, 1280, 3) uint8
    media.video: {'width': 1280, 'height': 720, 'rotate': 90,
                  'intrinsics': {'fx': 1809.52, 'cx': 640.0, 'calibrated': False}}
    pc_state: connected  ice_state: completed  control: True

That second line is the point. The intrinsics come from the robot now, so the
demo's overlay stops being arithmetic repeated in two places — and the fifteen
lines that make DTLS complete against GStreamer's webrtcsink are copied with the
credit and the upstream link, because they are the reason this took an afternoon
rather than a week.

**And the teardown ordering is written down because remembering it did not
work.** `POST /send` is refused once the event stream has gone, so the farewell
has to precede the cancel. I noticed exactly this bug in their consumer an hour
before writing it here — said ours could not do it, which was true of the Rust
relay and not of this — and the first end-to-end run raised on the way out. It
now says goodbye first and raises nothing: a teardown that throws leaves a UI
holding a session it believes is alive.

Assisted-by: Claude:claude-opus-5[1m]
`ModuleNotFoundError: No module named 'consumer'` — because the script was in a
scratchpad, reaching into a clone by absolute path, in a `/tmp` that gets wiped.
A check that only runs from one directory on one machine is a check nobody runs
twice.

`spaces/vision-demo/check_consumer.py` imports its neighbour, is committed with
it, and says in its own docstring what each stage of a successful run proves —
including the one their consumer cannot reach, `media.video` answering on the
control channel.

Assisted-by: Claude:claude-opus-5[1m]
`git diff --quiet` ignores untracked files, so a publish whose only change was a
new file said "the Space already serves this" and pushed nothing. That is the
worst shape a wrong answer can take: it reads exactly like the right one, and the
file it skipped was the check script somebody would go looking for.

Staged first, compared as staged. Additions, deletions and modifications all
count now.

Assisted-by: Claude:claude-opus-5[1m]
`COPY app.py filters.py ./` built a perfect image without `consumer.py` in it,
and the app died on import — the same `ModuleNotFoundError` the local check hit
an hour earlier, from the same cause in a different place.

That is three of these in one afternoon: `cp "$SOURCE"/*` published whatever was
lying around, `git diff --quiet` ignored a file that was only ever added, and now
a `COPY` naming two of three modules. Each is an enumeration somebody has to keep
in step with the truth, and each failed silently in the direction of looking fine.

`COPY *.py ./`, with the publisher already guaranteeing that only tracked files
are there to be globbed.

Assisted-by: Claude:claude-opus-5[1m]
Gradio decided it was not in a Space — `OAUTH_CLIENT_ID` is not in a Docker
Space's environment — fell back to *mocked* OAuth, and refused to start without a
local `huggingface-cli login`. The app crashed on `gr.Blocks.__exit__`, which is
before any of it runs.

That is the second time today a sign-in was blocked by platform behaviour rather
than by code: the console's static Space never injected the client id either, and
that one at least had a Docker escape. Here Docker *is* the escape and the
variable still is not there.

So the button goes and an `HF_TOKEN` secret takes its place, with the trade
written down rather than glossed: a visitor's own token would reach their robots
and nobody else's, which is what would make this Space safe to publish, and
without one **the Space must stay private** — a visitor would otherwise reach the
owner's robot with the owner's token. Still never the robot's own credential: the
rendezvous maps a token to one peer, so sharing the robot's takes the robot off
its own listing.

A demo that will not start is worse than a demo with one credential.

Verified the way the last three of these should have been: the Blocks builds
against the Gradio the Space installs, the four status states render, every filter
runs through the render path, and the status line now reports what the robot says
about its own camera — 1280×720, mounted 90° off upright, fx 1810 px (nominal).

Assisted-by: Claude:claude-opus-5[1m]
It printed nothing of its own. The consumer logs at INFO and nothing had
configured a handler, so every line about the welcome, the producer, the session
and the peer connection state went nowhere — leaving a private Space whose only
diagnostic is a status pill somebody has to read out.

`basicConfig` at INFO, aiortc and aioice turned down to WARNING so the log is
readable, and the connection state logged on every change: `connecting` that
never becomes `connected` is no candidate pair, `failed` is ICE having tried
them all, and those two want different conversations.

Assisted-by: Claude:claude-opus-5[1m]
The demo Space got as far as it can, and its log is the measurement §6 was
missing:

    the rendezvous welcomed this consumer as 9d3a17dd (PierreRouanet)
    found olducky (8a73eda9), asking for a session
    session 4c7e9c60 started; waiting for the robot's offer
    peer connection connecting (ice checking)
    the session ended: the robot ended the session      ← 8s later
    peer connection failed (ice failed)

Signalling crosses perfectly and no candidate pair works. The robot offers host
and srflx, the Space offers its own, neither offers a `relay` — and eight seconds
in, `webrtcsink` times out a consumer whose ICE never connected, ends the session,
and the bridge forwards that, which is why the robot's farewell arrives before
ICE's own verdict.

This turns a guess into a fact. On one LAN the console works on host candidates;
from a 4G phone it failed and CGNAT was the suspicion; from a Space it fails too,
and a Space is not behind CGNAT. **TURN is not a fallback for awkward networks.**
It is the requirement for every consumer that is not on the robot's own wifi,
which is every cloud backend and therefore anything doing perception off-robot.

Nothing in the demo needs changing for it: it will connect the day the robot can
offer a relay candidate.

Assisted-by: Claude:claude-opus-5[1m]
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown

Coverage

72.94% lines on this branch, against a floor of 70%.

Per-file
Filename                              Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
btd/src/adv.rs                             79                 0   100.00%           9                 0   100.00%          42                 0   100.00%           0                 0         -
btd/src/bluez.rs                          422               422     0.00%          32                32     0.00%         279               279     0.00%           0                 0         -
btd/src/chorale.rs                        346               246    28.90%          23                13    43.48%         230               171    25.65%           0                 0         -
btd/src/framing.rs                        217                 7    96.77%          17                 1    94.12%          97                 5    94.85%           0                 0         -
btd/src/gatt.rs                             3                 0   100.00%           1                 0   100.00%           3                 0   100.00%           0                 0         -
btd/src/link.rs                            13                 0   100.00%           1                 0   100.00%          17                 0   100.00%           0                 0         -
btd/src/main.rs                            77                77     0.00%          11                11     0.00%          77                77     0.00%           0                 0         -
btd/src/pairing.rs                        149                 2    98.66%          12                 1    91.67%          81                 1    98.77%           0                 0         -
btd/src/route.rs                          345                32    90.72%          27                 0   100.00%         344                11    96.80%           0                 0         -
btd/src/session.rs                       1118                71    93.65%          66                 5    92.42%         649                41    93.68%           0                 0         -
btd/src/upstream.rs                       397                35    91.18%          34                 8    76.47%         241                19    92.12%           0                 0         -
configd/src/bluez.rs                      441               441     0.00%          78                78     0.00%         297               297     0.00%           0                 0         -
configd/src/identity.rs                   111                 5    95.50%          12                 1    91.67%          52                 3    94.23%           0                 0         -
configd/src/main.rs                       494               494     0.00%          38                38     0.00%         338               338     0.00%           0                 0         -
configd/src/net.rs                        246                12    95.12%          38                 2    94.74%         181                 4    97.79%           0                 0         -
configd/src/nm.rs                         271               213    21.40%          43                39     9.30%         171               120    29.82%           0                 0         -
configd/src/pad.rs                        301                12    96.01%          33                 2    93.94%         186                 8    95.70%           0                 0         -
configd/src/power.rs                       30                30     0.00%           6                 6     0.00%          28                28     0.00%           0                 0         -
configd/src/store.rs                      350                25    92.86%          28                 2    92.86%         173                 9    94.80%           0                 0         -
configd/src/units.rs                      183               121    33.88%          24                19    20.83%         116                82    29.31%           0                 0         -
duck-control/src/bus.rs                   422               313    25.83%          34                22    35.29%         285               212    25.61%           0                 0         -
duck-control/src/fall.rs                  173                 0   100.00%          15                 0   100.00%         108                 0   100.00%           0                 0         -
duck-control/src/imu.rs                   370                 8    97.84%          20                 0   100.00%         195                 5    97.44%           0                 0         -
duck-control/src/io.rs                    134                19    85.82%          21                 5    76.19%         120                17    85.83%           0                 0         -
duck-control/src/model.rs                 113                 1    99.12%          14                 0   100.00%          68                 0   100.00%           0                 0         -
duck-control/src/obs.rs                   260                 3    98.85%          23                 1    95.65%         174                 5    97.13%           0                 0         -
duck-control/src/policy.rs                370               229    38.11%          45                25    44.44%         253               148    41.50%           0                 0         -
duck-control/src/safety.rs                450                13    97.11%          33                 2    93.94%         292                 6    97.95%           0                 0         -
duck-detect/src/bin/duck-bench.rs         306               306     0.00%          16                16     0.00%         170               170     0.00%           0                 0         -
duck-detect/src/lib.rs                    512                10    98.05%          24                 0   100.00%         274                 6    97.81%           0                 0         -
duck-detect/src/onnx.rs                    96                96     0.00%           5                 5     0.00%          52                52     0.00%           0                 0         -
duck-detect/src/rknn.rs                   267               237    11.24%          15                11    26.67%         216               195     9.72%           0                 0         -
duck-ipc-proto/src/lib.rs                2004               146    92.71%         127                12    90.55%        1461                80    94.52%           0                 0         -
duckctl/src/main.rs                      2281               930    59.23%         136                43    68.38%        1447               599    58.60%           0                 0         -
kinematics/src/hand.rs                    373                 2    99.46%          21                 2    90.48%         172                 2    98.84%           0                 0         -
kinematics/src/head.rs                    381                 9    97.64%          20                 0   100.00%         188                 4    97.87%           0                 0         -
kinematics/src/lib.rs                     229                11    95.20%          19                 2    89.47%         115                 7    93.91%           0                 0         -
kinematics/src/math.rs                    171                 0   100.00%          16                 0   100.00%          79                 0   100.00%           0                 0         -
kinematics/src/mjcf.rs                    225                32    85.78%          17                 1    94.12%         132                15    88.64%           0                 0         -
kinematics/src/tof.rs                     338                20    94.08%          14                 1    92.86%         184                13    92.93%           0                 0         -
mediad/src/camera.rs                      203                 4    98.03%          15                 0   100.00%         145                 4    97.24%           0                 0         -
mediad/src/config.rs                       90                 5    94.44%           7                 1    85.71%          46                 4    91.30%           0                 0         -
mediad/src/detect.rs                      293               222    24.23%          13                 9    30.77%         200               145    27.50%           0                 0         -
mediad/src/exposure.rs                    412               161    60.92%          28                 8    71.43%         279               110    60.57%           0                 0         -
mediad/src/hf.rs                           49                 3    93.88%           2                 0   100.00%          25                 2    92.00%           0                 0         -
mediad/src/main.rs                        287               287     0.00%           7                 7     0.00%         194               194     0.00%           0                 0         -
mediad/src/pipeline.rs                   1138               950    16.52%          76                58    23.68%         736               607    17.53%           0                 0         -
mediad/src/producer.rs                    161                33    79.50%          20                 5    75.00%         109                20    81.65%           0                 0         -
mediad/src/relay.rs                      1733               165    90.48%         143                21    85.31%        1137               117    89.71%           0                 0         -
mediad/src/route.rs                       173                19    89.02%          12                 0   100.00%         148                 8    94.59%           0                 0         -
mediad/src/session.rs                     533                12    97.75%          32                 0   100.00%         320                 8    97.50%           0                 0         -
mediad/src/turn.rs                        420                31    92.62%          39                 3    92.31%         254                16    93.70%           0                 0         -
mediad/src/upstream.rs                    263                16    93.92%          17                 1    94.12%         160                12    92.50%           0                 0         -
mediad/src/web.rs                         119                26    78.15%          15                 4    73.33%          82                17    79.27%           0                 0         -
odometry/src/lib.rs                       321                 5    98.44%          22                 1    95.45%         192                 7    96.35%           0                 0         -
padd/src/main.rs                          857               555    35.24%          26                11    57.69%         527               375    28.84%           0                 0         -
padd/src/tap.rs                           693               455    34.34%          42                25    40.48%         419               267    36.28%           0                 0         -
pet-detect/src/bin/detect.rs               61                61     0.00%           1                 1     0.00%          38                38     0.00%           0                 0         -
pet-detect/src/bin/features.rs             46                46     0.00%           2                 2     0.00%          20                20     0.00%           0                 0         -
pet-detect/src/lib.rs                     362               184    49.17%          27                13    51.85%         224               122    45.54%           0                 0         -
pet-detect/src/worker.rs                  381               230    39.63%          24                14    41.67%         276               160    42.03%           0                 0         -
robotctl/src/configure.rs                 846               329    61.11%          35                12    65.71%         464               226    51.29%           0                 0         -
robotctl/src/duck.rs                     1211               144    88.11%          63                 1    98.41%         604                47    92.22%           0                 0         -
robotctl/src/main.rs                     5076              2714    46.53%         276               125    54.71%        3452              1840    46.70%           0                 0         -
robotctl/src/monitor.rs                  4024               724    82.01%         213                35    83.57%        2522               464    81.60%           0                 0         -
robotctl/src/path_map.rs                  425                59    86.12%          24                 2    91.67%         223                36    83.86%           0                 0         -
robotctl/src/show.rs                      714                46    93.56%          31                 1    96.77%         509                25    95.09%           0                 0         -
robotd-params/src/edit.rs                1823               121    93.36%         111                14    87.39%         890                52    94.16%           0                 0         -
robotd-params/src/lib.rs                 1836                91    95.04%         173                10    94.22%        1323                58    95.62%           0                 0         -
robotd-params/src/registry.rs             186                10    94.62%          13                 2    84.62%         139                17    87.77%           0                 0         -
robotd/src/chorale.rs                    1366                30    97.80%          71                 4    94.37%         826                20    97.58%           0                 0         -
robotd/src/control.rs                     405               366     9.63%          28                23    17.86%         322               274    14.91%           0                 0         -
robotd/src/intents.rs                     419                69    83.53%          48                 8    83.33%         308                45    85.39%           0                 0         -
robotd/src/main.rs                       6943              1531    77.95%         326                51    84.36%        4485               979    78.17%           0                 0         -
robotd/src/soc.rs                          47                25    46.81%           4                 1    75.00%          30                15    50.00%           0                 0         -
robotd/src/sound.rs                       968               688    28.93%          50                33    34.00%         565               416    26.37%           0                 0         -
robotd/src/theremin.rs                    472                71    84.96%          32                 6    81.25%         271                38    85.98%           0                 0         -
sounds/src/chorale/beat.rs                403                16    96.03%          26                 1    96.15%         246                12    95.12%           0                 0         -
sounds/src/chorale/midi.rs               1047                80    92.36%          44                 2    95.45%         581                43    92.60%           0                 0         -
sounds/src/chorale/mod.rs                1423                57    95.99%          83                 3    96.39%         812                41    94.95%           0                 0         -
sounds/src/chorale/text.rs                700                60    91.43%          41                12    70.73%         376                17    95.48%           0                 0         -
sounds/src/lib.rs                         162                30    81.48%          14                 6    57.14%          84                18    78.57%           0                 0         -
sounds/src/main.rs                        463               463     0.00%          20                20     0.00%         240               240     0.00%           0                 0         -
sounds/src/personality.rs                 174                 0   100.00%           6                 0   100.00%          84                 0   100.00%           0                 0         -
sounds/src/rng.rs                         173                 0   100.00%          18                 0   100.00%          96                 0   100.00%           0                 0         -
sounds/src/stream.rs                      719                 7    99.03%          46                 1    97.83%         420                 6    98.57%           0                 0         -
sounds/src/synth.rs                       353                 7    98.02%          29                 0   100.00%         197                 3    98.48%           0                 0         -
sounds/src/voices.rs                      679                 2    99.71%          26                 0   100.00%         353                 2    99.43%           0                 0         -
test-support/src/lib.rs                   272                 2    99.26%          22                 0   100.00%         167                 0   100.00%           0                 0         -
tof/src/lib.rs                             88                 0   100.00%           9                 0   100.00%          54                 0   100.00%           0                 0         -
tof/src/main.rs                           535               452    15.51%          29                18    37.93%         338               294    13.02%           0                 0         -
tof/src/sensor.rs                         230               148    35.65%          22                15    31.82%         163               114    30.06%           0                 0         -
tof/src/status.rs                          76                 2    97.37%           7                 1    85.71%          58                 1    98.28%           0                 0         -
updater/src/account.rs                   1466               177    87.93%         137                28    79.56%         938               114    87.85%           0                 0         -
updater/src/config.rs                     436                24    94.50%          38                 4    89.47%         354                17    95.20%           0                 0         -
updater/src/engine.rs                    3239               473    85.40%         215                27    87.44%        2092               288    86.23%           0                 0         -
updater/src/faults.rs                      69                 7    89.86%           7                 0   100.00%          51                 0   100.00%           0                 0         -
updater/src/fsutil.rs                     104                30    71.15%          10                 6    40.00%          51                24    52.94%           0                 0         -
updater/src/hooks.rs                      454                15    96.70%          37                 2    94.59%         382                12    96.86%           0                 0         -
updater/src/ipc.rs                        901               308    65.82%          67                20    70.15%         559               167    70.13%           0                 0         -
updater/src/journal.rs                    832                78    90.62%          57                10    82.46%         483                53    89.03%           0                 0         -
updater/src/lib.rs                         44                13    70.45%           4                 0   100.00%          34                13    61.76%           0                 0         -
updater/src/main.rs                       550               222    59.64%          38                14    63.16%         420               151    64.05%           0                 0         -
updater/src/manifest.rs                   159                 6    96.23%          16                 0   100.00%         110                 1    99.09%           0                 0         -
updater/src/orphan.rs                     288                 6    97.92%          25                 0   100.00%         181                 3    98.34%           0                 0         -
updater/src/policy.rs                    1532               582    62.01%         121                49    59.50%         819               333    59.34%           0                 0         -
updater/src/preflight.rs                  382                16    95.81%          47                 4    91.49%         284                11    96.13%           0                 0         -
updater/src/reconcile.rs                  292                15    94.86%          25                 3    88.00%         172                 5    97.09%           0                 0         -
updater/src/robot.rs                      225                33    85.33%          37                10    72.97%         139                21    84.89%           0                 0         -
updater/src/source/github.rs              474               169    64.35%          51                26    49.02%         304                99    67.43%           0                 0         -
updater/src/source/hf_hub.rs              136                72    47.06%          20                12    40.00%          81                41    49.38%           0                 0         -
updater/src/source/http.rs                319                82    74.29%          29                11    62.07%         260                88    66.15%           0                 0         -
updater/src/source/local.rs               346                37    89.31%          36                 9    75.00%         192                26    86.46%           0                 0         -
updater/src/source/mod.rs                  39                30    23.08%           4                 2    50.00%          30                24    20.00%           0                 0         -
updater/src/spawn.rs                       94                13    86.17%           5                 0   100.00%          49                 4    91.84%           0                 0         -
updater/src/store.rs                      593                41    93.09%          43                 7    83.72%         271                42    84.50%           0                 0         -
updater/src/transcript.rs                 518                42    91.89%          31                 3    90.32%         290                22    92.41%           0                 0         -
updater/src/unix.rs                        44                 3    93.18%           3                 0   100.00%          22                 2    90.91%           0                 0         -
updater/src/verify.rs                     786                95    87.91%          55                18    67.27%         424                75    82.31%           0                 0         -
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                                   72243             19033    73.65%        4836              1262    73.90%       45312             12261    72.94%           0                 0         -

@pierre-rouanet

Copy link
Copy Markdown
Member Author

Superseded. Main grew its own spaces/vision-demo and built it the other way round: 4e3506b replaced the WebRTC consumer with a receiver — the robot dials wss://…/frames and the Space decodes H.264 — and deleted aiortc, the DTLS cipher shim and, in its own words, "the ICE stack that could never complete from a data centre". That is this branch's consumer.py and check_consumer.py.

What this PR was carrying has landed or been answered elsewhere:

  • filters.py is on main, same five filters.
  • The §6 measurement — that a data centre cannot reach the robot without a relay — is confirmed there in stronger form: offering relay candidates relays=5 across six sessions on olducky.
  • turn.fastrtc.org being dead turned out to be the vanity alias only. The Space behind it never stopped answering, and main points at https://fastrtc-turn-service.hf.space/credentials (mediad(turn): the relay endpoint is the Space, not the alias in front of it #258, console: offer a relay of this page's own, for a consumer with no IPv4 #280). The recommendation here to report an outage to fastrtc is no longer right.
  • Two of the three publisher bugs were fixed independently and better — find -type f -o -type l with cp -L, and COPY . $HOME/app instead of a hand-kept file list.

The third publisher bug is the one thing main still has, so it goes in on its own: #284.

Merging this as it stands would also revert hf-robot-account back to updater::account and delete §5.2 from the design doc. 168 commits behind, six files conflicting.

@pierre-rouanet
pierre-rouanet deleted the vision-demo branch September 14, 2026 12:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant