cardstream
Om

Poängen är att fråga en gång per kort, inte en gång per bildruta

Kortigenkänning fungerar redan. Rikta en bra modell mot ett samlarkort så kommer namnet, setet och numret tillbaka på ungefär en halv sekund. Det är när man kör det mot video som det faller ihop, inte av tekniska skäl utan av ren volym.

Video är mest upprepning. Ett kort som hålls upp i fyra sekunder med femton bildrutor i sekunden blir sextio bilder av ett och samma kort, och frågar man en identifieringsslutpunkt sextio gånger får man samma svar sextio gånger. Varje naiv streampipeline gör precis så, och det är därför streamanalys har rykte om sig att vara något som bara en välfinansierad plattform har råd med.

cardstream finns för att ta bort den upprepningen. Det är en liten tillståndsmaskin mellan din video och igenkänningsanropet, byggd nästan helt på signaler som den räknar fram själv: har scenen blivit stilla, är det här samma kort som för en stund sedan, finns det över huvud taget ett kort i bild? Anropet går iväg när ett verkligt nytt kort ligger still, och annars inte. Allt annat körs på hårdvara som du redan äger.

Räkneexemplet

Ett anrop per kort, inte per bildruta

En timmes sändning med femton bildrutor i sekunden, den högsta bildfrekvens som projektet är verifierat mot, och ungefär hundra olika kort framför linsen. Två sätt att analysera exakt samma video:

Bildruta för bildruta 54 000

identifieringsanrop: ett per bildruta, och de flesta upprepar en fråga som besvarades för ett ögonblick sedan.

Med cardstream ~100

identifieringsanrop: ett per unikt kort, oavsett bildfrekvens och oavsett hur länge du håller upp varje kort.

Ungefär 540× färre anrop, och skillnaden är inget sifferknep: den är hela konstruktionen. Håll ett kort stilla och antalet står kvar. Kör kameran snabbare och antalet står kvar. Antalet anrop följer korten du visar, inte timmarna du streamar.

Förvaltning

Vilka som håller det igång

Byggt av folk som levererar igenkänning

cardstream kommer från teamet bakom Ximilars igenkänning av samlarobjekt. Identifieringsslutpunkterna som anropas är samma som vi kör i produktion, så klienten och tjänsten underhålls av samma människor.

Arbetet sker öppet

Hela paketet finns på GitHub: tillståndsmaskinen, båda driftsätten och webbgränssnittet. Ingenting i beslutslogiken är gömt bakom en tjänst som du inte kan granska.

Testat utan nätverk

Hela testsviten körs offline, med attrapper i stället för modellfilerna och HTTP-anropen. Forka repot på en laptop utan API-nyckel och du kan ändå se om du har haft sönder något.

Principer

Det här får koden aldrig glömma

  1. Ett anrop per kort, inte per bildruta

    Varje designbeslut börjar här. Om en signal kan räknas fram lokalt körs den före det enda anrop som lämnar datorn.

  2. En enda kopia av beslutslogiken

    När ett anrop ska göras avgörs i exakt en modul. Inte utspritt över drivkod, transport och gränssnitt, där tre personer kan ändra det på tre sätt, utan i en fil som går att läsa i ett svep.

  3. Drivkoden hålls tunn

    Schemaläggning, loggning och I/O hör till drivkoden. Vad som räknas som ett nytt kort hör till motorn. Byter du sättet som bildrutorna kommer in på ändras aldrig i tysthet när ett anrop går iväg.

  4. Inget blockerar bildloopen

    Avkodning, detektering, HTTP och disk körs utanför loopen. En långsam identifiering kostar en tappad bildruta, men den förvandlar aldrig din stream till en växande fördröjning.

  5. Ingen leverantörsinlåsning, inte ens hos oss

    Identifieringsanropet är ett enda utbytbart steg bakom ett litet gränssnitt. Varje spärr, strypning och cache fortsätter att fungera om du riktar det mot något helt annat.

  6. Egen drift som standard

    Din hårdvara, din nyckel, din video. I klientläget är ett enda utsnitt per unikt kort det enda som lämnar datorn, om du inte själv väljer att spara sändningen på ditt eget Ximilar-konto.

Fältanteckningar

Sådant korten har lärt oss

En del av det här går så tvärt emot intuitionen att vi skriver ner det där nästa person hittar det: i repot, bredvid koden som det styr.

En hjälpsam ledtråd kan kosta träffsäkerhet

Om du talar om för slutpunkten vilket spel ett kort kommer från stängs dess egen klassificerare för skriftsystem av, och då faller den tillbaka på latin. Ett japanskt kort matchas då i tysthet mot sin engelska utgåva. Det är uppmätt, inte gissat, och därför behandlas ett angivet spel utan skriftsystem som ett fel.

Ett lite generösare utsnitt matchar bättre

Ett snävt snitt runt kortet ser rätt ut och presterar sämre. Utsnittet som skickas iväg har en avsiktlig marginal, eftersom lite sammanhang slår en ren kant.

Hellre återhämta sig än låtsas

När ett anrop hänger sig förbi sin timeout tar sig pipelinen loss själv och går vidare, i stället för att vänta på ett resultat som kanske aldrig kommer. Begränsningen står nedskriven i repot i stället för att sopas under mattan.

Källkod och bidrag

Läs koden, kör den, skicka patchar

Repot är offentligt: ett installerbart Python-paket med oberoende extras och ett webbgränssnitt. Vikterna för lokaliseraren och embeddingmodellen är våra egna, tränade och publicerade under Apache-2.0 tillsammans med releaserna. Issues och pull requests är välkomna, särskilt rapporter från riktiga sändningar, som visar sådant som ingen testrigg gör.

Själva igenkänningen är Ximilars slutpunkt och kommer alltid att vara det; det är den delen som har kortdatabasen bakom sig. Allt runt omkring är ditt att ändra.

Öppen källkod. Egen drift. Din stream, din stack.

Ingen plattform i mitten och ingen licens per användare: anslut Ximilars API eller ditt eget identifieringssystem, så anropar cardstream det en gång per unikt kort i stället för en gång per bildruta. Oavsett om du kör breaks på Whatnot, sänder i Fanatics Live-stil eller streamar från din egen liveshoppinglösning kan du köra cardstream redan i kväll, på den hårdvara du redan har.