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.
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:
identifieringsanrop: ett per bildruta, och de flesta upprepar en fråga som besvarades för ett ögonblick sedan.
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.
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.
Det här får koden aldrig glömma
-
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.
-
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.
-
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.
-
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.
-
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.
-
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.
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.
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.