NURLNURL registrynurl-lang.org →

← yoloe-demo

yoloe-demo 0.3.1 API

index_html_data.nu

GENERATED by tools/embed_page.py from views/index.html — do not edit. The demo page template, embedded so installed binaries need no views/ directory on disk (--page FILE overrides). Chunked because released nurlc (≤ v0.11.1) stack-overflows on literals past ~48 KB.

API

@ index_html_chunks → i

@ index_html_chunk i k → s


main.nu

yoloe-demo — live in-browser YOLOE segmentation, served by pure NURL.

The browser opens one page, grabs the webcam, and POSTs JPEG frames to this server; the server runs YOLOE (open-vocabulary detection + instance segmentation) on the GPU through the onnx package, composites the segmentation masks onto the frame, and answers with the masked JPEG plus a JSON detection list. The page draws boxes/labels on top and loops — live segmented video, end to end, with no Python, no OpenCV and no inference engine anywhere in the stack:

browser webcam → JPEG POST → http package (pure-NURL HTTP/TLS server) → image package (JPEG decode) → onnx package (every layer a CUDA-C kernel via NVRTC) → yoloe decode + mask branch → JPEG encode → browser

yoloe-demo --model yoloe-v8s-seg.onnx --classes classes.txt [--port 8090] [--host 0.0.0.0] [--gpu 0] [--tls] [--page FILE] (default: the template built into the binary)

--tls generates a self-signed P-256 certificate at startup (std/x509_gen, also pure NURL) so the camera works from other machines on the LAN too — browsers only expose getUserMedia on secure origins (localhost is exempt).

Routes: GET / the demo page (rendered once at startup via the template package with the class list + device name) POST /detect body = JPEG/PNG frame; query: conf=0.25 masks=1 on=0,2,5 → { ms, n, dets:[{n,s,c,k,x,y,w,h}], img:"data:..jpeg" } GET /health liveness probe

API

: DemoState

: DemoState {
    Engine eng  // the inference engine, for the program's lifetime
    OGraph graph
    ( Vec String ) names
    i nc
    String device
    String model_path
    String index_html  // pre-rendered demo page
    // runtime prompting (kmax > 0 → the promptable K-slot export is loaded):
    i kmax  // prompt slots baked into the detector graph (0 = baked vocab)
    OGraph tgraph  // MobileCLIP text encoder (pure NURL on the GPU)
    Tokenizer tk  // CLIP BPE tokenizer
    ( Vec u ) tpe  // kmax×512 f32 text embeddings, zero-padded past nc
    ( Vec u ) model_bytes  // raw .onnx, served to the wasm client mode
    b wasm_mode  // web/yoloe_detect.wasm present → offer in-browser compute
}

: Demo { s ctl }

The server's state is a handle the route closures capture: every copy is the same state, and the last owner (the app's routes, when the server returns) releases the engine, the graphs and the buffers.

@ Demo_drop sink Demo h → v

@ yd_name_at ( Vec String ) names i k → s

@ yd_read_names s path → ( Vec String )

classes.txt: one prompt per line (must match the model export)

@ yd_shape4 i a i b i c i d → ( Vec i )

@ yd_pal_r i k → i

8-colour instance palette (matches the page's JS palette by index)

@ yd_pal_g i k → i

@ yd_pal_b i k → i

@ yd_pal i ch → ( Vec i )

@ yd_query_f ( Vec UrlParam ) ps s key f dflt → f

value of key as float, or dflt when absent/garbage

@ yd_query_b ( Vec UrlParam ) ps s key b dflt → b

flag key (0/1), dflt when absent

@ yd_enabled ( Vec UrlParam ) ps i nc i ncap → ( Vec i )

per-class enable flags from on=0,2,5; no on param → all ACTIVE classes enabled. ncap is the decode width (kmax in prompt mode) — ids in [nc, ncap) are inert pad slots and stay off either way.

@ h_health HttpRequest req Params p → HttpResponse

@ wd_probe s path → ( Vec u )

1-byte marker vec when path exists and is readable ([] otherwise).

@ yd_load_graph s path → ?OGraph

@ yd_builtin_page → String

render the page template once with the static context The page template compiled into the binary (src/index_html_data.nu, generated by tools/embed_page.py) — an installed tool has no views/ directory on disk. --page FILE overrides it.


wasm_detect.nu

wasm_detect.nu — YOLOE inference as a wasm32-wasi module: the SAME pure-NURL onnx runtime the server runs on the GPU, compiled for the browser and executed on the gpu package's STATIC backend (precompiled kernels_static.wasm.o linked in — no NVRTC, no dlopen, no compiler).

This is a WASI command module driven by host imports (env.*): the embedder (a web worker — see web/worker.js — or the node test harness) supplies blobs and frames, the module loops forever inside start. Blocking hostframe is legal because the module runs in a worker thread (Atomics.wait), never on the UI thread.

host_blob_size(kind) → bytes 0 = model.onnx, 1 = seed tpe f32 host_blob_read(kind, dst) → 0/-1 embedder memcpys the blob in host_frame(rgb, ctl) → cmd 0 = frame ready, 2 = add prompt, anything else = exit host_result(dets, nd, ms) nd detections ready; the masked frame is in-place in rgb host_status(code, extra) 1 model-parsed, 2 engine-ready, -1 fatal (extra = detail)

ctl is an i32/f32 slab (4-byte slots): [0] conf ‰ (i32, e.g. 250 = 0.25) [1] masks 0/1 (i32) [2] enabled-class bitmask (i32, bit k = class k) [4] add-prompt slot index (i32) [16..527] add-prompt embedding (f32) dets out: 6 f32 per detection [cls, score, x, y, w, h], max 64.

Frame geometry is fixed 640×480 RGB (the embedder letterboxes the camera into that, exactly like the host-mode page does).

API

& c @ host_blob_size i kind → i

& c @ host_blob_read i kind *u dst → i

& c @ host_frame *u rgb *u ctl → i

& c @ host_result *u dets i nd i ms → v

& c @ host_status i code i extra → v

& c @ host_use_webgpu → i

1 → run the WebGPU backend, else the static CPU kernels

: i WD_W 640

: i WD_H 480

: i WD_K 32

: i WD_MAXDET 64

@ wd_shape4 i a i b i c i d → ( Vec i )

@ wd_pal i ch i k → i

8-colour instance palette (matches the page's JS palette by index)