{"id":50972851,"url":"https://github.com/longjoel/nosebleed","last_synced_at":"2026-06-19T04:02:02.626Z","repository":{"id":363124336,"uuid":"1155954068","full_name":"longjoel/nosebleed","owner":"longjoel","description":"Web-first libretro runtime for low-latency browser emulation streaming","archived":false,"fork":false,"pushed_at":"2026-06-07T15:08:21.000Z","size":6331,"stargazers_count":0,"open_issues_count":25,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-07T16:06:54.050Z","etag":null,"topics":["emulation","game-streaming","libretro","retro-gaming","webrtc","websocket"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/longjoel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-12T04:59:22.000Z","updated_at":"2026-06-07T15:08:25.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/longjoel/nosebleed","commit_stats":null,"previous_names":["longjoel/nosebleed"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/longjoel/nosebleed","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/longjoel%2Fnosebleed","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/longjoel%2Fnosebleed/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/longjoel%2Fnosebleed/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/longjoel%2Fnosebleed/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/longjoel","download_url":"https://codeload.github.com/longjoel/nosebleed/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/longjoel%2Fnosebleed/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34516549,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-19T02:00:06.005Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["emulation","game-streaming","libretro","retro-gaming","webrtc","websocket"],"created_at":"2026-06-19T04:01:58.422Z","updated_at":"2026-06-19T04:02:02.619Z","avatar_url":"https://github.com/longjoel.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# nosebleed\n\n`nosebleed` is a web-first libretro runtime for running emulator cores server-side and streaming low-latency video, audio, and realtime controller input to browsers.\n\nIt is designed for projects that want to host emulation sessions as a service: one runtime process per match/session, signed player tickets, browser clients, and direct WebSocket/WebRTC transport.\n\n## Why it exists\n\nMost emulator frontends assume the player owns the machine running the emulator. `nosebleed` flips that around:\n\n- native libretro core runs on the host/server\n- browser receives frames/audio\n- browser sends virtual gamepad input\n- orchestration layer assigns players to controller ports\n- signed tickets enforce which client may control which port\n\nThat makes it useful for:\n\n- web arcades\n- LAN game libraries\n- couch co-op over browser clients\n- emulator kiosks\n- preservation/demo environments\n- applications that need an embeddable libretro streaming backend\n\n## Repository layout\n\n- `apps/nosebleed` — Rust runtime crate and CLI binary.\n- `packages/player-sdk` — browser TypeScript SDK for consuming streams.\n- `packages/joel-nosebleed-arcade` — example/experimental arcade frontend.\n- `docs` — architecture and product notes.\n- `scripts` — repo-level helper scripts.\n\n## Install prerequisites\n\n- Rust stable\n- Node.js with Corepack / pnpm\n- A native libretro core (`.so` on Linux) for real games\n\n```bash\ncorepack enable\ncorepack prepare pnpm@10.4.1 --activate\npnpm install\n```\n\n## Run the runtime\n\nMock mode, no emulator core required:\n\n```bash\ncargo run -p nosebleed -- --listen 127.0.0.1:8080\n```\n\nWith a libretro core and ROM/content file:\n\n```bash\ncargo run -p nosebleed -- \\\n  --listen 127.0.0.1:8080 \\\n  --core /path/to/core.so \\\n  --content /path/to/game.rom\n```\n\nOpen:\n\n```text\nhttp://127.0.0.1:8080/\n```\n\n## Build\n\n```bash\npnpm build\n```\n\nOr build pieces independently:\n\n```bash\npnpm build:app      # Rust runtime binary\npnpm build:sdk      # TypeScript player SDK\npnpm build:arcade   # example arcade frontend\n```\n\n## Browser SDK\n\n```ts\nimport { NosebleedPlayer } from \"@nosebleed/player-sdk\";\n\nconst player = new NosebleedPlayer({\n  baseUrl: \"http://127.0.0.1:8080\",\n  canvas: document.querySelector(\"#screen\") as HTMLCanvasElement,\n  token: \"\u003coptional-signed-ticket\u003e\",\n  transport: \"auto\",\n  enableAudio: true,\n  defaultPort: 0\n});\n\nawait player.enableAudio();\nawait player.connect();\n\nplayer.sendInput({\n  buttons: { a: true, start: false },\n  axes: { lx: 0, ly: 0 }\n});\n```\n\nSee `packages/player-sdk/README.md` for more SDK examples.\n\n## Public service model\n\nFor multiplayer/orchestrated sessions, run one `nosebleed` process per match and mint signed tickets for clients:\n\n```bash\nNOSEBLEED_AUTH_SECRET=\"shared-secret\" cargo run -p nosebleed -- \\\n  --listen 0.0.0.0:8080 \\\n  --core /path/to/core.so \\\n  --content /path/to/game.rom \\\n  --require-auth\n```\n\nClient tokens specify:\n\n- `match_id`\n- `player_id`\n- `role`: `player`, `spectator`, or `observer`\n- `allowed_ports`: controller ports the player may control\n- `exp_unix_ms`: hard expiry\n\nSee `apps/nosebleed/docs/public-service.md` for the full protocol and auth model.\n\n## Runtime crate\n\nThe Rust crate exposes a library target as well as the CLI binary. Hosts can import server/session/input/protocol primitives from the crate, or simply spawn the CLI process.\n\n```toml\n[dependencies]\nnosebleed = \"0.1\"\n```\n\n## Status\n\nEarly public release. The runtime is functional, but APIs and packet formats may still change before `1.0`.\n\n## License\n\nMIT. See `LICENSE`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flongjoel%2Fnosebleed","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flongjoel%2Fnosebleed","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flongjoel%2Fnosebleed/lists"}