Inspiration

AI image and video tools are everywhere now. What’s still awkward is the part that happens after you hit generate: someone forwards a file, it shows up in a pitch deck or a newsroom Slack, and nobody can tell if it’s the original output or a quiet edit.

We kept running into that gap. Genblaze already produces provenance manifests, and Backblaze B2 is a solid place to keep the bytes. We wanted something a judge (or an editor) could actually use — generate, store, and then check a file without needing a PhD in hashing.

That’s ProofStudio: make the “can I trust this file?” question boringly easy to answer.

What it does

ProofStudio is a small studio web app with three main surfaces:

  • Studio — type a prompt, generate an image or a short video clip. Image runs go through a two-step Genblaze pipeline (Imagen generate, then an editorial pass). Video uses Veo 3.1 Lite at 4 seconds / 720p, with Fast as a fallback if Lite fails.
  • Gallery — browse past runs pulled from B2, see step counts, open a run into Verify.
  • Verify — upload a file (or paste a run ID). We re-hash the bytes, look up the sidecar manifest on B2, and show whether it still matches. Change one byte and it fails. There’s a preview of what you uploaded so the pass/fail isn’t abstract.

Every successful run stores the media and a sidecar provenance manifest on Backblaze B2 (private bucket, served through our API proxy). Genblaze’s Manifest.verify() is part of that check. You can also refine a previous run and keep parent_run_id lineage.

Live demo: https://proofstudio-web-rawshyh2rq-as.a.run.app

How we built it

Frontend is Next.js (Studio / Gallery / Verify). Backend is FastAPI. Generation is async: POST /api/generate returns a job_id immediately, the UI polls status, so long Veo or Imagen runs don’t die on HTTP timeouts.

In genblaze mode the backend builds a Genblaze Pipeline, runs Google providers (Imagen / Veo), then lands assets and manifests on B2 through an S3-compatible path. Layout is content-addressable (assets/<sha>/…, manifests/<run_id>.json) plus a small run index. We also keep a mock mode that generates real local bytes with no API keys — useful while wiring verify and storage.

For deploy we use Cloud Run (asia-southeast1), with secrets in Secret Manager, max-instances=1 and no CPU throttling so in-memory jobs don’t vanish mid-poll. PUBLIC_BASE_URL keeps asset URLs pointing at the live API instead of localhost.

Challenges we ran into

Veo → B2 wasn’t plug-and-play. The provider path we hit stored Google Files API URIs that our transfer step couldn’t download without auth. We had to materialize the MP4 locally (file://) before the B2 sink ran. Related: operation.name as a string vs what google-genai 2.x expects for poll/get. That took more hours than the happy-path docs suggest.

Fallback only helps if the error code is right. Lite returning “model not found”-style failures mapped to UNKNOWN in places, so Genblaze never tried Fast. We normalize those to MODEL_ERROR so fallback_models actually fires.

Cost and demo risk. Full Veo Standard clips add up fast. We standardized on Lite, 4 seconds, 720p (~$0.20/clip) and kept a pre-baked Gallery run as a recording backup.

Cloud Run quirks. Job state lives in memory, so multiple instances break polling. Mixed Content also bit us when old index entries still pointed at http://localhost:8000/files/... from a HTTPS page — we rewrite those onto the current API base.

Accomplishments that we're proud of

  • A full loop that judges can click through live: generate → B2 → verify original vs tampered.
  • Real multi-step Genblaze image pipeline (generate + editorial), not a single opaque API call.
  • Video that actually lands on B2 with the same sidecar story as images.
  • Private B2 + proxy so we don’t need a public bucket for the demo.
  • Shipping on Cloud Run with health checks that report genblaze + backblaze-b2.

What we learned

Provenance is only as useful as the verify UX. Hash strings in a JSON blob don’t convince anyone; uploading a file and seeing Verified / Not verified next to a preview does.

We also learned that “SDK integration” often means fighting version edges — provider adapters, error codes, and how bytes move from a model host into your own object store. Genblaze’s pipeline + fallback model ideas are solid once those edges are handled. And for a hackathon, cheaper defaults (Lite, short duration) matter as much as features; burned quota doesn’t impress judges.

What's next for ProofStudio

  • Optional inline embed of manifests into MP4/PNG (Genblaze media handlers) alongside the sidecar, for offline verify when the file travels alone.
  • Stronger lineage UI for refine chains (parent/child as a small graph, not just an ID).
  • Signed share links with expiry, so editors can send a verify URL without exposing the whole gallery.
  • Tighten the Veo adapter upstream (or drop the monkeypatch) once newer genblaze-google builds cover the Files download path we hit.
  • Broader provider mix later — same Studio/Verify shell, different Genblaze steps.

Built With

Share this project:

Updates