Skip to content

Repository files navigation

bitcoin++ videos

A resilient field uploader for Bitcoin++ conference recordings. It is a Wails v2 desktop app with a Go multipart-upload worker and a Svelte 5 interface.

What works

  • Drag/drop or native file selection for MOV, MP4, MXF, MTS, and other rough recordings.
  • A persistent upload queue that survives app restarts.
  • Resumable DigitalOcean Spaces multipart uploads. Completed 64 MiB parts are recorded locally; a dropped connection retries with exponential backoff instead of restarting the whole file.
  • Per-file and overall progress, current/average upload speed, remaining bytes, and ETA.
  • Pause/resume/remove controls and automatic continuation after transient failures.
  • SHA-256 fingerprinting before transfer, local and remote duplicate detection, and collision-safe object names.
  • Conference, day, and room metadata are captured with every queued file.
  • Spaces secrets are stored in the operating system keychain, not the queue file.

Development

The included Nix shell contains Go, Node 22, and Wails:

nix develop
cd frontend && npm install && cd ..
wails dev

Build the desktop application with:

wails build

Automated releases

GitHub Actions builds macOS ARM64, macOS Intel, Windows x64, and Linux x64 downloads whenever a version tag is pushed. To publish a release:

git tag v0.1.0
git push origin v0.1.0

The workflow in .github/workflows/release.yml runs the tests, packages each platform, generates SHA256SUMS.txt, and attaches everything to the matching GitHub Release. These initial downloads are unsigned. macOS notarization and Windows code signing should be configured before distributing outside a small trusted team.

On macOS, Wails links against Apple frameworks. If a Nix-provided ld exits with a Trace/BPT trap, install/use a native Go toolchain for the packaging command (the Nix shell remains suitable for frontend work and Go tests). This is a local linker-toolchain issue, not a source compilation error.

For frontend-only work:

cd frontend
npm run dev

The browser preview includes representative upload data; the Wails build starts with the real persisted queue.

Spaces setup

Open the gear menu and provide endpoint, region, bucket, access key, and secret. Use a narrowly scoped Spaces key. Rough mixes use this object-key convention:

{conference-tag}/recordings/raw/{day}/{room}/{original-filename}

For Toronto, the UI maps the field labels to compact path segments, for example Day 1 + Main Stage becomes toronto/recordings/raw/day1/main/filename.mov and Talks Stage becomes talks.

Before uploading, the app computes the file's SHA-256 digest. Stored video keys receive a 12-character digest suffix (filename--a1b2c3d4e5f6.mov) so distinct recordings can never overwrite each other. Each upload directory also receives an immutable marker at _manifest/sha256/{full-hash}.json containing the original filename, final object key, size, and upload time. If that marker—or the same local fingerprint—already exists, the duplicate is skipped.

The uploader creates private objects by default. Access/publishing should be managed by the backend after ingestion.

Bitcoin++ API integration

The UI currently carries a small local event list so field testing is not blocked while the API is being built. The intended API contract is documented in docs/backend-api.md. The next integration step is replacing that list with the returned upload context and using short-lived credentials from the backend instead of long-lived volunteer-entered keys.

Reliability notes

Queue metadata lives at the OS user config path under btcpp-video/queue.json. Removing a queue item does not abort its unfinished multipart upload in Spaces yet; a backend lifecycle rule should expire incomplete multipart uploads until an explicit abort flow is added.

Configure that safety-net rule without replacing other bucket lifecycle policies:

read "SPACES_ADMIN_KEY?Spaces admin access key: "
read -s "SPACES_ADMIN_SECRET?Spaces admin secret key: "
echo
export SPACES_ADMIN_KEY SPACES_ADMIN_SECRET

nix develop --command go run ./cmd/configure-lifecycle -days 7
nix develop --command go run ./cmd/configure-lifecycle -days 7 -apply

unset SPACES_ADMIN_KEY SPACES_ADMIN_SECRET

The command reads the endpoint, region, and bucket from the uploader's settings. The admin credentials exist only in that terminal session and are not written to disk. It preserves existing rules and adds or updates btcpp-video-abort-incomplete-multipart.

About

Video uploader for on-prem ops

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages