cardstream
Om

Pointen er at spørge én gang pr. kort, ikke én gang pr. billede

Kortgenkendelse virker allerede. Peg en god model mod et samlekort, og navnet, sættet og nummeret kommer tilbage på cirka et halvt sekund. Det er først, når man kører den mod video, at det falder fra hinanden. Ikke teknisk, men på grund af den rene mængde.

Video er mest gentagelser. Et kort, der holdes op i fire sekunder ved femten billeder i sekundet, er tres billeder af ét kort, og spørger man et identifikationsendpoint tres gange, får man det samme svar tres gange. Det er præcis, hvad enhver naiv streamingpipeline gør, og derfor har streamanalyse ry for at være noget, kun en velpolstret platform kan køre.

cardstream findes for at fjerne den gentagelse. Det er en lille tilstandsmaskine mellem din video og genkendelseskaldet, bygget næsten udelukkende af signaler, den selv regner ud: Er scenen faldet til ro? Er det samme kort som for et øjeblik siden? Er der overhovedet et kort i billedet? Kaldet går af sted, når et virkelig nyt kort ligger stille, og ellers ikke. Alt andet kører på hardware, du allerede ejer.

Regnestykket

Ét kald pr. kort, ikke pr. billede

En times show ved femten billeder i sekundet, som er den højeste hastighed, projektet er verificeret mod, og omkring hundrede forskellige kort foran linsen. To måder at analysere præcis den samme video på:

Billede for billede 54.000

identifikationskald: ét pr. billede, og de fleste stiller igen et spørgsmål, der blev besvaret for et øjeblik siden.

Med cardstream ~100

identifikationskald: ét pr. nyt kort, uanset din billedhastighed, og uanset hvor længe du holder hvert kort op.

Omkring 540× færre kald, og forskellen er ikke et trick med tallene: Den er hele designet. Hold et kort stille, og tallet rører sig ikke. Lad kameraet køre hurtigere, og tallet rører sig ikke. Antallet af kald følger de kort, du viser, ikke de timer, du streamer.

Vedligeholdelse

Hvem holder det kørende

Bygget af folk, der har genkendelse i drift

cardstream kommer fra teamet bag Ximilars genkendelse af samleobjekter. De identifikationsendpoints, det kalder, er dem, vi selv har i produktion, så klienten og tjenesten vedligeholdes af de samme mennesker.

Arbejdet foregår i det åbne

Hele pakken ligger på GitHub: tilstandsmaskinen, begge driftsformer og brugerfladen i browseren. Intet i beslutningslogikken er gemt bag en tjeneste, du ikke kan kigge ind i.

Testet uden netværk

Hele testpakken kører offline, hvor fakes træder i stedet for modelfilerne og HTTP-kaldene. Fork repoet på en bærbar uden API-nøgle, og du kan stadig se, om du har ødelagt noget.

Principper

Det, koden ikke må glemme

  1. Ét kald pr. kort, ikke pr. billede

    Enhver designbeslutning begynder her. Kan et signal beregnes lokalt, kører det før det ene kald, der forlader computeren.

  2. Én kopi af beslutningslogikken

    Hvornår der skal kaldes, bor i præcis ét modul. Ikke spredt ud over en driver, en transport og en brugerflade, hvor tre personer kan ændre det på tre måder, men i én fil, der kan læses på en aften.

  3. Driverne forbliver tynde

    Planlægning, logning og I/O hører til driveren. Hvad der tæller som et nyt kort, hører til motoren. At skifte den måde, billederne kommer ind på, ændrer aldrig i det stille på, hvornår et kald går ud.

  4. Intet blokerer billedløkken

    Dekodning, detektion, HTTP og disk kører alt sammen uden for løkken. En langsom identifikation koster et tabt billede. Den gør aldrig din stream til en voksende forsinkelse.

  5. Ingen binding til én udbyder, heller ikke til os

    Identifikationskaldet er ét udskifteligt trin bag en lille grænseflade. Hvert filter, hver drosling og hver cache virker stadig, hvis du peger det et helt andet sted hen.

  6. Selvhostet som standard

    Din hardware, din nøgle, din video. I klienttilstand er ét enkelt udsnit pr. nyt kort det eneste, der forlader computeren, medmindre du vælger at gemme showet på din egen Ximilar-konto.

Feltnoter

Det, kortene har lært os

Noget af det er så kontraintuitivt, at vi skriver det ned der, hvor den næste finder det: i repoet, ved siden af den kode, det sætter grænser for.

Et velment hint kan koste nøjagtighed

Fortæller du endpointet, hvilket spil et kort er fra, slår det sin egen klassificering af skriftsystemet fra og falder tilbage på latin, så et japansk kort i det stille matcher sin engelske udgave. Det er målt, ikke gættet, og derfor behandles det som en fejl at angive et spil uden et skriftsystem.

Et lidt løst udsnit matcher bedre

Et stramt snit omkring kortet ser rigtigt ud og klarer sig dårligere. Det udsnit, der sendes af sted, har med vilje en margen, for en smule kontekst slår en ren kant.

Hellere komme videre end lade som ingenting

Når et kald hænger ud over sin timeout, river pipelinen sig selv løs og går videre i stedet for at vente på et resultat, der måske aldrig kommer. Begrænsningen er skrevet ned i repoet i stedet for at blive pyntet på.

Kildekode og bidrag

Læs det, kør det, send patches

Repoet er offentligt: én installerbar Python-pakke med uafhængige extras og en brugerflade i browseren. Vægtene til lokaliseringsmodellen og embeddingmodellen er vores, trænet og udgivet under Apache-2.0 sammen med releaserne. Issues og pull requests er velkomne, især rapporter fra rigtige shows, som afslører ting, ingen testopstilling gør.

Selve genkendelsen er Ximilars endpoint og vil altid være det. Det er den del, der har kortdatabasen bag sig. Alt rundt om den er dit at ændre.

Open source. Selvhostet. Din stream, din stack.

Ingen platform i midten og ingen licens pr. bruger: Tilslut Ximilars API eller dit eget identifikationssystem, så kalder cardstream det én gang pr. nyt kort i stedet for én gang pr. billede. Uanset om du kører breaks på Whatnot, holder et show i stil med Fanatics Live eller streamer fra dit eget liveshopping-setup, kan du køre cardstream i aften på den hardware, du allerede har.