The BlinkExam SDK is a JavaScript module for integrating online proctoring into web applications. It supports camera and microphone checks, face detection, screen sharing, and photo/ID capture to monitor test-takers and prevent cheating. The SDK calculates a Trust Score and generates violation reports. It offers three proctoring modes: live
, recorded
, and combo
, with recording options image
or vScreen
This documentation guides developers on integrating the SDK using CDN-loaded scripts, compatible with vanilla JavaScript or frameworks like AngularJS.
TFfaceModel
).live
and combo
modes.window.apiConfig
object with js_path
pointing to CDN-hosted utility scripts.serviceAccessKey
by registering at https://lavender-porcupine-221748.hostingersite.com/register.Integrate the BlinkExam SDK by loading its main script and utility scripts from a CDN. Scripts must be loaded sequentially to resolve dependencies.
Load the SDK and utilities on DOMContentLoaded
.
window.apiConfig = { js_path: 'https://cdn.lavender-porcupine-221748.hostingersite.com' };
document.addEventListener('DOMContentLoaded', async () => {
// Load main SDK
await loadScript('https://dqxf2of07o2qg.cloudfront.net/v2/blinkexam.min.js');
// Load utility scripts
const scriptUrls = [
`${window.apiConfig.js_path}/util/v2/variable.js`,
`${window.apiConfig.js_path}/util/v2/config.js`,
`${window.apiConfig.js_path}/util/v2/fileworker.js`,
`${window.apiConfig.js_path}/util/v2/mediaHandler.js`,
`${window.apiConfig.js_path}/util/v2/eventRecordingUtil.js`,
`${window.apiConfig.js_path}/util/v2/proctoringEvents.js`
];
await loadScriptsInOrder(scriptUrls);
// Load WebRTC and meeting scripts
await loadScriptsInOrder([
`${window.apiConfig.js_path}/util/v2/meetingv2.js`,
`${window.apiConfig.js_path}/util/v2/mzRTC.js`
]);
console.log('BlinkExam SDK initialized');
});
// Utility functions
async function loadScriptsInOrder(urls) {
for (const url of urls) {
await loadScript(url);
}
}
function loadScript(url) {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = url;
script.async = true;
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
});
}
Set window.apiConfig.js_path
to your CDN base URL (e.g.), https://cdn.lavender-porcupine-221748.hostingersite.com
. Register at https://lavender-porcupine-221748.hostingersite.com/register to obtain your serviceAccessKey
.
After loading the SDK scripts, functions are available globally under the BlinkExam
namespace (e.g.), BlinkExam.preCheckCameraAndMic
. If no namespace is used, functions are attached to window
.
BlinkExam.preCheckCameraAndMic('localVideo', 'canvas_output')
.$scope
for state management, e.g., $scope.stream = await BlinkExam.preCheckCameraAndMic(...)
.
if (typeof BlinkExam !== 'undefined') {
console.log('BlinkExam SDK loaded');
} else {
console.error('BlinkExam SDK not loaded');
}
Initialize the SDK with a configuration object passed to setConfig
. The serviceAccessKey
is mandatory for authentication.
const config = { /* ... */ };
BlinkExam.setConfig(config);
Property | Type | Required | Description |
---|---|---|---|
serviceAccessKey | String | Yes | Unique key from BlinkExam registration. |
clientId | String | Yes | Client identifier. |
testId | String | Yes | Test identifier. |
candidateId | String | Yes | Candidate identifier. |
proctorMode | String | Yes | Mode: recorded , live , or combo . |
roomInfo.roomId | String | Yes | Session ID (e.g., ${serviceAccessKey}${testId}${batchId} ). |
attemptNumber | String | Yes | Attempt number for the session. |
captureCandidate | Boolean | Yes | Enable candidate photo capture. |
captureIdentity | Boolean | Yes | Enable ID capture. |
faceAuth | Boolean | Yes | Enable face authentication. |
roomInspection | Boolean | Yes | Enable room inspection. |
inspectionType | String | Yes | Inspection mode: recorded or live . |
recordingCategory | String | Yes | Recording type: image or vScreen . |
containerId | String | Yes | ID of the HTML container for proctoring UI. |
fileNamePrefix | String | Yes | File prefix (e.g., ${testId}_${candidateId}_${attemptNumber} ). |
position | Object | Yes | UI positions (e.g., { verification: 'center', id: 'center', liveCam: 'top-right' } ). |
preUploadPath | String | Yes | Temporary file storage path. |
const config = {
serviceAccessKey: 'your-secret-key',
clientId: '1',
testId: '596',
candidateId: '323',
proctorMode: 'combo',
roomInfo: {
roomId: 'your-secret-key5962' // ${serviceAccessKey}${testId}${batchId}
},
attemptNumber: '1',
captureCandidate: true,
captureIdentity: true,
faceAuth: true,
roomInspection: true,
inspectionType: 'recorded',
recordingCategory: 'vScreen',
containerId: 'proctoringContainer',
fileNamePrefix: '596_323_1',
position: {
verification: 'center',
id: 'center',
liveCam: 'top-right'
},
preUploadPath: 'testResources'
};
BlinkExam.setConfig(config);
BlinkExam.preCheckCameraAndMic(localVideoId, canvasId)
Checks camera and microphone availability.
localVideoId
(String): ID of the <video>
element.canvasId
(String): ID of the <canvas>
element.Promise<MediaStream>
or throws an error.
async function initCamera() {
try {
const stream = await BlinkExam.preCheckCameraAndMic('localVideo', 'canvas_output');
console.log('Camera and mic ready:', stream);
} catch (error) {
console.error('Camera/mic error:', error);
}
}
BlinkExam.checkMicLevel(stream, colorPids)
Monitors microphone input and updates visual indicators.
stream
(MediaStream): Audio stream.colorPids
(Array/Object): Indicator configuration.
BlinkExam.checkMicLevel(stream, { low: 'green', high: 'red' });
BlinkExam.calculateFaceCount(video, canvas, callback)
Detects faces using TensorFlow.js.
video
(HTMLVideoElement): Video feed.canvas
(HTMLCanvasElement): Canvas for output.callback
(Function): Handles face count.
async function initFaceDetection() {
if (typeof TFfaceModel === 'undefined') {
console.error('TensorFlow.js not loaded');
return;
}
const video = document.getElementById('localVideo');
const canvas = document.getElementById('canvas_output');
BlinkExam.calculateFaceCount(video, canvas, count => console.log(`Faces: ${count}`));
}
BlinkExam.stopFaceDetection()
Stops face detection.
BlinkExam.stopFaceDetection();
BlinkExam.multipleScreensAttached()
Checks for multiple screens.
Promise<Boolean>
.
async function checkScreens() {
const hasMultipleScreens = await BlinkExam.multipleScreensAttached();
console.log(hasMultipleScreens ? 'Multiple screens detected' : 'Single screen');
}
BlinkExam.capturePhotoAndIdCanva(videoId, canvasId)
Captures a snapshot for photo/ID verification.
videoId
(String): Video element ID.canvasId
(String): Canvas element ID.
async function captureSnapshot() {
await BlinkExam.capturePhotoAndIdCanva('blink-live-feed', 'blink-live-canva');
console.log('Snapshot captured');
}
BlinkExam.captureAndSubmitPhoto(id, errorHandler, submissionCallback, config)
Captures and submits a photo or ID.
id
(String): photo
or id
.errorHandler
(Function): Error callback.submissionCallback
(Function): Success callback.config
(Object): Configuration object.
BlinkExam.captureAndSubmitPhoto(
'photo',
error => console.error('Photo error:', error),
() => console.log('Photo submitted'),
config
);
BlinkExam.recordedImg()
Recorded proctoring with image capture.
if (config.recordingCategory === 'image') {
BlinkExam.recordedImg();
}
BlinkExam.recordedVScreen()
Recorded proctoring with video.
if (config.recordingCategory === 'vScreen') {
BlinkExam.recordedVScreen();
}
BlinkExam.liveVScreen()
Live proctoring with screen sharing.
if (config.proctorMode === 'live' && config.recordingCategory === 'vScreen') {
BlinkExam.liveVScreen();
}
lavender-porcupine-221748.hostingersite.comboVScreen()
Combined live and recorded proctoring.
if (config.proctorMode === 'combo' && config.recordingCategory === 'vScreen') {
lavender-porcupine-221748.hostingersite.comboVScreen();
}
window.apiConfig = { js_path: 'https://cdn.lavender-porcupine-221748.hostingersite.com' };
document.addEventListener('DOMContentLoaded', async () => {
await loadScript('https://dqxf2of07o2qg.cloudfront.net/v2/blinkexam.min.js');
await loadScriptsInOrder([
`${window.apiConfig.js_path}/util/v2/variable.js`,
`${window.apiConfig.js_path}/util/v2/config.js`,
`${window.apiConfig.js_path}/util/v2/fileworker.js`,
`${window.apiConfig.js_path}/util/v2/mediaHandler.js`,
`${window.apiConfig.js_path}/util/v2/eventRecordingUtil.js`,
`${window.apiConfig.js_path}/util/v2/proctoringEvents.js`,
`${window.apiConfig.js_path}/util/v2/meetingv2.js`,
`${window.apiConfig.js_path}/util/v2/mzRTC.js`
]);
BlinkExam.setConfig(config);
if (config.recordingCategory === 'image' && window.proctorPluginVersion === 'v2') {
BlinkExam.recordedImg();
}
});
async function capturePhoto() {
try {
await BlinkExam.captureAndSubmitPhoto(
'photo',
error => { throw new Error(`Photo capture failed: ${error}`); },
() => console.log('Photo submitted'),
config
);
} catch (error) {
console.error(error);
}
}
async function startProctoring() {
try {
const stream = await BlinkExam.preCheckCameraAndMic('localVideo', 'canvas_output');
if (typeof TFfaceModel !== 'undefined') {
BlinkExam.calculateFaceCount(
document.getElementById('localVideo'),
document.getElementById('canvas_output'),
count => console.log(`Detected ${count} faces`)
);
}
} catch (error) {
console.error('Proctoring setup failed:', error);
}
}
angular.module('proctorApp', []).controller('ProctorCtrl', function($scope) {
const config = { /* ... */ };
BlinkExam.setConfig(config);
$scope.proctorMode = config.proctorMode;
async function init() {
try {
$scope.stream = await BlinkExam.preCheckCameraAndMic('localVideo', 'canvas_output');
} catch (error) {
console.error('Camera error:', error);
}
}
init();
});
TFfaceModel
).mzRTC.js
for live proctoring.variable.js
: Core utilities.config.js
: Configuration handling.fileworker.js
: File utilities.mediaHandler.js
: Camera/microphone handling.eventRecordingUtil.js
: Event logging.proctoringEvents.js
: Proctoring events.meetingv2.js
: Live session management.mzRTC.js
: WebRTC communication.Use try-catch blocks and error callbacks to handle issues like permission denials or script failures.
Example:
async function captureAndSubmit() {
try {
await BlinkExam.captureAndSubmitPhoto(
'id',
error => { throw new Error(`ID capture failed: ${error}`); },
() => console.log('ID submitted'),
config
);
} catch (error) {
console.error(error);
alert('Failed to capture ID. Please try again.');
}
}
Issue | Cause | Solution |
---|---|---|
preCheckCameraAndMic fails | Missing permissions | Prompt user to allow camera/mic; ensure HTTPS. |
TFfaceModel undefined | TensorFlow.js not loaded | Load <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"> . |
Script loading fails | Incorrect js_path | Verify window.apiConfig.js_path . |
WebRTC errors | Browser incompatibility | Use Chrome/Firefox; ensure HTTPS. |
Photo submission fails | Invalid endpoint | Check config.preUploadPath and server logs. |
The SDK supports version v2
(window.proctorPluginVersion
).
if (window.proctorPluginVersion === 'v2') {
BlinkExam.recordedImg();
} else {
console.warn('Unsupported SDK version');
}
For more information about API integration and pricing, contact us:
📞 Sales Enquiry: +91 95828 74969
📧 Support: support@lavender-porcupine-221748.hostingersite.com
To get started, request a demo.