Trillboards
Back to Developer Docs
Developer Docs

Trillboards Sensing SDK Real-Time Audience Intelligence

Privacy-first on-device sensing for digital signage and retail media. Face detection, attention scoring, audio classification, BLE / WiFi co-viewing, and demographic estimates β€” running entirely on-device. No raw frames, no raw audio, no face embeddings ever leave the screen.

Overview

The Sensing SDK ships the canonical Trillboards sensing surface as a single Maven artifact for Android. It runs all face, audio, speech, BLE, WiFi, and discovery pipelines locally on the device. Outbound traffic is limited to compact heartbeat envelopes containing aggregate demographic estimates and anonymized device-presence signals β€” no raw frames, no raw audio, no images, no biometric face embeddings ever leave the device. The agent transmits the device's resettable Google Advertising ID (GAID) when available, used for cross-device frequency capping and partner attribution; the agent honors LIMIT_AD_TRACKING.

What ships in production today

  • On-device demographics β€” FaceXFormer (10-year age bins, gender estimates)
  • Audio classification β€” MediaPipe AudioClassifier (YAMNet event taxonomy)
  • Speech recognition β€” Moonshine ASR via sherpa-onnx
  • Audio diarization β€” multimodal clip prompt schema
  • BLE co-viewing β€” beacon scan, GATT 0x180A enumeration, manufacturer parsers (iBeacon, Eddystone, Continuity, FastPair, Tile)
  • WiFi environment β€” RSSI variance, channel congestion, AP density
  • Multi-protocol device discovery β€” mDNS, SSDP, ARP, HTTP probes
  • Vertex multimodal embeddings (1408-dim per observation)

Quick Start (Android)

Android is the primary platform. The full sensing surface ships as a single Maven AAR β€” one Gradle dependency line, no transitive setup.

1. Register the JitPack registry

Add the registry block to your root settings.gradle.kts so Gradle can resolve com.github.trillboards:agent-core. JitPack serves anonymously β€” no auth tokens needed.

settings.gradle.kts
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        maven { url = uri("https://jitpack.io") }
    }
}

2. Add the dependency

app/build.gradle.kts
dependencies {
    implementation("com.github.trillboards:agent-core:v1.0.4")
}

Source repo (Apache 2.0): https://github.com/trillboards/agent-core. JitPack mirrors public tags β€” pin to v1.0.4 for the current release, or main-SNAPSHOT if you want the latest commit.

3. Initialize the SDK

MyApplication.kt
import com.trillboards.sdk.TrillboardsSensingSdk

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        TrillboardsSensingSdk.start(
            context = applicationContext,
            partnerApiKey = BuildConfig.TRILLBOARDS_PARTNER_API_KEY
        )
    }
}

4. Declare manifest permissions

The agent only activates the sensors your venue actually exposes; permissions are declared as optional features so an APK without cameras or microphones still installs cleanly.

AndroidManifest.xml
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.microphone" android:required="false" />
<uses-feature android:name="android.hardware.bluetooth_le" android:required="false" />

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
    android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

Quick Start (Linux / Windows)

For non-Android partners β€” Linux digital-signage players, Windows kiosks, embedded edge boxes β€” install the Node-based @trillboards/edge-sdk. It exposes the same sensing event surface backed by ONNX runtimes and BlueZ.

Terminal
npm install @trillboards/edge-sdk
agent.ts
import { EdgeAgent } from '@trillboards/edge-sdk';

const agent = new EdgeAgent({
  platform: 'linux',
  deviceToken: 'YOUR_DEVICE_TOKEN',
  screenId: 'screen-001',
  camera: { enabled: true },
  audio: { enabled: true },
});

await agent.start();

See the Edge SDK reference for federated learning, kiosk management, and the MCP fleet-control surface.

Quick Start (Browser / CTV WebView)

Creatives running inside a partner WebView consume sensing data through the bridge contract exposed by @trillboards/ctv-measurement. No camera permissions, no on-device models β€” the host agent fans out measurement snapshots and your WebView reads them.

Terminal
npm install @trillboards/ctv-measurement
creative.ts
// Inside a WebView creative running on a Trillboards-hosted screen
const bridge = (window as any).__TRILL_BRIDGE_V1__;

if (bridge?.getMeasurementSnapshot) {
  const snapshot = await bridge.getMeasurementSnapshot();
  console.log('attention', snapshot.attention);
  console.log('audience', snapshot.audience);
  console.log('discovery', snapshot.discovery);
}

See the CTV Measurement reference for the full bridge schema, GIVT-deduped impression ingestion, and QR attribution.

Configuration

Every knob below is partner-tunable at construction time or via server-pushed sensing-config updates. Defaults are tuned for retail tablets at typical mounting distances; only override when your venue calls for it.

OptionTypeDefaultDescription
partnerApiKeyStringβ€”Partner API key issued by Trillboards. Identifies the cohort all heartbeats land in.
apiBaseUrlStringhttps://api.trillboards.comOverride for staging or self-hosted ingestion. Most partners leave this default.
socketUrlStringhttps://chat.trillboards.comRealtime command channel. Used for server-pushed sensing-config updates and device commands.
heartbeatPathString/openrtb/v1/heartbeatPOST path for the heartbeat envelope. Override only when running behind a proxy that rewrites paths.
heartbeatIntervalMsLong30000Heartbeat cadence in milliseconds. 30s is the recommended default; lower values increase server cost without measurably improving freshness.
sharedPrefsNameStringβ€”App-scoped SharedPreferences name the agent uses for fingerprint persistence. Set per-app to avoid collisions in multi-tenant builds.
overlayRefreshActionStringβ€”Local-broadcast action the agent emits when the server pushes a creative refresh. Wire your overlay activity to receive this intent.
overlayBlackoutActionStringβ€”Local-broadcast action emitted on screen-blackout commands. Lets your kiosk shell react without polling.
SensingConfig.attention.dwellMsThresholdLong1500Minimum gaze dwell before an attention event is emitted. Raise to suppress glance-only signals; lower to capture lighter engagement.
SensingConfig.detection.personConfidenceThresholdFloat0.55Lower bound for person-detection confidence before downstream demographic / attention scoring runs.
SensingConfig.audio.classificationEnabledBooleantrueMaster switch for MediaPipe AudioClassifier. Disable on devices without microphone access.
SensingConfig.viewability.darkLuxThresholdFloatcalibratedAuto-calibrated by LuxCalibrator on first run. Frames below this lux value are excluded from viewability counts.
SensingConfig.capture.maxNearbyDevicesPerListInt50Hard cap on BLE / WiFi device-list length per heartbeat. Prevents unbounded payloads in dense venues.

Privacy & Consent

The Sensing SDK is built around a privacy-first contract that satisfies the operational requirements of GDPR (EU) and CCPA / CPRA (California) for venue-side audience measurement.

  • On-device only β€” no raw frames, no raw audio, no images, no biometric face embeddings ever leave the screen. Only aggregate signals (counts, age bins, gender estimates, attention scores) are transmitted.
  • Resettable advertising ID only β€” the agent transmits the device's Google Advertising ID (GAID) when available, used for cross-device frequency capping and partner attribution. The agent honors LIMIT_AD_TRACKING.
  • Consent gating β€” the agent honors a per-screen consent flag. Sensing pipelines pause cleanly when consent is withdrawn and resume on re-grant; no data is buffered while paused.
  • PII minimization β€” facial demographic estimates emit 10-year age buckets and gender; the SDK never produces a face embedding, face image, or identifier capable of re-identifying an individual across sessions.
  • Transparent disclosure β€” partners are responsible for venue-side consent signage. The SDK exposes a status surface so your kiosk shell can render the active sensing posture to viewers on request.

Comparison

Capabilities differ across the three platform SDKs because the underlying runtimes do. The table below is honest about per-platform gaps so you can pick the right surface for your hardware.

CapabilitySensing SDK (Android)Edge SDK (Linux/Windows)CTV Measurement (Browser)
Face detectionFaceXFormer (full)BlazeFace ONNXMediaPipe Web (limited)
Audio classificationMediaPipe AudioClassifierONNX YAMNetβ€”
Speech recognitionMoonshine ASRβ€”β€”
BLE co-viewingNative (BLUETOOTH_SCAN)BlueZ (Linux only)Web Bluetooth (user-gesture-gated)
WiFi environmentNative (RSSI / channel)Nativeβ€”
Discovery (mDNS/SSDP/ARP)Full multi-protocolPartialβ€”
Vertex multimodal embeddingsYes (1408-dim)β€”β€”

Need help?

Email engineering@trillboards.com for integration support. For native IMA SDK consumers, the partner-native-ima-sdk guide's Section 12 covers the Maven coordinate, GitHub Packages registry block, and minimal init snippet from a partner-ad-serving perspective.

Ship the first sensing-enabled fleet.

One Gradle line on Android. One npm install on Linux/Windows. One bridge call in the browser. Same canonical sensing surface across all three.