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

proctor-sdk

v1.0.3

Published

A light-weight proctoring library for some of the commonly used proctoring events

Downloads

25

Readme

ProctorSDK: Web-Based Proctoring & Monitoring SDK

ProctorSDK is a client-side JavaScript library designed to provide essential proctoring and user monitoring functionalities for web applications. It helps ensure exam integrity or user presence by leveraging browser APIs and TensorFlow.js for face detection.

Features

  • Face Detection:
    • Detects if zero, one, or multiple faces are present in the webcam feed.
    • Draws bounding boxes around detected faces.
  • Environment Monitoring:
    • Fullscreen Exit Detection: Warns if the user exits fullscreen mode.
    • Tab Switch / Window Minimize Detection: Warns if the page visibility changes (user switches tabs or minimizes the window).
    • Copy/Paste/Cut Attempt Detection: Warns if the user attempts clipboard actions on the page.
    • Multiple Screen Detection: Warns if the user has an extended display setup (using window.screen.isExtended where available).
  • Configurable:
    • Enable or disable specific checks.
    • Customize CDN paths for TensorFlow.js and BlazeFace models.
    • Set custom throttle durations for violation event reporting.
  • Event-Driven:
    • Provides callbacks for status changes (e.g., "initializing", "started", "error") and proctoring violations.
  • Easy Integration:
    • Designed to be integrated into existing web applications, including those built with frameworks like React, Vue, or Angular.
    • Requires a designated DOM container element where it will inject the webcam feed and canvas overlay.
  • Modular Design:
    • Internally structured for better maintainability and separation of concerns.
  • TypeScript Support:
    • Includes type definitions for a better development experience in TypeScript projects.

Table of Contents

Installation

Install ProctorSDK using npm (or yarn):

npm install proctor-sdk
# or
yarn add proctor-sdk

Then, import it into your project:

import ProctorSDK, { STATUS_TYPES, WARNING_TYPES } from "proctor-sdk";

Quick Start

Here's a minimal example of how to use ProctorSDK in plain JavaScript after installing it via npm:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>ProctorSDK Quick Start</title>
    <style>
      #proctorView {
        width: 320px;
        height: 240px;
        border: 1px solid black;
        position: relative;
        background-color: #eee;
      }
    </style>
  </head>
  <body>
    <h1>ProctorSDK Demo</h1>
    <div id="proctorView">
      <!-- SDK will inject video feed here -->
    </div>
    <button id="startBtn">Start Proctoring</button>
    <button id="stopBtn">Stop Proctoring</button>
    <div id="statusLog">Status: Idle</div>
    <div id="violationsLog"></div>

    <script type="module">
      import ProctorSDK from "proctor-sdk"; 

      const proctorContainer = document.getElementById("proctorView");
      const startBtn = document.getElementById("startBtn");
      const stopBtn = document.getElementById("stopBtn");
      const statusLog = document.getElementById("statusLog");
      const violationsLog = document.getElementById("violationsLog");

      const sdkConfig = {
        containerElement: proctorContainer,
        callbacks: {
          onStatusChange: (statusData) => {
            console.log("SDK Status:", statusData);
            statusLog.textContent = `Status: ${statusData.status} - ${
              statusData.message || ""
            }`;
            if (statusData.error) {
              statusLog.innerHTML += `<br><span style="color: red;">Error: ${statusData.error.message}</span>`;
            }
          },
          onViolation: (violation) => {
            console.warn("SDK Violation:", violation);
            let vMsg = `${violation.active ? "ALERT 🔴" : "CLEARED ✅"} - ${
              violation.type
            }: ${violation.message}`;

            let p = document.getElementById(`v-${violation.type}`);
            if (!p) {
              p = document.createElement("p");
              p.id = `v-${violation.type}`;
              violationsLog.appendChild(p);
            }
            p.textContent = vMsg;
            p.style.color = violation.active ? "red" : "green";
          },
        },
      };

      let proctorInstance;
      try {
        proctorInstance = new ProctorSDK(sdkConfig);
      } catch (e) {
        console.error("Fatal SDK Init Error:", e);
        statusLog.textContent =
          "SDK Init Error: " + (e instanceof Error ? e.message : String(e));
      }

      startBtn.addEventListener("click", () => {
        if (proctorInstance) proctorInstance.start();
      });

      stopBtn.addEventListener("click", () => {
        if (proctorInstance) proctorInstance.stop();
      });

      window.addEventListener("beforeunload", () => {
        if (proctorInstance) proctorInstance.destroy();
      });
    </script>
  </body>
</html>

Configuration

The ProctorSDK is initialized with a configuration object.

Core Options

  • containerElement (Required): HTMLElement | string
    • The DOM element (or its ID string) where the SDK will inject the webcam video feed and canvas overlay. The SDK will clear the contents of this element.
    • Important: For proper canvas overlay, this container element should have its CSS position set to relative, absolute, or fixed. If it's static (the default for most elements), the canvas overlay might not align correctly. The SDK will log a warning if it detects a static position.

Callbacks

  • callbacks (Optional): object
    • An object containing callback functions for SDK events.
    • onStatusChange: (statusData: StatusData) => void
      • Called when the SDK's operational status changes (e.g., loading models, starting, error).
      • See StatusData Object.
    • onViolation: (violationData: ViolationData) => void
      • Called when a proctoring rule is triggered (violation becomes active) or cleared (violation becomes inactive).
      • See ViolationData Object.
    • onWebcamStreamReady: (stream: MediaStream) => void
      • Called when webcam access is granted and the MediaStream is available.
    • onFacePredictions: (predictions: Array<object>) => void
      • (Advanced) Called on each frame with the raw face detection prediction results from BlazeFace. This can be verbose. (The object type should ideally be a more specific BlazeFace prediction type if available).

Enabled Checks

  • enabledChecks (Optional): object
    • An object with boolean flags to enable or disable specific proctoring checks. Defaults to all true.
    • faceDetection: boolean (Checks for no face, one face, multiple faces)
    • fullscreen: boolean (Checks for fullscreen exit)
    • tabSwitch: boolean (Checks for page visibility changes)
    • copyPaste: boolean (Checks for copy, paste, cut events)
    • multipleScreens: boolean (Checks for extended display usage)

Model Paths

  • tfjsModelPaths (Optional): object
    • Allows overriding the default CDN URLs for TensorFlow.js and the BlazeFace model.
    • tfjs: string (URL for TensorFlow.js core library)
    • blazeface: string (URL for the BlazeFace model script)

Throttle Durations

  • violationThrottleDurations (Optional): object
    • An object to customize the minimum time (in milliseconds) between consecutive onViolation callbacks for active violations of the same type. This prevents flooding the host application with events for continuous issues. Clearing a violation is not throttled.
    • Keys should be values from ProctorSDK.WARNING_TYPES (e.g., [ProctorSDK.WARNING_TYPES.NO_FACE]: 5000).
    • Defaults:
      • NO_FACE: 3000ms
      • MULTIPLE_FACES: 3000ms
      • FULLSCREEN_EXIT: 1000ms
      • TAB_SWITCH: 1000ms
      • COPY_PASTE_ATTEMPT: 1000ms
      • MULTIPLE_SCREENS: 10000ms

API Reference

ProctorSDK Class

The main class you interact with.

import ProctorSDK from "proctor-sdk";
const instance = new ProctorSDK(config);

Public Methods

  • async start(): Promise<void>
    • Initiates the proctoring session.
  • stop(): void
    • Stops the currently active proctoring session.
  • isProctoringActive(): boolean
    • Returns true if proctoring is currently running.
  • requestFullscreen(): Promise<void>
    • Attempts to make the SDK's container element (or the document) enter fullscreen mode.
  • destroy(): void
    • Completely cleans up the SDK instance.

Static Properties

Accessible directly on the imported ProctorSDK class (e.g., ProctorSDK.STATUS_TYPES).

  • ProctorSDK.STATUS_TYPES: object
    • An enum-like object for status strings (see StatusData.status).
  • ProctorSDK.WARNING_TYPES: object
    • An enum-like object for violation type strings (see ViolationData.type).

Data Structures

Type definitions are provided for TypeScript users.

StatusData Object

Passed to the onStatusChange callback.

interface StatusData {
  status: string; // A value from ProctorSDK.STATUS_TYPES
  message: string;
  error?: Error; // Present if status is ERROR
}

ViolationData Object

Passed to the onViolation callback.

interface ViolationData {
  type: string; 
  active: boolean; 
  message: string; 
  timestamp: Date; 
  details?: {
    count?: number; 
    eventType?: "copy" | "paste" | "cut";
  };
}

Usage with React (Example)

// SimpleProctor.jsx / SimpleProctor.tsx
import React, { useEffect, useRef, useCallback } from "react";
import ProctorSDK, { STATUS_TYPES, WARNING_TYPES } from "proctor-sdk";

const SimpleProctor = () => {
  const proctorContainerRef = useRef(null);
  const proctorSDKInstanceRef = useRef(null);

  const handleStatusChange = useCallback((statusData) => {
    console.log(
      "[ProctorSDK Status]",
      statusData.status,
      "-",
      statusData.message
    );
    if (statusData.error) console.error("[ProctorSDK Error]", statusData.error);
  }, []);

  const handleViolation = useCallback((violation) => {
    if (violation.active) {
      console.warn(
        `[ProctorSDK Violation ACTIVE] ${violation.type}: ${violation.message}`,
        violation.details || ""
      );
    } else {
      console.info(
        `[ProctorSDK Violation CLEARED] ${violation.type}: ${violation.message}`
      );
    }
  }, []);

  useEffect(() => {
    if (proctorContainerRef.current && !proctorSDKInstanceRef.current) {
      const sdkConfig = {
        containerElement: proctorContainerRef.current,
        callbacks: {
          onStatusChange: handleStatusChange,
          onViolation: handleViolation,
        },

      };
      try {
        proctorSDKInstanceRef.current = new ProctorSDK(sdkConfig);
      } catch (e) {
        console.error("[ProctorSDK] Initialization failed:", e);
      }
    }
    return () => {
      if (proctorSDKInstanceRef.current) {
        proctorSDKInstanceRef.current.destroy();
        proctorSDKInstanceRef.current = null;
      }
    };
  }, [handleStatusChange, handleViolation]);

  const start = () => proctorSDKInstanceRef.current?.start();
  const stop = () => proctorSDKInstanceRef.current?.stop();

  return (
    <div>
      <h3>Simple Proctoring View (React)</h3>
      <div
        ref={proctorContainerRef}
        style={{
          width: "320px",
          height: "240px",
          border: "1px solid black",
          position: "relative",
          backgroundColor: "#f0f0f0",
        }}
      >
        {/* SDK injects video here. Add placeholder if desired. */}
      </div>
      <button onClick={start}>Start Proctoring</button>
      <button onClick={stop}>Stop Proctoring</button>
      <p>Check console for logs.</p>
    </div>
  );
};
export default SimpleProctor;

How it Works (Brief Overview)

  1. Initialization: The SDK sets up a designated container element, creating internal <video> and <canvas> elements.
  2. Start:
    • Models: TensorFlow.js and BlazeFace are loaded dynamically from CDNs (or custom paths).
    • Webcam: navigator.mediaDevices.getUserMedia requests camera access. The stream is piped into the <video> element.
    • Detection:
      • Face Detection: A requestAnimationFrame loop feeds video frames to BlazeFace. Violations are triggered, and boxes are drawn on the <canvas>.
      • Environment Monitoring: Event listeners detect fullscreen changes, tab switches, clipboard actions, and multi-screen setups.
  3. Communication: Callbacks inform the host application of violations and status updates.
  4. Stop/Destroy: Resources are released, and listeners are removed.

Browser Compatibility

  • Modern Browsers: Requires support for WebRTC (getUserMedia), ES6+ (Promises, async/await), Canvas API, Fullscreen API, Page Visibility API, Clipboard Events API.
  • Multiple Screen Detection: Relies on window.screen.isExtended (Window Management API), which is newer and support may vary.
  • TensorFlow.js/WebGL: Performance depends on WebGL and device capabilities.
  • Permissions: Camera permission is essential.

Contributing

Contributions are welcome! Please open an issue or pull request on the project repository.

Github Repository

License

This project is licensed under the MIT License - see the LICENSE.md file for details.