npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sentriqx/web-sdk

v1.0.12

Published

Sentriqx Web SDK — Screen recording, face recognition, live location tracking, and transaction recording for web applications and games (Unity WebGL, Phaser.js, React)

Readme

@sentriqx/web-sdk

npm version license types

Web SDK for game platforms — Screen Recording, Live Streaming (RTMP), Live Location, Transaction Recording, and Face Recognition.

Built for web games using Unity WebGL, Phaser.js, or any React-based app.

This is the web equivalent of the Sentriqx Kotlin/Android SDK, ported to TypeScript using browser-native APIs.


Installation

npm install @sentriqx/web-sdk

Or with yarn / pnpm:

yarn add @sentriqx/web-sdk
pnpm add @sentriqx/web-sdk

Quick Start

import { SentriqxSDK } from '@sentriqx/web-sdk';

// 1. Initialize
const sdk = new SentriqxSDK({
  appId: 'NX-992',
  apiSecretKey: 'sxk_live_xxxxx',
  mediaServerUrl: 'https://your-media-server.com', // optional, for streaming
  debug: true,
});

// 2. Fetch config from backend
await sdk.fetchConfig();

// 3. Register this device/browser
await sdk.registerDevice();

// 4. Check browser support
const support = SentriqxSDK.checkSupport();
console.log(support);
// { screenRecording: true, faceRecognition: true, geolocation: true, deviceMotion: true }

Feature 1: Screen Recording & Live Streaming

Uses the browser's getDisplayMedia() + MediaRecorder APIs (replaces Android MediaProjection + RootEncoder).

Option A — Full Pipeline (Recommended)

For streaming to your media server with automatic backend integration and chunked upload:

// Must be called from a user gesture (button click)
document.getElementById('record-btn').onclick = async () => {

  // Step 1: Request screen capture permission
  await sdk.startScreenCapture({
    width: 1280,
    height: 720,
    fps: 30,
    enableAudio: true,
  });

  // Step 2: Start the complete streaming pipeline
  // This handles: backend stream creation + media server FFmpeg + chunked upload
  const { streamKey, sessionId, backendResult } = await sdk.startScreenStreaming({
    streamTitle: 'My Recording',
    streamerName: 'Player One',
    config: { videoBitrate: 2500000 },
  });

  console.log('Stream key:', streamKey);

  // Step 3: Listen for chunk events
  sdk.on('streaming:chunk', ({ index, size }) => {
    console.log(`Chunk #${index} sent (${size} bytes)`);
  });

  sdk.on('streaming:chunk-error', ({ index, error }) => {
    console.error(`Chunk #${index} failed:`, error);
  });

  // Step 4: Stop when done — handles all cleanup
  await sdk.stopScreenStreaming();
};

Option B — Local Recording Only

For recording without a media server (download-only):

// Step 1: Request screen capture
await sdk.startScreenCapture({ enableAudio: true });

// Step 2: Start local recording
const sessionId = sdk.startStreaming('game-123');

// Step 3: Stop and get the blob
const result = await sdk.stopStreaming();

// Download the recording
if (result.recordedUrl) {
  const a = document.createElement('a');
  a.href = result.recordedUrl;
  a.download = `recording-${result.sessionId}.webm`;
  a.click();
}

// Or upload the blob to your backend
if (result.recordedBlob) {
  const formData = new FormData();
  formData.append('video', result.recordedBlob, 'recording.webm');
  await fetch('/api/upload', { method: 'POST', body: formData });
}

Pause / Resume

sdk.pauseStreaming();
sdk.resumeStreaming();

// Check state
if (sdk.streaming.isSessionPaused()) {
  sdk.resumeStreaming();
}

Feature 2: Live Location

Uses the browser's Geolocation API (replaces Android FusedLocationProvider).

// One-shot location
const loc = await sdk.getCurrentLocation();
console.log(loc.latitude, loc.longitude);

// Continuous tracking
sdk.on('location:updated', (data) => {
  console.log('New position:', data.latitude, data.longitude);
});

sdk.startLocationTracking();

// Stop later
sdk.stopLocationTracking();

// Get location history
const history = sdk.getLocationHistory();

Feature 3: Transaction Recording

Validates and sends crypto transaction data to your backend.

// Validate locally (no API call)
const validation = sdk.validateTransaction({
  transaction_hash: '0xabc123...',
  receiver_wallet: '0xdef...',
  sender_wallet: '0x456...',
  amount: '100.5',
  chain: 'ethereum',
});

if (validation.validated) {
  // Record on backend
  const result = await sdk.recordTransaction({
    transaction_hash: '0xabc123...',
    receiver_wallet: '0xdef...',
    sender_wallet: '0x456...',
    amount: '100.5',
    chain: 'ethereum',
    token_symbol: 'usdt',
  });
  console.log('Recorded:', result.success);
}

// Fetch history
const txHistory = await sdk.getTransactions();

Feature 4: Face Recognition

Uses the browser's getUserMedia() for webcam access + Canvas for image capture (replaces Android Camera2 API). Includes a built-in capture UI with overlay guide.

Capture Only

const result = await sdk.captureFace({
  useFrontCamera: true,
  maxImageWidth: 480,
  jpegQuality: 0.8,
  guideText: 'Position your face in the frame',
});

if (result.success) {
  console.log('Image blob:', result.imageBlob);
  console.log('Data URL:', result.imageDataUrl);

  // Upload separately
  await sdk.uploadFace(result.imageBlob, 'username123');
}

Capture + Auto Upload

const result = await sdk.captureFaceAndUpload({
  useFrontCamera: true,
  maxImageWidth: 480,
  jpegQuality: 0.8,
});

if (result.success) {
  console.log(result.message); // "Face registered successfully!"
}

Events

Listen for SDK events:

// Streaming events
sdk.on('session:started', (data) => console.log('Started:', data.sessionId));
sdk.on('session:stopped', (data) => console.log('Stopped:', data.durationMs));
sdk.on('session:paused', () => console.log('Paused'));
sdk.on('session:resumed', () => console.log('Resumed'));
sdk.on('streaming:started', (data) => console.log('Streaming:', data));
sdk.on('streaming:stopped', () => console.log('Stream stopped'));
sdk.on('streaming:error', (data) => console.log('Error:', data.reason));
sdk.on('streaming:chunk', (data) => console.log('Chunk sent:', data.index));
sdk.on('streaming:chunk-error', (data) => console.log('Chunk error:', data));

// Location events
sdk.on('location:updated', (data) => console.log('Location:', data));
sdk.on('location:error', (data) => console.log('Location error:', data));

// Face events
sdk.on('face:captured', () => console.log('Face captured'));
sdk.on('face:uploaded', (data) => console.log('Face uploaded:', data));
sdk.on('face:error', (data) => console.log('Face error:', data));

// Transaction events
sdk.on('transaction:recorded', (data) => console.log('TX recorded'));
sdk.on('transaction:error', (data) => console.log('TX error:', data));

// Device/config events
sdk.on('device:registered', (data) => console.log('Registered:', data));
sdk.on('config:loaded', (data) => console.log('Config:', data));

React Integration Example

import { useEffect, useRef, useState } from 'react';
import { SentriqxSDK } from '@sentriqx/web-sdk';

function GamePage() {
  const sdkRef = useRef<SentriqxSDK | null>(null);
  const [isRecording, setIsRecording] = useState(false);
  const [streamKey, setStreamKey] = useState<string | null>(null);

  useEffect(() => {
    const sdk = new SentriqxSDK({
      appId: 'NX-992',
      apiSecretKey: 'sxk_live_xxxxx',
      mediaServerUrl: 'https://your-media-server.com',
      debug: true,
    });
    sdkRef.current = sdk;

    sdk.fetchConfig().then(() => sdk.registerDevice());

    return () => sdk.destroy();
  }, []);

  const startRecording = async () => {
    const sdk = sdkRef.current!;
    await sdk.startScreenCapture({ enableAudio: true });
    const { streamKey } = await sdk.startScreenStreaming({
      streamTitle: 'Game Session',
    });
    setStreamKey(streamKey);
    sdk.startLocationTracking();
    setIsRecording(true);
  };

  const stopRecording = async () => {
    const sdk = sdkRef.current!;
    await sdk.stopScreenStreaming();
    sdk.stopLocationTracking();
    setIsRecording(false);
  };

  return (
    <div>
      {/* Your game canvas (Unity WebGL / Phaser.js) */}
      <canvas id="game-canvas" />

      <button onClick={isRecording ? stopRecording : startRecording}>
        {isRecording ? 'Stop Recording' : 'Start Recording'}
      </button>

      {streamKey && <p>Stream Key: {streamKey}</p>}
    </div>
  );
}

Unity WebGL Integration

<script type="module">
  import { SentriqxSDK } from 'https://unpkg.com/@sentriqx/web-sdk/dist/index.mjs';

  const sdk = new SentriqxSDK({
    appId: 'NX-992',
    apiSecretKey: 'sxk_live_xxxxx',
    mediaServerUrl: 'https://your-media-server.com',
  });

  await sdk.fetchConfig();
  await sdk.registerDevice();

  // Expose to Unity via window
  window.SentriqxSDK = sdk;

  // Unity C# can call these via Application.ExternalCall or jslib
  window.startRecording = async () => {
    await sdk.startScreenCapture();
    const { streamKey } = await sdk.startScreenStreaming({
      streamTitle: 'Unity Game',
    });
    return streamKey;
  };

  window.stopRecording = async () => {
    const result = await sdk.stopScreenStreaming();
    return JSON.stringify(result);
  };
</script>

Phaser.js Integration

import { SentriqxSDK } from '@sentriqx/web-sdk';

const sdk = new SentriqxSDK({
  appId: 'NX-992',
  apiSecretKey: 'sxk_live_xxxxx',
});

class GameScene extends Phaser.Scene {
  create() {
    // Start tracking when game scene loads
    sdk.startLocationTracking();

    sdk.on('location:updated', (loc) => {
      // Use location data in your game
      this.updatePlayerRegion(loc.latitude, loc.longitude);
    });
  }
}

API Reference

new SentriqxSDK(config)

| Property | Type | Required | Description | |---|---|---|---| | appId | string | Yes | Your app identifier | | apiSecretKey | string | Yes | API secret key | | baseUrl | string | No | Backend URL (default: built-in) | | mediaServerUrl | string | No | Media server URL for streaming | | organizationId | string | No | Organization ID (auto-set by fetchConfig) | | productId | string | No | Product ID (auto-set by fetchConfig) | | debug | boolean | No | Enable debug logs |

Static Methods

| Method | Returns | Description | |---|---|---| | SentriqxSDK.checkSupport() | object | Check browser feature support |

Instance Methods

| Method | Returns | Description | |---|---|---| | fetchConfig() | Promise<ApiResponse> | Fetch backend config | | registerDevice() | Promise<ApiResponse> | Register device | | isServiceActive(name) | boolean | Check if a service is active | | startScreenCapture(config?) | Promise<MediaStream> | Request screen capture permission | | startScreenStreaming(options?) | Promise<{streamKey, sessionId, backendResult}> | Full streaming pipeline | | stopScreenStreaming() | Promise<SessionResult> | Stop full pipeline | | startStreaming(gameId, config?) | string | Low-level: start MediaRecorder only | | stopStreaming() | Promise<SessionResult> | Low-level: stop MediaRecorder only | | pauseStreaming() | void | Pause recording | | resumeStreaming() | void | Resume recording | | captureFace(config?) | Promise<FaceCaptureResult> | Capture face image | | captureFaceAndUpload(config?) | Promise<FaceCaptureResult> | Capture + upload | | uploadFace(blob, username) | Promise<ApiResponse> | Upload face image | | recordTransaction(fields) | Promise<ApiResponse> | Record transaction | | validateTransaction(fields) | TransactionValidation | Validate locally | | getTransactions() | Promise<ApiResponse> | Get transaction history | | getCurrentLocation() | Promise<LocationData> | Get current location | | startLocationTracking() | void | Start live location | | stopLocationTracking() | void | Stop live location | | getLocationHistory() | LocationData[] | Get location history | | sendSensorData(data) | Promise<ApiResponse> | Send gyro/accel data | | getDeviceId() | string | Get persistent device ID | | getDeviceInfo() | Promise<DeviceInfo> | Get full device info | | on(event, listener) | () => void | Subscribe to events | | off(event, listener) | void | Unsubscribe from events | | destroy() | void | Clean up all resources |


TypeScript

Full type definitions are included. Import types directly:

import type {
  SentriqxConfig,
  ApiResponse,
  StreamConfig,
  SessionResult,
  FaceRecognitionConfig,
  FaceCaptureResult,
  TransactionFields,
  TransactionValidation,
  LocationData,
  DeviceInfo,
  SdkEventType,
  SdkEventListener,
} from '@sentriqx/web-sdk';

Kotlin → Web API Mapping

For developers familiar with the Sentriqx Android SDK:

| Kotlin (Android) | Web (Browser) | |---|---| | MediaProjection + ScreenSource | navigator.mediaDevices.getDisplayMedia() | | RootEncoder / GenericStream | MediaRecorder API | | Camera2 API | navigator.mediaDevices.getUserMedia() | | FusedLocationProvider | navigator.geolocation | | SharedPreferences | localStorage | | HttpURLConnection | fetch() API | | SensorManager (Gyroscope) | DeviceMotionEvent / DeviceOrientationEvent | | LocalBroadcastManager | EventEmitter (custom pub/sub) | | Build.MODEL / Build.MANUFACTURER | navigator.userAgent parsing |


Browser Support

| Feature | Chrome | Firefox | Safari | Edge | |---|---|---|---|---| | Screen Recording | 72+ | 66+ | 13+ | 79+ | | Face Recognition (Camera) | 53+ | 36+ | 11+ | 79+ | | Geolocation | 5+ | 3.5+ | 5+ | 12+ | | DeviceMotion | 31+ | 6+ | 4.2+ | 12+ |

Note: Screen recording requires a secure context (HTTPS or localhost).


Troubleshooting

NotAllowedError on startScreenCapture()

Screen capture must be initiated from a user gesture (click, tap). Don't call it on page load or from a timeout.

NotSupportedError on Safari

Safari requires iOS 15+ and macOS 12+ for screen capture. Face recognition works on all supported versions.

Recording blob is empty

Ensure you call stopStreaming() (or stopScreenStreaming()) and wait for it to resolve. The blob is only available after the MediaRecorder has flushed.


License

MIT © Sentriqx