Ukázková verze 0.1.0, formát výsledku 0.1

BEAM X1 Sense

Tenký doplněk, který si vložíte do vlastní školící stránky jedním skriptem. Po souhlasu účastníka sleduje přes kameru a mikrofon, jestli je ve školení přítomen a pozorný, a po skončení vám předá výsledek na společné časové ose v milisekundách.

Princip

Měříme to, co umíme

Doplněk předává naměřenou realitu bez výkladu. Co z ní uděláte, je na vás.

U každého měření uvádíme spolehlivost

Naměřeno, nebo odvozeno pravidly. Procenta přesnosti neuvádíme, protože je nemáme změřená, a nechceme je vymýšlet.

Žádný obraz ani zvuk

Doplněk neukládá a neodesílá obraz ani zvuk. Výsledkem jsou body obličeje, metriky, události a přepis řeči.

Všechno běží v prohlížeči účastníka

Zpracování probíhá u účastníka. Výsledek dostane hostitel až po jeho schválení.

Co se měří

Každé pole výsledku má záznamy s časem t (ms od startu měření). Spolehlivost je i přímo ve výsledku, v timeline.measurements.<pole>.reliability, spolu s krátkým zdůvodněním a příznakem validated: false.

PoleCo obsahujeZápisSpolehlivost
faceDetectedJe obličej v záběru1 snaměřeno
presenceChecksPočet obličejů v záběru (druhá kontrola, až 3)5 snaměřeno
landmarkLog478 bodů obličeje z modelu MediaPipe2 snaměřeno
blendshapeLog52 svalových hodnot z modelu MediaPipe2 snaměřeno
micVolumeHlasitost, rms, dominantní frekvence, příznak mluvení1 snaměřeno
voiceCommentsPřepis řeči po větách s jistotou rozpoznávačekaždá větanaměřeno
sessionLogUdálosti: start, stav kamery, okno ztratilo fokus, změna viditelnosti karty, myš v okně nebo mimo něj, celá obrazovkapři událostinaměřeno
attentionPoloha duhovky mezi koutky oka, 100 = uprostřed (nezahrnuje otočení hlavy)1 sodvozeno
gazeAttentionPozornost podle pohledu: odklon do stran, nahoru a extrémně dolů1 sodvozeno
headPoseNatočení hlavy ve stupních: pitch, yaw, roll1 sodvozeno
distanceOdhad vzdálenosti od kamery v cm, přesný jen po kalibraci měřítka1 sodvozeno
blinkRatePočet mrknutí za posledních 60 s (mrknutí je zavření očí do 500 ms)1 sodvozeno
fatigueIndicatorsPERCLOS (podíl času se zavřenýma očima za 60 s), průměrná doba mrknutí, zívnutí za 5 min1 sodvozeno
fatigueHeuristické skóre únavy, prahy jsou předpoklady a nebyly ověřeny1 sodvozeno
emotionsVýraz obličeje (Happy, Surprised, Focused, Relaxed, Neutral) pravidly nad blendshapy, není to natrénovaný model emocí1 sodvozeno
gesturesGesta rukou a poloha ruky1 sodvozeno
cameraSnapshotsVšechny metriky jednoho okamžiku pohromadě (a volitelně všech 52 blendshapů)1 sodvozeno

Naměřeno je přímý výstup senzoru nebo modelu. Odvozeno je spočítáno jednoduchými pravidly z naměřeného a je třeba s tím tak zacházet. Úroveň unreliable je ve formátu pro měření se známým problémem ve výpočtu, aktuálně ji žádné měření nemá.

Kvalita konkrétní relace

Blok quality ve výsledku říká, jak dopadlo toto měření: od kdy kamera měřila (MediaPipe se načítá několik sekund), v kolika snímcích byl nalezen obličej, kolik bylo mezer bez obličeje a jak dlouhá byla nejdelší, nejvíce osob v záběru, podíl mluvení a počet přepsaných vět a chyb rozpoznávání řeči. Podle něj poznáte, jestli měření stojí za zpracování, třeba když účastník kameru zakryl.

Vypínače kategorií

Každou kategorii dat lze v init vypnout (categories: { landmarks: false }). Vypnutá kategorie se nesbírá a její pole ve výsledku chybí. Výchozí je vše zapnuto, kromě photos.

KategoriePole výsledku
facefaceDetected, emotions, attention, gazeAttention, headPose, distance, blinkRate, fatigue, fatigueIndicators, cameraSnapshots, presenceChecks
blendshapesblendshapeLog
landmarkslandmarkLog
gesturesgestures
voicevoiceComments
audiomicVolume
activitysessionLog
devicedevice
photos (výchozí vypnuto)faceSnapshot, facePhotos, periodicPhotos, jen pro ladění

Vložení do vaší stránky

1. Skript a inicializace

Stáhnout beamsense-0.1.0.js (verze 0.1.0, formát výsledku 0.1, 110 kB). Soubor se nikdy nemění, nové verze přibývají jako nové soubory. Poslední sestavení je vždy na dist/beamsense.js, to se ale mění a pro nasazení ho nepoužívejte.

Otisk SHA-256: d825cf51b92a4e89ffd67e6b6a2cc543c6a8d0c97b3c3e62515a2736f7cc13f3

<script src="https://sense.beamx1.cz/releases/beamsense-0.1.0.js"
        integrity="sha256-2CXPUbkqTon/1n5raizFQ8ao0Ml7PD5iUVonNvfME/M="
        crossorigin="anonymous"></script>

Atribut integrity zajistí, že prohlížeč soubor spustí jen tehdy, když odpovídá otisku. Doporučujeme si soubor stáhnout a dát na vlastní hosting, pak integrity nepotřebujete.

Skript do globálního prostoru stránky přidá jen window.BeamSense.

<script src="beamsense.js"></script>
<script>
  BeamSense.init({
    lang: 'cs',
    host: { sessionId: 'id-relace-na-vasi-strane', participantRef: 'odkaz-na-ucastnika' },
    onResult: function (result) {
      // výsledek po schválení účastníkem, pošlete ho na svůj server
    }
  });
</script>

Po init se vpravo nahoře zobrazí ikona s oknem pro souhlas. Po souhlasu se spustí kamera a mikrofon. Na konci školení zavolejte BeamSense.stop(): účastník uvidí volbu Odeslat, Stáhnout kopii nebo Zahodit. Po Odeslat dostane vaše onResult výsledek. Chcete-li výsledek odesílat sami, použijte volbu endpoint (POST).

2. Volby a volání

Volba initVýznam
categoriesVypínače kategorií dat
langcs nebo en
hostsessionId, participantRef a další vaše pole, předají se do výsledku
onResultFunkce, která dostane výsledek po schválení účastníkem
endpointVolitelně adresa pro odeslání výsledku metodou POST
cameraPresetdemo-max, demo-high, standard nebo lite
widgetfalse = bez vlastního rozhraní, souhlas pak řešíte vy
VoláníCo dělá
BeamSense.stop()Ukončí relaci a zobrazí Odeslat, Stáhnout kopii nebo Zahodit
BeamSense.now()Čas společné osy v ms od startu měření (před startem null)
BeamSense.getStatus()Stav a počty záznamů
BeamSense.on('state', fn)Změny stavu

Časová osa v milisekundách

Hostitel nemusí doplňku nic hlásit, žádné značky ani začátky a konce kapitol. Každý záznam výsledku má t (ms od startu měření) a původní absolutní timestamp. Výsledek má startedAt (ms, epoch). Události svého školení si zaznamenejte s Date.now() a jejich místo na ose spočítejte takto:

var udalosti = [];
function zaznamenej(nazev) { udalosti.push({ nazev: nazev, cas: Date.now() }); }

// po obdržení výsledku:
udalosti.forEach(function (u) {
  u.t = u.cas - result.startedAt;   // ms na společné ose
});

Četnost zápisu zůstává (metriky obličeje jednou za sekundu, body obličeje jednou za 2 sekundy). Milisekundy určují přesnost časové značky, ne hustotu vzorků.

Tvar výsledku (zkráceně)

{
  "formatVersion": "0.1",
  "sessionId": "id-relace-na-vasi-strane",
  "host": { "participantRef": "odkaz-na-ucastnika" },
  "startedAt": 1760000000000, "completedAt": 1760000060000, "duration": 60,
  "timeline": { "unit": "ms", "origin": "startedAt",
    "measurements": { "attention": { "category": "face", "everyMs": 1000,
      "values": "score: ...", "reliability": { "level": "derived", "basis": "...", "validated": false } } } },
  "quality": { "camera": { "faceFoundPercent": 89, "gapCount": 1, "longestGapMs": 6000 } },
  "faceDetected": [ { "t": 3000, "timestamp": 1760000003000, "detected": true } ],
  "headPose": [ { "t": 3000, "pitch": -3, "yaw": 2, "roll": 0 } ],
  "voiceComments": [ { "t": 14000, "text": "...", "confidence": 0.9 } ],
  "sessionLog": [ { "t": 20000, "event": "window_blur", "toIframe": true } ]
}

Definice úhlů: yaw je kladný, když se obličej otáčí doprava v obraze kamery (člověk se otáčí doleva), pitch je kladný při pohledu nahoru a roll je kladný při náklonu proti směru hodinových ručiček v obraze.

Požadavky na stránku, která doplněk vkládá

default-src 'none';
script-src 'self' https://cdn.jsdelivr.net 'wasm-unsafe-eval';
style-src 'self' 'unsafe-inline';
connect-src 'self' https://cdn.jsdelivr.net https://storage.googleapis.com;
img-src 'self' data: blob:;
media-src 'self' blob: mediastream:;
worker-src 'self' blob:;

Widget si styl vkládá sám, proto je potřeba style-src 'unsafe-inline'. Nutnost jednotlivých položek jsme zvlášť netestovali, politika je ověřená jako celek.

Přítomnost v okně. Událost window_blur má příznak toIframe: je true, když fokus přešel do vloženého iframe na stránce. Účastník pak zůstal ve školení, jen klikl do jeho obsahu, a ztrátu fokusu proto nemusíte brát jako odchod. Sleduje se jen okno, ve kterém doplněk běží. Souřadnice myši se nesbírají, jen přechody (myš opustila okno, vrátila se).

Soukromí a souhlas

Omezení ukázkové verze

Vyzkoušet

Na testovacích stránkách si doplněk vyzkoušíte v několika způsobech vložení: čisté HTML, stránka generovaná JavaScriptem, přísná CSP, školení v iframe s doplňkem nad ním nebo uvnitř. Je tam také vedený test výpočtů na skutečné kameře. Nejjednodušší ukázka je demo-host.html.