cardstream
Open source Powered by Ximilar Beta version

The best card identification for live streams. Built for breaks, rips and live shows.

cardstream watches your break, rip or show and identifies every trading card the moment it enters the frame — name, set and confidence, live. Analyse your live shopping streams with card tracking system. For streamers that want to know more.

What it identifies

From Pokémon to Magic: The Gathering

Switch category per show and the whole engine follows — detection, gating and the identify call all point at the right endpoint. Every match comes back with name, set, set code, card number, series and year.

🃏

Trading card games

collectibles/v2/tcg_id
Ximilar Ready

Modern and vintage TCG singles, straight off the stream. The endpoint reads the art, the frame and the text, so a card is identified from the same picture your viewers are looking at — no set symbol hunting, no collector-number squinting.

  • Pokémon
  • Magic: The Gathering
  • Yu-Gi-Oh!
  • One Piece
  • Lorcana
  • Digimon
  • Dragon Ball Super
  • Flesh and Blood
  • Star Wars Unlimited
  • Star Wars Destiny
  • MetaZoo
  • Riftbound
  • Weiss Schwarz
  • Union Arena
  • Force of Will
  • Grand Archive
  • Vanguard
  • Marvel Champions
  • Sorcery
  • Final Fantasy
  • Gundam
  • Duel Masters
  • Naruto Mythos
  • Hololive
  • Garbage Pail Kids
🏅

Sports cards sport_id

Rookies, parallels, inserts and autos across every major sport — baseball, basketball, football, soccer, hockey and more — the exact card, the exact set, the exact year.

Coming soon
🧊

Graded slabs slab_id

Reads the label on a graded case — the card inside a PSA, BGS or CGC slab, identified without cracking it.

Coming soon
📚

Comics comics_id

Covers identified the same way as cards: title, issue and year, from a single settled frame.

Coming soon
Not locked to one provider

Plug in a proprietary recogniser — or your own

Everything that decides whether to call happens before the identification itself: detection, the motion gate and the same-card gate are all local and provider-agnostic. The call itself is one swappable step — Ximilar out of the box, a proprietary card identification service, or a model you trained yourself and host on your own hardware.

It is one small interface: a card crop goes in, a match comes out. Implement IdentifyTarget and every gate, throttle and threshold in front of it keeps working exactly as before — still one crop per distinct card, whoever answers it.

# your own recogniser, same engine
class HouseIdentifier(IdentifyTarget):
    def identify(self, crop_bgr):
        return my_service.match(crop_bgr)

# one crop per distinct card, either way
$ cardstream-web --detector rfdetr
Why cardstream.ai?

One call per card, not per frame

The point is to keep streaming analysis down to the calls that actually tell you something new. The open-source alternative to closed card-recognition SaaS: no platform in the middle, no seat licence — your hardware, your API key, and a state machine that only calls out when the card in frame is genuinely new.

54,000 → ~100
API calls per hour

A naive per-frame pipeline at 15 fps fires 54,000 identifications an hour. cardstream fires one per distinct card you show — around a hundred in that same hour.

540×
fewer identification calls

Same hour, same video, same cards: 54,000 calls against roughly 100. Motion and identity gates run locally on your own hardware — a call only goes out when a genuinely new card settles in frame.

$0
platform fee

No SaaS subscription, no per-seat pricing, no lock-in. Self-host the whole stack with identification or connect to the Ximilar API.

Features

Everything a streaming card show needs

A co-host that never misses a card — for live commerce sellers on Whatnot- and Fanatics Live-style platforms, box breaks, card shop streams and collection cataloguing. Anywhere a camera meets cardboard.

Known the moment it hits the frame

No scan button. No waiting. Just show the card — name, set and confidence go from cardboard to card name in about half a second, live on stream.

🎯

One call per card

A motion gate and an embedding identity gate run locally on your own CPU. Hold a card still — zero repeat calls. Swap cards — exactly one new call.

📡

Any stream source

Webcam, video files, RTSP, RTMP and SRT — pulled, or pushed straight from OBS with --listen. WebSocket JPEG feeds for custom rigs.

🔌

Any identification backend

Ximilar collectibles/v2 out of the box — or point the same engine at a proprietary card recogniser, or one you trained and host yourself.

🧠

Bring your own models

The locator weights are ours — a finetuned RF-DETR segmentation model, Apache-2.0, fetched by the installer. Box detectors (RF-DETR, RT-DETRv2) are supported too, if you would rather bring your own export.

🔓

Open source, self-hosted

One Python package, permissively licensed. Read it, fork it, run it on your own hardware. Your key, your data, your infrastructure.

How it works

Smart enough to know when not to call the API

A state machine stands between your stream and the API. Every frame flows through DecisionCore — one state machine, running locally — and three local gates decide when the one API step is actually warranted.

1

Detect

local · no API call

Find the card quadrilateral and deskew a clean crop. Throttled in three tiers by the local motion gate — moving, static-with-card, empty.

2

Motion gate

local · no API call

Cheap mean frame-diff. Only when the scene has settled for N frames is the card worth a closer look. Still moving? Wait.

3

Identity gate

local · no API call

An embedding comparison answers one question: is this the same card as before? Same card → re-emit the cached result.

4

Identify

ximilar · 1 call

Only a genuinely new, settled card triggers a Ximilar identification — async, debounced, off the frame loop. Result pushed back live.

For streamers, breakers and shops

Are you an individual streamer?

One person, one camera, one long night of breaks — you should not need an engineering team to know what card is on screen. Connect the stream you are already running and let cardstream analyse it live, whether you sell on a marketplace or straight off your own channel.

  • Whatnot
  • Fanatics Live
  • eBay Live
  • TikTok Shop
  • Twitch
  • YouTube Live
  • your own site

No account access, no marketplace API keys, no bot in your chat — and no affiliation with any of these platforms. cardstream reads your video, nothing else.

01

You already stream from OBS

Add one more output next to the one feeding your show. Your buyers see exactly what they saw before — a copy of the same feed lands in cardstream, and every card that hits the table gets identified on the way past. The listener below needs the system ffmpeg binary — or skip the second output entirely and let cardstream read the OBS virtual camera as an ordinary webcam.

$ cardstream-web --listen \
      --source rtmp://0.0.0.0:1935/live
# point OBS's second target here
02

Or the camera that is already on the table

Overhead cam, capture card, phone as a webcam — whatever you rip and reveal under. Analysis runs on the machine next to the camera, so nothing but one crop per card ever leaves the room.

$ cardstream-web --source 0
# webcam · browser UI on localhost
03

Or anything with a URL

Encoders, switchers, restreamers, a second studio across town. RTSP, RTMP and SRT pulls, plus WebSocket JPEG feeds when your rig is homemade.

$ cardstream-web \
      --source rtsp://studio/stream1

Live overlay

Name, set and confidence appear the moment a card settles — ready to read out, or to composite back into your scene.

Every card, logged

A running history of everything you showed, timed per appearance. The break notes write themselves.

Sized for one person

No platform fee, no seat licence. A three-hour show is a handful of identification calls, not one per frame.

Quick start

From zero to live identification in 3 steps

1

Install it

A virtualenv, the release wheel (checksum-verified), the model weights and both commands on your PATH. Take the script, pip install the same wheel from PyPI (the weights are a separate download), or clone the repo and build it yourself — Docker and Windows are on the download page.

$ curl -fsSL https://raw.githubusercontent.com/Ximilar-com/cardstream/main/scripts/install.sh | sh
# other install paths → cardstream.ai/download
$ pip install 'cardstream[client,onnx]'   # or: uv tool install 'cardstream[client,onnx]'
# the wheel has no weights — unpack the two tarballs from cardstream.ai/models
# and point the flags at them:
$ cardstream-web --segmentor-model segmentation_model/onnx/model.onnx \
    --embed-model similarity_model/onnx/model.onnx
$ git clone https://github.com/Ximilar-com/cardstream && cd cardstream
$ ./scripts/build-from-source.sh --models
$ source .venv/bin/activate
2

Connect an identification system

Ximilar collectibles/v2 out of the box — a key from ximilar.com is the only credential the whole system needs. Or point the same step at your own recogniser.

$ export XIMILAR_API_KEY=your-key
3

Point a camera at a card

Open the browser UI on your webcam, or feed it your show — RTSP pull, or let OBS push RTMP straight into it. Breaking one set all night? Prefill it and the endpoint stops guessing: English Pokémon out of CRI is three fewer things to get wrong. Set --alphabet whenever you set --game — prefilling the game turns the endpoint's own writing-system detection off. Add --price-stats and every match also brings USD market prices: median, range and latest sale, on the card and in the history.

$ cardstream-web
# → http://127.0.0.1:8001 — hold up a card

# English Pokémon cards, one set (CRI - Chaos Rising), with USD market prices:
$ cardstream-web --game Pokemon --set-code CRI --alphabet latin --price-stats

Open source. Self-hosted. Your stream, your stack.

No platform in the middle, no seat licence: connect the Ximilar API or your own identification system, and cardstream calls it once per distinct card instead of once per frame. Whether you're breaking on Whatnot, running a Fanatics Live-style show, or streaming your own live commerce setup, run cardstream tonight on the hardware you already have.