1-bit-bridge

module
v0.1.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 27, 2026 License: MIT

README ΒΆ

1-bit-bridge

Latest release Go version iOS app on App Store

Companion server for the 1-bit iOS music player β€” bit-exact playback of your own music library, including DSD, from anywhere. The bridge runs on a home server (Windows / Linux / macOS / NAS) and exposes your library over HTTPS + bearer-token auth with a pre-built manifest endpoint, so the iOS app syncs its whole library in a single request instead of walking a slow SMB tree.

πŸ‘‰ 1-bit.app/bridge for the landing page, setup walkthrough, feature reference, troubleshooting, and privacy policy.

Why

1-bit's existing SMB transport is great on LAN but painful over Tailscale / similar overlays: SMB's chatty pread pattern multiplies every round-trip, and DERP-relayed connections can push latency past 3 seconds. 1-bit-bridge replaces SMB with an HTTP/2 protocol purpose-built for the app:

  • 5 primitives matching the iOS app's internal SMBConnectionPool API (list, stat, readRange, download, downloadStreaming), so the existing scanner + playback code paths are unchanged.
  • Pre-built library manifest β€” the bridge keeps a SQLite-backed index; iOS fetches the full library (or a ?since=<mtime> delta) in one call. Both scan phases (walk + enrich) are replaced by a single HTTP GET.
  • Bit-exact preserved β€” the bridge delivers bytes; iOS still pre-caches the full DSF file before playback, protecting the Hugo 2 DoP lock. The bridge never transcodes.

Status

v0.1.7 — wire protocol stays at PROTOCOL.md v1 (additive only since v0.1.6). Headline: Smart Mixes — the bridge now generates rotating, server-side playlists from your library's listening history and audio analysis (Heavy Rotation, Daily Mix, Auto Mix's harmonic flow, Drive Mix, On Repeat, Wind Down, Lift Off, and a time-of-day mix), served at GET /v1/smart-playlists and advertised via the smartPlaylists health flag. The offline audio analysis that was groundwork in v0.1.6 is now fully wired and surfaced — waveform, R128 loudness, and key + tempo (with an ffmpeg decode fallback for AAC/m4a) feed both Smart Mixes and richer iOS quality chips; still opt-in via analysis.enabled, off by default. Album artwork gains Atlas premium covers (up to 1080px, cache-bust-aware so iOS refreshes a stale cover in place). The admin console gets a large UX upgrade: master-quality composition bars, live SSE telemetry (replacing the old polling), a per-worker SoX pipeline grid, an interactive Camelot harmonic wheel, and per-track skip badges in the Library Inspector. CLI + robustness hardening: native Windows port→PID attribution in bridge doctor, sox-FLAC capability verification before features enable, PCM geometry extraction for WAV/AIFF/m4a/MP3, and post-scan track-number + year backfill for existing libraries. macOS binaries are Developer-ID-signed and Apple-notarized; Windows binaries are unsigned for now (Authenticode signing via SignPath Foundation pending). See the releases page for per-release notes.

Install

Grab a pre-built binary from the releases page β€” no Go toolchain required. Pick your OS + arch, then run bridge init.

macOS / Linux:

tar -xzf 1-bit-bridge_*_macos_arm64.tar.gz   # or linux_amd64 / linux_arm64 / macos_amd64
./bridge init

Writes config + TLS cert under ~/Library/Application Support/1-bit-bridge/ (macOS) or $XDG_CONFIG_HOME/1-bit-bridge/ (Linux), registers a launchd user agent / systemd user unit, opens the admin console.

Windows (PowerShell or File Explorer):

# Unzip 1-bit-bridge_*_windows_amd64.zip (or _arm64)
bridge.exe init

Two install paths on Windows:

  • Startup-folder launcher (default) β€” bridge init. Per-user, runs at logon, stops on logout. No admin required. Launcher lives at %APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\com.acoseac.1-bit-bridge.cmd; config under %LOCALAPPDATA%\1-bit-bridge\.
  • Windows Service (survives logout) β€” bridge init --service, run from an elevated PowerShell. Installs an SCM service that starts at boot, runs as LocalSystem, logs to %PROGRAMDATA%\1-bit-bridge\bridge.log. Because the service runs as LocalSystem, point --library at a machine-wide path (e.g. C:\Music) rather than %USERPROFILE%\Music.

Uninstall: run bridge init again and answer "no" to overwrite (Startup launcher), or sc.exe delete 1-bit-bridge from an admin shell (Windows Service).

Preflight: bridge doctor

Before (or any time after) running bridge init, bridge doctor prints a punch list of what's wrong in your environment:

[ok]   platform            darwin/arm64
[ok]   config-dir          /Users/me/Library/Application Support/1-bit-bridge
[ok]   tls-cert            present
[FAIL] port-api            :7788 in use
  ↳ another process owns this port; stop it or pick a different address in bridge.yaml
[ok]   port-admin          free (:7789)
[ok]   library-roots       1 root(s) reachable
[ok]   service-manager     launchctl available
[ok]   browser-opener      open

bridge init runs doctor automatically and bails on fail (use --skip-doctor to override β€” not recommended).

Admin console β€” http://127.0.0.1:7789/. Add/remove library folders, pair iOS devices (QR + copy-buttons), revoke tokens, view scan state + stats. Loopback-only, no auth β€” anyone on the machine already has filesystem access to the token store. (For internet-exposed deployments, see bridge init --public in the public-deployment docs β€” that profile binds the admin console to a routable interface and adds a single-user password login.)

Pairing an iOS device: on the Devices page, click Pair new device, give it a name, optionally edit the bridge URL (defaults to https://<hostname>.local:7788), then generate the token. The modal shows a QR encoding a bridge://pair?... URL β€” scan it in the 1-bit app, or copy the URL/token/fingerprint fields manually.

Build from source

Requires Go 1.25+.

make build          # builds ./bin/bridge for the host OS
make build-all      # cross-compiles darwin/linux/windows Γ— amd64/arm64 into dist/
make test           # unit tests

For a local release dry-run: goreleaser release --snapshot --clean.

Contributing

PRs welcome. See CONTRIBUTING.md for the branch / PR conventions, the pre-push checklist, and the mirror-PR rule that applies whenever a change touches the wire protocol shared with the 1-bit iOS app.

Security

Found a vulnerability? Please report privately via GitHub's Security Advisories β€” see SECURITY.md for scope, response SLA, and what to include in your report.

Tailscale modes

The bridge offers three Tailscale integration modes via the tailscale.mode key in bridge.yaml:

  • cli (default) β€” shells out to the host's installed tailscale binary for status detection and Let's Encrypt cert provisioning on *.ts.net connections. Requires Tailscale to be installed and running on the host.
  • tsnet β€” embeds a tailnet node directly in the bridge process via tailscale.com/tsnet. No Tailscale binary required; LE cert is renewed in-process. Authenticate with bridge tsnet auth on first run, or set tailscale.authKey for unattended deployments.
  • disabled β€” turns off both the CLI auto-pilot and the embedded tsnet node. Use this for LAN-only deployments. The admin tile renders a one-line explanation so operators who flipped to disabled accidentally can recover.

Mode changes require a bridge restart. The admin tile shows the current Tailscale state and any errors from the active path.

Manual run (without bridge init)

For anyone who wants to skip the service install or run the bridge out of an arbitrary directory:

./bridge init --no-service --yes --library /path/to/music --dir ./bridge-data
./bridge serve --config ./bridge-data/bridge.yaml

Protocol

See PROTOCOL.md. Every client endpoint is prefixed /v1/. The admin console (/, /api/*, /static/*) lives on a separate loopback listener and is not part of the wire protocol β€” iOS never talks to it.

License

MIT. See LICENSE.

Directories ΒΆ

Path Synopsis
cmd
bridge command
Command bridge is the 1-bit-bridge server CLI.
Command bridge is the 1-bit-bridge server CLI.
internal
admin
Package admin serves the local-only web console for operating a running bridge instance β€” adding/removing library roots, pairing/revoking client devices, and surfacing scan + uptime stats.
Package admin serves the local-only web console for operating a running bridge instance β€” adding/removing library roots, pairing/revoking client devices, and surfacing scan + uptime stats.
adminauth
Package adminauth manages the admin console's single-user authentication layer: bcrypt-hashed credentials persisted to disk, in-memory session tokens, and a per-(IP, username) login rate limiter.
Package adminauth manages the admin console's single-user authentication layer: bcrypt-hashed credentials persisted to disk, in-memory session tokens, and a per-(IP, username) login rate limiter.
advertise
Package advertise enumerates every network endpoint a running bridge is reachable at β€” LAN IPv4 / IPv6, mDNS hostname, Tailscale interface β€” so /v1/health can self-report the full list to iOS clients, and the admin pairing QR can bake alternates into `bridge://pair?urls=...`.
Package advertise enumerates every network endpoint a running bridge is reachable at β€” LAN IPv4 / IPv6, mDNS hostname, Tailscale interface β€” so /v1/health can self-report the full list to iOS clients, and the admin pairing QR can bake alternates into `bridge://pair?urls=...`.
analyze
Package analyze owns the bridge's offline audio analysis: decoding a source file to PCM via sox(1), reducing it to a compact peak waveform sidecar, and the worker pool the `bridge analyze` CLI and the serve-side background pass share.
Package analyze owns the bridge's offline audio analysis: decoding a source file to PCM via sox(1), reducing it to a compact peak waveform sidecar, and the worker pool the `bridge analyze` CLI and the serve-side background pass share.
api
Package api implements the HTTP/2 handlers for the v1 wire protocol (see PROTOCOL.md at the repo root).
Package api implements the HTTP/2 handlers for the v1 wire protocol (see PROTOCOL.md at the repo root).
atlasharvest
Package atlasharvest is the bridge side of the Phase-H bridge-driven bulk harvest.
Package atlasharvest is the bridge side of the Phase-H bridge-driven bulk harvest.
atomicwrite
Package atomicwrite provides the tmp-file-then-rename helper the scanner and enricher both use to commit cached JPEGs to disk without a concurrent reader ever observing a torn file.
Package atomicwrite provides the tmp-file-then-rename helper the scanner and enricher both use to commit cached JPEGs to disk without a concurrent reader ever observing a torn file.
auth
Package auth manages bearer tokens: generation, hashed storage, and request-time validation.
Package auth manages bearer tokens: generation, hashed storage, and request-time validation.
backup
Package backup snapshots and restores the bridge's state directory.
Package backup snapshots and restores the bridge's state directory.
config
Package config loads and validates bridge.yaml (library roots, listen address, TLS paths, scan interval).
Package config loads and validates bridge.yaml (library roots, listen address, TLS paths, scan interval).
dlna
Package dlna implements a UPnP/DLNA MediaServer surface that lets spec-compliant network audio renderers (Chord 2go, Lumin, dCS Network Bridge, Auralic Aries, Bluesound, Eversolo, …) discover and stream the bridge's library bit-exact.
Package dlna implements a UPnP/DLNA MediaServer surface that lets spec-compliant network audio renderers (Chord 2go, Lumin, dCS Network Bridge, Auralic Aries, Bluesound, Eversolo, …) discover and stream the bridge's library bit-exact.
dlna/discovery
Package discovery is the bridge-side SSDP M-SEARCH client + renderer cache that powers `GET /v1/renderers`.
Package discovery is the bridge-side SSDP M-SEARCH client + renderer cache that powers `GET /v1/renderers`.
doctor
Package doctor runs environment preflight checks for `bridge init` and `bridge doctor`.
Package doctor runs environment preflight checks for `bridge init` and `bridge doctor`.
dsn
Package dsn builds SQLite URI DSN strings that safely encode filesystem paths containing URL-reserved characters (?, #, %) across POSIX and Windows.
Package dsn builds SQLite URI DSN strings that safely encode filesystem paths containing URL-reserved characters (?, #, %) across POSIX and Windows.
enrich
Package enrich looks up external metadata (MusicBrainz, Cover Art Archive) for tracks that are missing MBIDs or artwork, then updates the manifest store.
Package enrich looks up external metadata (MusicBrainz, Cover Art Archive) for tracks that are missing MBIDs or artwork, then updates the manifest store.
fs
Package fs resolves client-supplied relative paths against a configured library root and rejects LEXICAL traversal (`..`, absolute paths, NUL bytes).
Package fs resolves client-supplied relative paths against a configured library root and rejects LEXICAL traversal (`..`, absolute paths, NUL bytes).
fsutil
Package fsutil holds small cross-cutting filesystem helpers shared across the bridge β€” today the durability barrier (file + parent-dir fsync) that producers of on-disk sidecars run before committing the SQLite row that points at the freshly-written file.
Package fsutil holds small cross-cutting filesystem helpers shared across the bridge β€” today the durability barrier (file + parent-dir fsync) that producers of on-disk sidecars run before committing the SQLite row that points at the freshly-written file.
integrity
Package integrity contains the bridge's proactive consistency watchers β€” long-lived goroutines that walk durable state on a schedule and reconcile drift between what the bridge thinks exists (SQLite manifest, track_variants table) and what actually exists on disk.
Package integrity contains the bridge's proactive consistency watchers β€” long-lived goroutines that walk durable state on a schedule and reconcile drift between what the bridge thinks exists (SQLite manifest, track_variants table) and what actually exists on disk.
logging
Package logging owns the bridge's structured-logging entry point.
Package logging owns the bridge's structured-logging entry point.
lrucache
Package lrucache implements a small bounded LRU cache safe for concurrent use.
Package lrucache implements a small bounded LRU cache safe for concurrent use.
manifest
Package manifest owns the library index: the SQLite-backed store, per- format tag extractors (FLAC / DSF / ALAC / WAV / MP3), and the filesystem scanner that drives them.
Package manifest owns the library index: the SQLite-backed store, per- format tag extractors (FLAC / DSF / ALAC / WAV / MP3), and the filesystem scanner that drives them.
mdns
Package mdns advertises the bridge on the local network as _onebit-bridge._tcp.local.
Package mdns advertises the bridge on the local network as _onebit-bridge._tcp.local.
metrics
Package metrics is the Prometheus exposition surface for the bridge.
Package metrics is the Prometheus exposition surface for the bridge.
packaging
Package packaging renders service-manager unit files (launchd plist on darwin, systemd user unit on linux) and installs them where the user's service manager expects to find them.
Package packaging renders service-manager unit files (launchd plist on darwin, systemd user unit on linux) and installs them where the user's service manager expects to find them.
pairing
Package pairing implements the in-memory state machine for the admin-approval pairing flow.
Package pairing implements the in-memory state machine for the admin-approval pairing flow.
smartplaylist
Package smartplaylist generates server-side "smart" / dynamic playlists (Heavy Rotation, Auto Mix, Forgotten Favorites, time-of-day, Daily Mix, The Finish Line) from playback-history aggregations + offline audio analysis.
Package smartplaylist generates server-side "smart" / dynamic playlists (Heavy Rotation, Auto Mix, Forgotten Favorites, time-of-day, Daily Mix, The Finish Line) from playback-history aggregations + offline audio analysis.
smartplaylistgen
Package smartplaylistgen orchestrates smart-playlist regeneration: it assembles the pure engine's Inputs from manifest.Store aggregations, runs internal/smartplaylist.Generate, and writes the populated families to the `smart_playlists` cache.
Package smartplaylistgen orchestrates smart-playlist regeneration: it assembles the pure engine's Inputs from manifest.Store aggregations, runs internal/smartplaylist.Generate, and writes the populated families to the `smart_playlists` cache.
supervision
Package supervision answers a single runtime question: "if this process calls os.Exit(0), will something relaunch us?"
Package supervision answers a single runtime question: "if this process calls os.Exit(0), will something relaunch us?"
tailscale
Package tailscale wraps the small surface area of the Tailscale CLI the bridge needs for HTTPS auto-pilot: detecting whether Tailscale is installed and what the local node's MagicDNS name is, and minting an HTTPS certificate via `tailscale cert`.
Package tailscale wraps the small surface area of the Tailscale CLI the bridge needs for HTTPS auto-pilot: detecting whether Tailscale is installed and what the local node's MagicDNS name is, and minting an HTTPS certificate via `tailscale cert`.
tls
Package tls mints a self-signed certificate on first run and loads existing cert/key material on subsequent runs.
Package tls mints a self-signed certificate on first run and loads existing cert/key material on subsequent runs.
tlsacme
Package tlsacme wraps `golang.org/x/crypto/acme/autocert` with the glue the bridge needs to participate in `internal/tls.Manager`'s SNI switcher:
Package tlsacme wraps `golang.org/x/crypto/acme/autocert` with the glue the bridge needs to participate in `internal/tls.Manager`'s SNI switcher:
transcode
Package transcode owns offline PCM-upscaling: building sox(1) invocations, choosing variant identifiers + sidecar paths, and the worker pool the CLI subcommand and (in Phase 2.5) the HTTP `POST /v1/upscale` handler share.
Package transcode owns offline PCM-upscaling: building sox(1) invocations, choosing variant identifiers + sidecar paths, and the worker pool the CLI subcommand and (in Phase 2.5) the HTTP `POST /v1/upscale` handler share.
tsnet
Package tsnet wraps the upstream tailscale.com/tsnet library so the bridge can run as its own embedded tailnet node β€” no external `tailscaled` daemon, no CLI shell-out, no on-disk Let's Encrypt cert files.
Package tsnet wraps the upstream tailscale.com/tsnet library so the bridge can run as its own embedded tailnet node β€” no external `tailscaled` daemon, no CLI shell-out, no on-disk Let's Encrypt cert files.
updater
Package updater polls the GitHub Releases API for newer 1-bit-bridge builds and drives the full self-update lifecycle: poll β†’ download β†’ SHA-256 verify (always) β†’ platform signature verify (macOS Apple codesign + Team-ID; Linux/Windows currently TLS-of-checksums.txt only, see verify_other.go for the seam where Sigstore / minisign / SignPath would land) β†’ swap (atomic rename on Unix; live rename + caller-driven restart on Windows, see swap_windows.go β€” note this is NOT the MoveFileEx/MOVEFILE_DELAY_UNTIL_REBOOT "pending rename" mechanism) β†’ arm rollback marker.
Package updater polls the GitHub Releases API for newer 1-bit-bridge builds and drives the full self-update lifecycle: poll β†’ download β†’ SHA-256 verify (always) β†’ platform signature verify (macOS Apple codesign + Team-ID; Linux/Windows currently TLS-of-checksums.txt only, see verify_other.go for the seam where Sigstore / minisign / SignPath would land) β†’ swap (atomic rename on Unix; live rename + caller-driven restart on Windows, see swap_windows.go β€” note this is NOT the MoveFileEx/MOVEFILE_DELAY_UNTIL_REBOOT "pending rename" mechanism) β†’ arm rollback marker.
upnp
Package upnp is the bridge's UPnP/DLNA control-point client toward an UPSTREAM MediaServer (e.g.
Package upnp is the bridge's UPnP/DLNA control-point client toward an UPSTREAM MediaServer (e.g.
upnpingest
Package upnpingest is the orchestration layer that turns a discovered upstream UPnP MediaServer into rows in the bridge's manifest store.
Package upnpingest is the orchestration layer that turns a discovered upstream UPnP MediaServer into rows in the bridge's manifest store.
upnpproxy
Package upnpproxy contains the HTTP byte proxy that fronts an upstream UPnP MediaServer's `<res>` URL with bit-exact passthrough.
Package upnpproxy contains the HTTP byte proxy that fronts an upstream UPnP MediaServer's `<res>` URL with bit-exact passthrough.
version
Package version exports the server build version and the wire protocol version.
Package version exports the server build version and the wire protocol version.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL