Skip to content

gwp developer guide

Andre Lafleur edited this page Feb 1, 2026 · 3 revisions

The Genetec Web Player (GWP) is a JavaScript/TypeScript library designed to embed live and playback video streams from Genetec Security Center™ into custom web applications. It offers advanced video streaming capabilities using WebSockets and Media Source Extensions, providing an easy-to-use API while abstracting the complexities of managing streams, codecs, and security.

This guide provides detailed instructions for integrating the GWP into your application, including setup, authentication, and usage examples for advanced features like PTZ control, timeline management, and diagnostics.

Additional Documentation:

  • GWP API Reference - Complete technical API reference with all interfaces, methods, properties, events, and enumerations
  • Sample Application - Comprehensive working example demonstrating all GWP features, perfect for testing and debugging

2. Architecture

  • Client:

    • GWP runs in the browser, using WebSockets and Media Source Extensions for streaming.
    • All video/audio decoding is handled by the browser, leveraging hardware acceleration when available.
  • Server:

    • The Media Gateway role in Security Center streams video/audio and handles transcoding if needed.
    • The web server hosting your application must be able to reach the Media Gateway.
  • Authentication:

    • Uses Security Center users for secure token retrieval.
    • All user privileges are enforced by the Media Gateway.
  • Data Flow:

    1. Browser (GWP) establishes a secure WebSocket (WSS) to the Media Gateway.
    2. Token retrieval is handled via a callback function.
    3. Video/audio streams are delivered directly to the browser.

Features

  • Live and Playback Video Streaming: Access real-time and recorded video feeds.
  • Audio Support: Stream AAC audio where supported.
  • PTZ Camera Control: Low-latency Pan-Tilt-Zoom control.
  • Dynamic Stream Selection: Adaptive resolution and bitrate adjustment based on player size.
  • Digital Zoom: Enhance video regions for detailed views.
  • Fisheye Dewarping: Correct fisheye distortions for a traditional PTZ-like experience.
  • Timeline API: Access bookmarks and motion detection events.
  • Diagnostics: Tools for debugging and monitoring.

Prerequisites

  1. Media Gateway Role:

    • The Media Gateway Role must be configured in Security Center. See the Media Gateway Developer Guide for setup instructions.
    • Open ports 80 and 443 for public access.
    • Ensure the Media Gateway and GWP library versions are compatible.
  2. Authentication:

    • Security Center user credentials.
  3. Environment Requirements:

    • Supported Browsers: Chrome, Firefox, Edge, Safari, Internet Explorer 11.
  4. Camera GUIDs: Unique identifiers for the cameras you wish to stream.


Security Center Privileges

To use the Genetec Web Player, users must have the appropriate Security Center privileges configured.

Important

A local user account with the necessary privileges listed below will work. The user must also have access rights to the partition where the camera is located.

Required Privileges

These privileges are required for all GWP applications:

Application Privileges

  • Log on using the SDK: Allows the user to run SDK applications and authenticate with the Media Gateway.

Administrative Privileges - Physical Entities

  • View camera properties: Allows the user to view camera configurations.

Web App Privileges

  • Live hit monitoring: Allows the user to open the Live hit monitoring task in the Web App.

Optional Privileges (Feature-Specific)

These privileges are only required if your application uses the corresponding features:

Action Privileges - Cameras

  • View live video: Required to view live video streams from cameras (when using playLive()).
  • View playback: Required to view recorded/playback video from cameras (when using seek() or playback features).

PTZ Motor Privileges (under View live video)

For PTZ camera control functionality, the following table maps GWP PTZ methods to their required Security Center privileges:

GWP PTZ Method(s) Required Privilege Description
startPanTilt(), stopPanTilt(), startZoom(), stopZoom(), stop(), goHome() Perform basic operations Allows basic PTZ operations (pan, tilt, zoom, and stop movements)
goToPreset(preset) Use presets Allows the user to move the camera to preset positions
runPattern(pattern) Use patterns Allows the user to run camera movement patterns
lock(), unlock() Lock PTZ Allows the user to lock and unlock PTZ controls
startFocus(), stopFocus(), startIris(), stopIris() Change focus and iris settings Allows the user to adjust camera focus and iris settings

Note

PTZ privileges are hierarchical. The parent privilege "View live video" must be granted before any PTZ motor privileges can take effect.


Configuration Note: All privileges can be configured in Security Center Config Tool under User Management. Ensure that users or user groups are granted the necessary privileges and have access rights to the partitions containing the cameras they need to access.


Quick Start

This section provides a minimal working example to get you started quickly. For detailed explanations, see the subsequent sections.

Step 1: Include GWP in Your HTML

<!DOCTYPE html>
<html>
<head>
    <title>GWP Quick Start</title>
</head>
<body>
    <div id="playerContainer" style="width: 640px; height: 480px;"></div>
    <script src="https://<YourMediaGatewayAddress>/media/v2/files/gwp.js"></script>
    <script src="app.js"></script>
</body>
</html>

Step 2: Create Your Application (app.js)

// Configuration
const mediaGatewayEndpoint = 'https://<YourMediaGatewayAddress>/media';
const cameraGuid = '00000000-0000-0000-0000-000000000000'; // Replace with your camera GUID
const username = 'admin';
const sdkCertificate = 'YourSDKCertificate'; // From Security Center license
const password = 'yourPassword';

// Token retrieval function
const getTokenFct = async (cameraId) => {
    const response = await fetch(`${mediaGatewayEndpoint}/v2/token/${cameraId}`, {
        credentials: 'include',
        headers: {
            'Authorization': `Basic ${btoa(username + ";" + sdkCertificate + ":" + password)}`
        }
    });

    if (!response.ok) {
        throw new Error(`Failed to fetch token: ${response.statusText}`);
    }

    return await response.text();
};

// Initialize player
async function startPlayer() {
    try {
        // Create player instance
        const divContainer = document.getElementById('playerContainer');
        const webPlayer = gwp.buildPlayer(divContainer);

        // Register error handler
        webPlayer.onErrorStateRaised.register((error) => {
            console.error(`Error ${error.errorCode}: ${error.value}`);
        });

        // Start and connect to camera
        await webPlayer.start(cameraGuid, mediaGatewayEndpoint, getTokenFct);

        // Play live video
        webPlayer.playLive();

        console.log('Player started successfully!');
    } catch (error) {
        console.error('Failed to start player:', error);
    }
}

// Start when page loads
startPlayer();

Step 3: Configure CORS (if needed)

If you see CORS errors, configure the Media Gateway to allow your origin. See the Troubleshooting section.

Next Steps: Continue reading for detailed information on authentication, privileges, PTZ control, playback, and advanced features.


Installation

1. Add GWP to Your Project

The GWP library can be included in two ways:

Using a Script Tag

<script src="https://<MediaGatewayAddress>/media/v2/files/gwp.js"></script>

Using a CommonJS Module

const gwp = require('<MediaGatewayAddress>/media/v2/files/gwp');

Important

It is strongly recommended to load the GWP library directly from your Media Gateway server using the URLs shown above. Each Security Center version includes a specific gwp.js file designed for that version. While you can download and cache the gwp.js file separately, this approach is not recommended as using a mismatched GWP version (e.g., an older gwp.js with a newer Security Center version) may result in compatibility issues, broken functionality, or unexpected behavior. Always ensure the GWP library version matches your Media Gateway version.

2. Verify Version Compatibility

Ensure the GWP library version matches the Media Gateway version. To retrieve the version:

console.log(gwp.version);

The version displayed should match your Security Center/Media Gateway version to ensure full compatibility.


Media Gateway Configuration

Roles and Agents

In Security Center, a Role represents a specific task with its configuration, while Agents are servers assigned to perform that role's work. When you create a Media Gateway role in Security Center, every agent assigned to this role shares the same configuration.

The Genetec Web Player connects to a specific Media Gateway agent. You must provide the public address of this agent in the start() method.

Load Balancing (Multiple Agents)

If you have multiple Media Gateway agents, you are responsible for implementing load balancing logic in your application. The GWP does not automatically load balance between agents.

Simple Approach: Alternate between agents in a round-robin fashion.

Advanced Load Balancing should consider:

  1. Current Server Load - Distribute connections evenly across all agents
  2. Resource Sharing - Streaming the same camera twice from the same agent is more efficient than using two different agents
  3. Network Topology - Avoid long-distance redirection; prefer geographically closer agents
  4. Agent Health - Monitor agent availability and route away from unhealthy agents

Example:

const mediaGatewayAgents = [
    'https://gateway1.example.com/media',
    'https://gateway2.example.com/media',
    'https://gateway3.example.com/media'
];

let currentAgentIndex = 0;

function getNextMediaGatewayAgent() {
    const agent = mediaGatewayAgents[currentAgentIndex];
    currentAgentIndex = (currentAgentIndex + 1) % mediaGatewayAgents.length;
    return agent;
}

// Use when starting player
const mediaGatewayEndpoint = getNextMediaGatewayAgent();
await webPlayer.start(cameraGuid, mediaGatewayEndpoint, getTokenFct);

Authentication

Token-Based Authentication

To connect to the Media Gateway and stream video, the GWP requires a security token. This token is obtained by authenticating with Security Center user credentials (username, password, and SDK certificate). The token contains all Security Center user privileges, which are enforced by the Media Gateway. Only users with the correct Security Center permissions (such as "Log on using the SDK" and "View live video") can retrieve tokens and access video streams.

Obtaining a Token

Tokens can be obtained via the Media Gateway's /v2/token/{cameraId} endpoint.

API Endpoint:

GET /v2/token/{cameraId}

Headers:

  • Authorization: Basic <Base64(username;sdkCertificate:password)>

Example:

const getTokenFct = async (cameraId) => {
    const response = await fetch(`${mediaGatewayEndpoint}/v2/token/${cameraId}`, {
        credentials: 'include',
        headers: {
            'Authorization': `Basic ${btoa(username + ";" + sdkCertificate + ":" + password)}`
        }
    });

    if (!response.ok) {
        throw new Error(`Failed to fetch token: ${response.statusText}`);
    }

    return await response.text();
};

Important Note

  • Do Not Hardcode Credentials: Use server-side logic to fetch tokens securely. The recommended approach is for your backend to handle token requests using Security Center user credentials, then pass the token to the browser.

Summary:

  • GWP relies on Security Center users for authentication and token retrieval.
  • The token is what authorizes and scopes access to video streams.
  • All user privileges are enforced by the Media Gateway based on the Security Center user account used for token generation.

Creating and Managing the Player

Player Life Cycle

A player (or IWebPlayer) represents a single video stream displayed in your web page. The player goes through distinct states during its lifetime:

1. Instantiating the Player

Players are anchored in an existing empty HTML div element on your web page.

const divContainer = document.getElementById('playerContainer');
const webPlayer = gwp.buildPlayer(divContainer);

At this stage:

  • The player displays a black background
  • No connection to Media Gateway has been established
  • The player tries to use as much space as possible in the div element
  • Now is the time to register event handlers before starting the player

Next steps: Either start the player or dispose of it.

2. Starting the Player

The start() method initializes the connection with a Media Gateway for a specific camera (but doesn't play anything until you call playLive() or seek()).

await webPlayer.start(cameraGuid, mediaGatewayEndpoint, getTokenFct);

Parameters:

  • cameraGuid: The unique identifier of the camera in 8-4-4-4-12 format (e.g., "00000001-0000-babe-0000-080023e940c6")
  • mediaGatewayEndpoint: The Media Gateway's public address (e.g., "https://hostname.com/media")
  • getTokenFct: A callback function returning a token (see Authentication)

This call returns a Promise:

  • Succeeds once initialization and connection to Media Gateway is complete
  • Fails if connection cannot be established (invalid parameters, network issues, or token problems)
  • You cannot use the player until the promise completes

Alternative: Use startWithService() for WebSocket multiplexing (see Advanced: Multiplexing Multiple Players)

3. Using the Player

Once started, all player commands can be called. Commands are immediate but are queued internally and handled asynchronously.

Playing a Live Stream:

webPlayer.playLive();

Playback Controls:

// Seek to a specific time
webPlayer.seek(new Date('2023-12-24T10:00:00Z'));

// Pause and Resume
webPlayer.pause();
webPlayer.resume();

// Adjust playback speed (0.01 to 100, or -100 to -0.01 for reverse)
webPlayer.setPlaySpeed(2);    // Fast-forward at 2x speed
webPlayer.setPlaySpeed(-6);   // Reverse playback at 6x speed

Other Controls:

// Enable audio
webPlayer.setAudioEnabled(true);

// Enable PTZ low-latency mode
webPlayer.setPtzMode(true);

// Toggle privacy protection
webPlayer.togglePrivacy();

// Show diagnostic overlay
webPlayer.showDebugOverlay(true);

Next steps: Either stop the player or dispose of it when done.

4. Stopping the Player

Calling stop() on a started player will stop and clear any stream currently being displayed.

webPlayer.stop();

After stopping:

  • No video will be displayed (black background)
  • You can start() again with a different camera or Media Gateway
  • It's generally better to reuse a player for performance and to avoid changing the web page layout

5. Disposing the Player

Disposing will free all resources and remove everything from the HTML div element.

webPlayer.dispose();

Important

  • The player instance becomes completely unusable after disposal
  • Unregister all event handlers before disposing
  • The DOM container is cleared

Error Handling

Overview

The GWP provides error events to help you handle issues such as network problems, invalid tokens, permission errors, or server outages. Proper error handling improves user experience and aids in troubleshooting.

Listening for Errors

The player provides the onErrorStateRaised event that fires when an error occurs. Always register an error handler:

webPlayer.onErrorStateRaised.register((error) => {
    console.error(`Error ${error.errorCode}: ${error.value}`);

    if (error.isFatal) {
        // Fatal errors stop the player
        handleFatalError(error);
    } else {
        // Non-fatal errors may allow continued operation
        handleNonFatalError(error);
    }
});

Error Event Structure

The ErrorStatusEvent object contains:

  • errorCode (number): The error code from the ErrorCode enum
  • value (string): Textual description of the error (not localized)
  • isFatal (boolean): Indicates whether the error stops the player

Error Codes

The GWP uses the following error codes (from the ErrorCode enum):

Error Code Value Description Suggested Action
Unknown 0 Unknown error Display generic error message and retry
ConnectionLost 2 Connection lost Attempt to reconnect or notify user
InsufficientDiskSpace 3 Server has disk space issues Notify user, contact administrator
ConnectionFailed 4 Connection failed Check network connectivity, retry
StreamNotFound 6 Stream not found Verify camera GUID, check camera availability
RequestTimedOut 9 Request timed out Retry operation
UnitPlaybackUnavailable 11 Video unit can't do playback Notify user that playback is unavailable
LiveCapacityExceeded 12 Live stream limit reached Notify user, try again later
PlaybackCapacityExceeded 13 Playback stream limit reached Notify user, try again later
UnsupportedEncoding 14 Unsupported codec Check camera configuration
DatabaseUpgradeRequired 15 Media Router database needs upgrade Contact administrator
InsufficientPrivilege 16 User lacks required privileges Check Security Center privileges, contact administrator
InsufficientCapability 17 Video unit cannot process command Check camera/server capabilities
MissingCertificate 18 Cannot decrypt encrypted stream Check encryption certificates
NotSupported 20 Command not supported Check feature availability
CantUsePrivateKey 21 Certificate missing private key Check certificate configuration
DeniedByServer 23 Server rejected the request Check permissions and configuration
NoTranscodingAllowed 24 Transcoding is prevented Check Media Gateway configuration
ForbiddenTransformation 32 Stream transformation requires transcoding Adjust stream settings or enable transcoding
CloudPlaybackFailure 33 Unable to play from cloud Check cloud configuration
UnsupportedOmnicastFederationRole 34 Omnicast Federation Role not supported Check federation configuration
UpdateSessionError 1000 Invalid stream state Restart player session

Example: Handling Common Errors

webPlayer.onErrorStateRaised.register((error) => {
    switch (error.errorCode) {
        case 16: // InsufficientPrivilege
            displayError('Access denied. You do not have permission to view this camera. Please contact your administrator.');
            break;

        case 2: // ConnectionLost
        case 4: // ConnectionFailed
            displayError('Network connection lost. Attempting to reconnect...');
            // Optionally implement retry logic
            break;

        case 6: // StreamNotFound
            displayError('Camera not found. Please verify the camera is online and try again.');
            break;

        case 9: // RequestTimedOut
            displayError('Request timed out. Please check your network connection and try again.');
            break;

        case 12: // LiveCapacityExceeded
        case 13: // PlaybackCapacityExceeded
            displayError('Server capacity limit reached. Please try again later.');
            break;

        default:
            displayError(`An error occurred: ${error.value}`);
            console.error('Error details:', error);
    }
});

function displayError(message) {
    const errorDiv = document.getElementById('errorDiv');
    errorDiv.textContent = message;
    errorDiv.style.display = 'block';
}

Monitoring Connection Status

In addition to error events, you can monitor the streaming connection status:

webPlayer.onStreamStatusChanged.register((status) => {
    console.log(`Connection status: ${status.state} - ${status.value}`);

    // Handle specific connection states
    if (status.state === 5) { // Streaming
        console.log('Successfully streaming');
    } else if (status.state === 31) { // UnauthorizedToken
        console.error('Token was denied - check user privileges');
    }
});

Refer to the StreamingConnectionStatus enum in the TypeScript definitions for a complete list of connection status codes.


Connection Life Cycle and Recovery

Overview

The player must be connected to the Media Gateway to stream video. Various situations can prevent or interrupt streaming, and the GWP handles connection issues differently depending on whether they are recoverable.

Initial Connection

When you call start(), the player establishes a connection to the Media Gateway. This method returns a Promise:

try {
    await webPlayer.start(cameraGuid, mediaGatewayEndpoint, getTokenFct);
    console.log('Player started successfully');
} catch (error) {
    console.error('Failed to start player:', error);
    // Possible causes: invalid parameters, network issues, invalid token
    // You can periodically retry if connectivity might be restored
}

Automatic Reconnection

Once the player is successfully started, if any streaming problem occurs later, the player will automatically attempt to reconnect and recover to its previous state (e.g., playing live video).

The onStreamStatusChanged event will fire with the value ConnectingToMediaGateway (status code -1) once a connection timeout occurs:

webPlayer.onStreamStatusChanged.register((status) => {
    if (status.state === -1) {
        console.log('Connection lost, attempting to reconnect...');
    } else if (status.state === 5) {
        console.log('Successfully streaming');
    }
});

Recoverable vs Non-Recoverable Errors

Recoverable Errors: Most streaming problems are considered recoverable, and the player will automatically go back to a valid state when the issue is resolved:

  • Connection timeouts
  • Network interruptions
  • Temporary server issues
  • Camera temporarily offline

Non-Recoverable Errors: Some errors require you to manually restart the player (call stop(), then start() again):

Status Code Description Required Action
NotEnoughBandwidth 19 Bandwidth limit reached Stop and restart player when bandwidth is available
MediaRouterStreamNotFound 22 Media Router couldn't find stream Verify camera configuration, restart player
StreamUnreachable 25 No route found for stream Check network topology, restart player
UnauthorizedToken 31 Token was denied Verify user privileges and token, restart player

Example: Handling Non-Recoverable Errors

webPlayer.onStreamStatusChanged.register((status) => {
    const nonRecoverableStates = [19, 22, 25, 31];

    if (nonRecoverableStates.includes(status.state)) {
        console.error('Non-recoverable error:', status.value);

        // Display error to user
        displayError(`Cannot stream: ${status.value}. Please try again.`);

        // Cleanup and prepare for restart
        webPlayer.stop();

        // Optionally: implement retry logic with delay
        setTimeout(() => {
            retryPlayerStart();
        }, 5000);
    }
});

Best Practices

  1. Handle Initial Connection Failures: Always wrap start() in a try-catch block
  2. Monitor Connection Status: Register to onStreamStatusChanged to track connection health
  3. Provide User Feedback: Display meaningful messages during reconnection attempts
  4. Implement Retry Logic: For non-recoverable errors, consider implementing exponential backoff retry
  5. Avoid Automatic Retries on User Errors: Don't auto-retry if the error is due to insufficient privileges or invalid configuration

Advanced Features

PTZ Control: Real-World Use Case

Consider a large retail store using PTZ cameras to monitor different sections. A user can program the PTZ to focus on high-traffic areas during peak hours and adjust manually when suspicious activity is detected:

// Move the camera to monitor entrance
const ptz = webPlayer.ptzControl;
ptz.goToPreset(1); // Preset 1 is configured for the main entrance

// Follow a suspicious individual
ptz.startPanTilt(0.3, -0.2); // Pan right and tilt down
setTimeout(() => ptz.stopPanTilt(), 5000); // Stop after 5 seconds

// Zoom in for a closer look
ptz.startZoom(0.5); // Slowly zoom in
setTimeout(() => ptz.stopZoom(), 3000); // Stop after 3 seconds

Timeline API: Real-World Use Case

A security operator in a corporate setting may want to review past events, such as motion detection in restricted areas:

// Set a timeline range to view activity during the night shift
webPlayer.timelineProvider.setTimelineRange(new Date('2023-12-23T22:00:00Z'), new Date('2023-12-24T06:00:00Z'));

// Display bookmarks and motion detection events
webPlayer.timelineProvider.onTimelineContentUpdated.register(({ events }) => {
    events.forEach(event => {
        if (event.kind === 1) { // Bookmark
            console.log(`Bookmark: ${event.details} at ${event.time}`);
        } else if (event.kind === 0) { // Recording sequence
            console.log(`Motion detected: starts at ${event.time} for ${event.duration}s`);
        }
    });
});

PTZ Control

The GWP supports Pan-Tilt-Zoom (PTZ) control for compatible cameras.

const ptz = webPlayer.ptzControl;
ptz.startPanTilt(0.5, 0.3);  // Start panning and tilting
ptz.stopPanTilt();          // Stop movement
ptz.startZoom(1);           // Zoom in
ptz.stopZoom();             // Stop zooming
ptz.goToPreset(1);          // Move to a preset position

Timeline API

The Timeline API allows you to query and display playback metadata, including recorded video sequences and user bookmarks. The API is designed for graphical timeline representations and focuses on a "range of interest" (the visible portion of the timeline).

Important Limitations:

  • Maximum range: 72 hours between start and end time
  • Recommended range: 24 hours or less for optimal performance
  • The API does not provide user actions (like adding bookmarks) - use the Web SDK or REST SDK for those operations

Setting Timeline Range:

You must set a range of interest before receiving timeline updates. The range can include future times for live updates:

// Set a 24-hour range
const startTime = new Date('2023-12-24T00:00:00Z');
const endTime = new Date('2023-12-25T00:00:00Z');
webPlayer.timelineProvider.setTimelineRange(startTime, endTime);

Important

Register your event handler BEFORE calling setTimelineRange() to avoid missing initial data.

Handling Timeline Updates:

The onTimelineContentUpdated event fires whenever the timeline content changes within your range of interest:

webPlayer.timelineProvider.onTimelineContentUpdated.register((event) => {
    console.log('Coverage:', event.coverageStart, 'to', event.coverageEnd);
    console.log('Events:', event.events);

    event.events.forEach((timelineEvent) => {
        if (timelineEvent.kind === 0) {
            // RecordingSequence
            console.log('Recording from', timelineEvent.time,
                       'duration:', timelineEvent.duration, 'seconds');
        } else if (timelineEvent.kind === 1) {
            // Bookmark
            console.log('Bookmark at', timelineEvent.time,
                       'details:', timelineEvent.details);
        }
    });
});

Timeline Event Structure:

interface TimelineContentEvent {
    coverageStart: Date;    // Start of updated range
    coverageEnd: Date;      // End of updated range
    events: TimelineEvent[]; // All events in coverage range
}

interface TimelineEvent {
    time: Date;                        // Event time or start time
    duration?: number;                 // Duration in seconds (for sequences)
    details?: string;                  // User-provided details (for bookmarks)
    kind: 0 | 1;                      // 0 = RecordingSequence, 1 = Bookmark
}

Understanding Coverage:

The coverageStart and coverageEnd define which part of the timeline was updated. This can be smaller than your range of interest - areas outside the coverage are considered untouched:

// Your range: 00:00 to 24:00
// Coverage received: 10:00 to 14:00
// Interpretation: Only data between 10:00-14:00 changed;
//                 data before 10:00 and after 14:00 remains unchanged

Handling Overlapping Sequences:

Sequences may overlap between updates. You must merge overlapping sequences to build the complete timeline:

function mergeSequences(existingSequences, newSequences) {
    // Merge logic: combine overlapping sequences
    // This is left as an exercise - implement based on your UI needs
    return mergedSequences;
}

Live Updates:

If the endTime is in the future, you'll periodically receive updates for new live recordings:

// Set range including future time for live updates
const now = new Date();
const future = new Date(now.getTime() + (60 * 60 * 1000)); // +1 hour
webPlayer.timelineProvider.setTimelineRange(now, future);

// You'll receive updates as new recordings become available

Timeline Dynamics:

Timeline content can change in real-time:

  • Sequences may get shorter, longer, or disappear
  • Archivers going offline/online affects sequence availability
  • Retention policies may delete old archives
  • Multiple sources (camera, auxiliary archivers) create overlapping sequences

The "Near-Live" Gap:

There's typically a small gap (a few seconds) between the last recorded sequence and "live" time. This is the time it takes for live frames to be written to the archiver and become available for playback. This gap is called the "near-live" period.

Digital Zoom

The GWP supports digital zoom when available (check if webPlayer.digitalZoomControl is non-null). Digital zoom allows users to magnify specific regions of the video for detailed viewing.

Key Features:

  • Zoom factor from 1x (no zoom) to 20x maximum
  • Navigate around the zoomed image
  • Optional preview canvas showing the zoomed region
  • Can zoom into black bars when video aspect ratio doesn't match container

Basic Usage:

const zoom = webPlayer.digitalZoomControl;

if (zoom) {
    // Zoom to a specific point
    zoom.goTo(0.5, 0.5, 2);  // x, y (normalized 0-1), zoom factor

    // Zoom into the center of current view
    zoom.zoom(3);  // Zoom factor 3x

    // Move around at current zoom level
    zoom.move(0.2, -0.1);  // Move right and up (normalized -1 to 1)

    // Zoom with focus point (keeps point at same location)
    zoom.zoomWithFocus(0.3, 0.3, 5);  // x, y, zoom factor

    // Reset to full image
    zoom.stop();

    // Get current position
    console.log(`Position: (${zoom.X}, ${zoom.Y}), Zoom: ${zoom.Zoom}x`);
}

Digital Zoom Preview:

The optional preview canvas shows an overview of the full image with the zoomed region highlighted:

const preview = zoom.Preview;

// Enable/disable the preview
preview.Enabled = true;

// Access the preview canvas for customization
const canvas = preview.Canvas;
canvas.style.position = 'absolute';
canvas.style.top = '10px';
canvas.style.left = '10px';
canvas.style.border = '2px solid white';

Default User Interactions:

The GWP provides built-in mouse/touch interactions for convenience:

On Player Canvas:

  • Click and drag: Moves the zoomed view - the center follows the cursor position
  • Mouse wheel: Not implemented by default (you must implement this yourself if needed)

On Preview Canvas:

  • Click: Centers the zoomed view on the clicked point
  • Drag: Continuously updates the center as you drag

Customizing or Disabling Interactions:

You can override default interactions by intercepting JavaScript events during the capture phase:

// Example: Disable default drag behavior
divContainer.addEventListener('mousedown', (event) => {
    event.stopPropagation();  // Prevents GWP's default handler
    // Implement your custom behavior here
}, true);  // true = capture phase

Implementing Mouse Wheel Zoom:

The GWP doesn't handle mouse wheel by default. Here's a complete implementation:

const zoom = webPlayer.digitalZoomControl;

divContainer.addEventListener('wheel', (event) => {
    event.preventDefault();

    if (!zoom) return;

    const delta = event.deltaY > 0 ? -0.5 : 0.5;  // Scroll direction
    const newZoom = Math.max(1, Math.min(20, zoom.Zoom + delta));

    zoom.zoom(newZoom);
}, { passive: false });

Taking Snapshots of Zoomed View:

// Snapshot of the zoomed portion only
const imageData = zoom.snapshot();
if (imageData) {
    // Convert to downloadable image
    const canvas = document.createElement('canvas');
    canvas.width = imageData.width;
    canvas.height = imageData.height;
    const ctx = canvas.getContext('2d');
    ctx.putImageData(imageData, 0, 0);

    const link = document.createElement('a');
    link.download = 'zoomed-snapshot.png';
    link.href = canvas.toDataURL();
    link.click();
}

Fisheye Dewarping

When a fisheye lens is configured for a camera in Security Center, the GWP can dewarp the image to simulate a PTZ camera experience. This feature is available when webPlayer.dewarperControl is non-null (requires Media Gateway 5.10.2+).

Important Notes:

  • Dewarping is performed in the browser and can be resource-intensive
  • Frame rate is limited to 10 fps when dewarping is enabled
  • Supports common circular fisheye lenses (Acti and Euklis oval lenses may show slight distortion)
  • Replaces digital zoom when available

Basic Usage:

const dewarper = webPlayer.dewarperControl;

if (dewarper) {
    // Check if currently dewarping
    console.log('Is dewarping:', dewarper.isDewarping);

    // Navigate using pan/tilt (in degrees)
    dewarper.gotoPanTilt(45, -20);  // Pan 45° right, tilt 20° down

    // Navigate using X/Y coordinates (normalized -1 to 1)
    dewarper.gotoXY(0.3, 0.3);  // Move to upper-right quadrant

    // Zoom (1x to 20x)
    dewarper.gotoZoom(3);  // 3x zoom

    // Get current position
    console.log(`Pan: ${dewarper.PanDegrees}°, Tilt: ${dewarper.TiltDegrees}°`);
    console.log(`Position: (${dewarper.X}, ${dewarper.Y}), Zoom: ${dewarper.ZoomFactor}x`);

    // Stop dewarping and return to original warped image
    dewarper.stopDewarping();
}

Dewarping Preview:

The preview shows the full fisheye image with the dewarped region highlighted. By default, it appears in the upper-left corner:

const preview = dewarper.Preview;

// Enable/disable preview
preview.Enabled = true;

// Access and customize the preview canvas
const canvas = preview.Canvas;

// Position and style the preview
canvas.style.position = 'absolute';
canvas.style.top = '10px';
canvas.style.left = '10px';
canvas.style.width = '200px';
canvas.style.height = '200px';

// Customize colors using CSS properties
canvas.style.color = 'rgba(255, 255, 0, 0.3)';      // Yellow tint inside visible zone
canvas.style.borderColor = 'red';                    // Red border around visible zone

CSS Customization Table:

CSS Property Effect
color (on preview canvas) Color/tint inside the visible dewarped zone
border-color (on preview canvas) Color of the border outlining the visible zone
color (on main dewarper canvas) Background color outside the fisheye circle

Default User Interactions:

The dewarper provides built-in mouse interactions for both preview and main canvas:

On Preview Canvas:

  • Mouse wheel up: Increases zoom by 0.5x (up to maximum of 20x)
  • Mouse wheel down: Decreases zoom by 0.5x (down to minimum of 1x)
    • Note: Reducing zoom to 1.0x automatically calls stopDewarping() and returns to the original warped stream
  • Left-click: Calls gotoXY() to center the dewarped view at the clicked point
  • Click and drag: Continuously updates center position - the dewarped view follows the cursor

On Main Dewarped Video Canvas:

  • Mouse wheel: Zoom in/out (same behavior as preview)
  • Click and drag: Simulates gotoPanTilt() - horizontal movement sets pan degrees, vertical movement sets tilt degrees

Overriding Default Behaviors:

All default interactions can be overridden by intercepting events during the capture phase:

// Example: Disable zoom on mouse wheel
divContainer.addEventListener('wheel', (event) => {
    event.stopPropagation();  // Prevents GWP's default zoom behavior
    // Implement custom behavior or do nothing
}, true);  // true = capture phase

Snapshot

Capture still images from the video stream using the getSnapshot() method. This returns an ImageData object containing the last displayed frame, or null if no frame is available.

Basic Snapshot:

// Get snapshot from main player (includes watermarking, no zoom/dewarping)
const imageData = webPlayer.getSnapshot();

if (imageData) {
    // Convert ImageData to downloadable image
    const canvas = document.createElement('canvas');
    canvas.width = imageData.width;
    canvas.height = imageData.height;
    const ctx = canvas.getContext('2d');
    ctx.putImageData(imageData, 0, 0);

    // Download as PNG
    const link = document.createElement('a');
    link.download = `snapshot-${new Date().toISOString()}.png`;
    link.href = canvas.toDataURL('image/png');
    link.click();
}

Snapshot Comparison:

Different snapshot sources include different elements:

Source Includes Watermark Includes Zoom/Dewarping
webPlayer.getSnapshot() ✅ Yes ❌ No
digitalZoomControl.snapshot() ❌ No ✅ Yes (zoomed view only)
dewarperControl.snapshot() ❌ No ✅ Yes (dewarped view only)

Display Snapshot in Page:

function displaySnapshot(imageData) {
    const canvas = document.createElement('canvas');
    canvas.width = imageData.width;
    canvas.height = imageData.height;
    const ctx = canvas.getContext('2d');
    ctx.putImageData(imageData, 0, 0);

    const img = new Image();
    img.src = canvas.toDataURL();
    img.style.maxWidth = '300px';
    document.getElementById('snapshotContainer').appendChild(img);
}

// Take and display snapshot
const snapshot = webPlayer.getSnapshot();
if (snapshot) {
    displaySnapshot(snapshot);
}

Privacy Protection

Toggle privacy protection on the video stream to mask sensitive content. When enabled, video will be obscured based on Security Center privacy settings.

// Toggle privacy protection on/off
webPlayer.togglePrivacy();

// Check current privacy protection state
console.log('Privacy protected:', webPlayer.isPrivacyProtected);

// Monitor privacy protection changes
webPlayer.onPrivacyProtectionChanged.register(() => {
    console.log('Privacy protection changed to:', webPlayer.isPrivacyProtected);

    // Update UI to reflect state
    if (webPlayer.isPrivacyProtected) {
        console.log('Video is now privacy protected');
    } else {
        console.log('Video is now unprotected');
    }
});

Note

Privacy protection availability depends on camera configuration and user privileges in Security Center.

Audio Playback

The GWP supports audio streaming when the camera provides an AAC audio codec stream.

Requirements:

  • Codec: Only AAC audio is currently supported
  • Live Audio: Camera must have a microphone
  • Playback Audio: "Audio recording" must be enabled in the camera configuration (disabled by default in Security Center)
  • User Privileges: User must have appropriate audio viewing privileges

Checking Audio Availability:

// Check if audio is available for this camera
console.log('Audio available:', webPlayer.isAudioAvailable);

// Monitor audio availability changes
webPlayer.onAudioAvailabilityChanged.register((event) => {
    console.log('Audio availability changed:', event.isAudioAvailable);

    if (event.isAudioAvailable) {
        console.log('Audio is now available - you can enable it');
    } else {
        console.log('Audio is not available at this time');
    }
});

Note

isAudioAvailable checks camera capabilities and user privileges, but it doesn't guarantee audio is present at the current moment.

Enabling Audio Playback:

// Enable audio playback
webPlayer.setAudioEnabled(true);

// Disable audio
webPlayer.setAudioEnabled(false);

// Check if audio is currently enabled
console.log('Audio enabled:', webPlayer.isAudioEnabled);

// Monitor audio state changes
webPlayer.onAudioStateChanged.register((event) => {
    console.log('Audio state changed:', event.isAudioEnabled);

    // Update UI (e.g., toggle mute button)
    updateMuteButton(event.isAudioEnabled);
});

Important: Browser Autoplay Policy

Modern browsers prevent audio from playing automatically without user interaction. If you try to enable audio on page load or without a user action, the browser will likely block it.

Best Practices:

  1. Only enable audio in response to user actions (button click, touch event, etc.)
  2. Never auto-enable audio on page load or player start
  3. Provide UI controls for users to explicitly enable/disable audio

Example: Audio Toggle Button

// HTML: <button id="toggleAudioBtn">Unmute</button>

const audioBtn = document.getElementById('toggleAudioBtn');

audioBtn.addEventListener('click', () => {
    // User action triggers audio - browser allows this
    const currentState = webPlayer.isAudioEnabled;
    webPlayer.setAudioEnabled(!currentState);

    // Update button text
    audioBtn.textContent = !currentState ? 'Mute' : 'Unmute';
});

// Keep button in sync with audio state
webPlayer.onAudioStateChanged.register((event) => {
    audioBtn.textContent = event.isAudioEnabled ? 'Mute' : 'Unmute';
});

Browser Autoplay Consequences:

If you attempt to enable audio without user interaction:

  • The browser may blacklist your page from playing audio
  • Future audio enable attempts may also be blocked
  • Users may need to manually adjust browser permissions to restore audio

Handling Autoplay Failures:

There's no direct event for autoplay blocking. If audio doesn't play after enabling it, assume the browser blocked it and prompt the user to click an audio button.

Stream Usage and Resolution Selection

In Security Center, cameras can provide multiple stream configurations labeled by "stream usage":

  1. Live - Default live viewing stream
  2. Recording - Stream being recorded to archiver
  3. Remote - Optimized for remote/WAN viewing
  4. Low Resolution - Lower quality for bandwidth savings
  5. High Resolution - Highest quality available

Automatic Stream Selection:

By default, GWP uses automatic stream selection in live mode, choosing the appropriate stream based on player size:

// Automatic mode (default)
// - Player size < 640x480: Uses Low Resolution stream
// - Player size 640x480 to 1280x720: Uses Live stream
// - Player size > 1280x720: Uses High Resolution stream

// The stream automatically switches when the player is resized

Configuration:

Stream selection is configured in the Media Gateway configuration page in Config Tool. You can choose:

  • Specific stream usage (e.g., always use High Resolution)
  • Automatic mode with custom thresholds

Transcoding:

If the browser doesn't support the camera's codec, the Media Gateway can transcode the stream. Transcoding configuration in Media Gateway settings:

  • Never - No transcoding (some streams may be unplayable)
  • For PTZ Only - Transcode only when PTZ mode is enabled
  • Always - Allow transcoding for unsupported codecs

PTZ Low-Latency Mode:

Enable PTZ mode to prioritize low latency over stream quality (may trigger transcoding):

// Enable PTZ mode for low-latency control
webPlayer.setPtzMode(true);

// Perform PTZ operations with reduced latency
const ptz = webPlayer.ptzControl;
ptz.startPanTilt(0.5, 0);

// Disable when done to reduce server load
webPlayer.setPtzMode(false);

Note

Transcoding is computationally expensive for the Media Gateway server. Configure maximum output resolution and frame rate limits in Media Gateway settings to control resource usage.

Diagnostic Overlay

The GWP includes a built-in diagnostic overlay for troubleshooting stream issues. The overlay displays real-time information about the stream, including codec, resolution, frame rate, latency, and connection state.

Enable/Disable the Overlay:

// Show the diagnostic overlay
webPlayer.showDebugOverlay(true);

// Hide the diagnostic overlay
webPlayer.showDebugOverlay(false);

// Toggle with keyboard shortcut: Ctrl+Shift+A (when player canvas has focus)

Overlay Information Includes:

  • Tile ID and camera information
  • Video codec and resolution
  • Frame rate (current and average)
  • Player state and streaming state
  • Network latency (global and local)
  • Media time and timestamps
  • Bitrate and key frame interval

Important

The diagnostic overlay's appearance and content may change in future versions. It is intended for troubleshooting only, not for production use.

Enable GWP Console Logs:

For detailed debugging information in the browser console:

// Enable standard GWP logs (Info level)
gwp.enableLogs();

// Enable verbose/intense logging (Debug level - very detailed)
gwp.enableLogs(true);

// Disable logs (warnings and errors still shown)
gwp.disableLogs();

Log Filtering: All GWP logs are prefixed with the 🐹 emoji for easy filtering in the browser console.

Browser-Specific Behavior:

  • Chrome: GWP logs appear as "Info" level
  • Firefox: GWP logs appear as "Logs" and "Info" levels

Warning

Intense logging (gwp.enableLogs(true)) generates a large volume of output and can impact performance. Use it only when necessary for troubleshooting, and disable it when done.

Advanced: Multiplexing Multiple Players

By default, each player creates its own WebSocket connection to the Media Gateway. If you need to display many players simultaneously, you can multiplex them over a single WebSocket connection for better performance and resource efficiency.

Note

This is an advanced feature. A communication failure of the shared socket will impact all players using it.

Creating a Media Gateway Service

First, create a shared Media Gateway service:

const mediaGatewayService = await gwp.buildMediaGatewayService(
    mediaGatewayEndpoint,
    getTokenFct
);

Starting Players with the Service

Use startWithService() instead of start() for each player:

// Create multiple players
const player1 = gwp.buildPlayer(document.getElementById('player1'));
const player2 = gwp.buildPlayer(document.getElementById('player2'));
const player3 = gwp.buildPlayer(document.getElementById('player3'));

// Start all players with the same service
await player1.startWithService(camera1Guid, mediaGatewayService);
await player2.startWithService(camera2Guid, mediaGatewayService);
await player3.startWithService(camera3Guid, mediaGatewayService);

// Control each player independently
player1.playLive();
player2.playLive();
player3.seek(new Date('2023-12-24T10:00:00Z'));

Complete Example

async function setupMultiplePlayers() {
    try {
        // Create shared service
        const mediaGatewayService = await gwp.buildMediaGatewayService(
            'https://gateway.example.com/media',
            getTokenFct
        );

        // Define cameras to display
        const cameras = [
            { id: 'camera-guid-1', container: 'player1' },
            { id: 'camera-guid-2', container: 'player2' },
            { id: 'camera-guid-3', container: 'player3' },
            { id: 'camera-guid-4', container: 'player4' }
        ];

        // Create and start all players
        const players = [];
        for (const cam of cameras) {
            const player = gwp.buildPlayer(document.getElementById(cam.container));

            // Register error handler
            player.onErrorStateRaised.register((error) => {
                console.error(`Player ${cam.container} error:`, error.value);
            });

            await player.startWithService(cam.id, mediaGatewayService);
            player.playLive();

            players.push(player);
        }

        console.log(`Started ${players.length} players over single WebSocket`);

        return players;
    } catch (error) {
        console.error('Failed to setup multiplexed players:', error);
        throw error;
    }
}

Benefits and Considerations

Benefits:

  • Reduced number of WebSocket connections
  • Lower network overhead
  • Better resource utilization
  • Improved performance with many simultaneous players

Considerations:

  • Single point of failure: if the shared WebSocket connection fails, all players are affected
  • More complex error handling
  • Players must connect to the same Media Gateway agent

Limitations

  1. Audio: Only AAC audio codec is supported. For playback, "audio recording" must be enabled in the camera configuration (disabled by default in Security Center).
  2. Reverse Playback: Smooth reverse playback is only supported for MJPEG streams. Other codecs will play keyframes only during reverse playback (recommended minimum speed: -6x).
  3. Browser Codec Support: Some codecs may require transcoding on the Media Gateway server. Currently, most browsers support H.264 and MJPEG decoding natively.
  4. Dewarping Frame Rate: When dewarping is enabled, frame rate is limited to 10 fps due to browser processing requirements.
  5. Dewarping Lens Support: Dewarping currently supports common circular fisheye lenses. Oval lenses (such as Acti and Euklis) may show slight distortion. Special viewing modes (e.g., Panorama effect) are not yet supported.
  6. CORS Configuration: The Media Gateway must be configured to accept requests from your web application's origin. See the CORS Configuration section.

Cross-Origin Resource Sharing (CORS)

Overview

Cross-Origin Resource Sharing (CORS) is a security mechanism enforced by web browsers that restricts how resources on a web server can be requested from a different origin. For Genetec Web Player (GWP), proper CORS configuration ensures that web applications can securely communicate with the Media Gateway while preventing unauthorized access.

Configuring CORS Restrictions

To enforce CORS restrictions, administrators must modify the MediaGateway.gconfig file. This file is located in the ConfigurationFiles directory on the Media Gateway server. If the file does not exist, it must be created manually in this directory.

Location of ConfigurationFiles Directory

Typically, the ConfigurationFiles directory is found in:

C:\Program Files (x86)\Genetec Security Center X.X\

where X.X represents the version of Security Center installed on the server.

Restricting Access to Specific Domains

To limit CORS access exclusively to specific domains, create or modify the MediaGateway.gconfig file and include the following XML structure:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <MediaGateway EnforceStrictCrossOrigin="true"/>
</Configuration>

This setting prevents other web applications from making requests to the Media Gateway, allowing only official Security Center clients to access it.

Defining a Custom Allowed Origins List

For custom web applications that integrate GWP, administrators can specify allowed origins explicitly. To define specific origins, update the MediaGateway.gconfig file as follows:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <MediaGateway EnforceStrictCrossOrigin="true">
        <AllowedOrigin Origin="https://example1.com" />
        <AllowedOrigin Origin="https://example2.com" />
        <AllowedOrigin Origin="https://web.example3.com" />
    </MediaGateway>
</Configuration>

In this configuration, only the domains example1.com, example2.com, and web.example3.com can request video streams from the Media Gateway.


Troubleshooting

This section covers common issues and their solutions when working with the Genetec Web Player.

Most Common Issues

The following are the most frequently encountered issues by developers:


1. Browser Blocks Untrusted Certificate (Self-Signed Certificate)

Symptoms:

  • Browser shows security warning or blocks connection
  • "Your connection is not private" or "NET::ERR_CERT_AUTHORITY_INVALID" error
  • Unable to load gwp.js or connect to Media Gateway
  • Console shows certificate errors

Cause: The Media Gateway is using a self-signed SSL certificate that the browser doesn't trust.

Solutions:

  1. Accept the Certificate in Browser (Development/Testing Only)

    • Navigate directly to the Media Gateway URL in your browser: https://<MediaGatewayAddress>
    • Browser will show security warning
    • Click "Advanced" and "Proceed to [site]" (or similar option depending on browser)
    • This adds a temporary exception for the certificate
    • Note: This only works for testing and must be done in each browser/device
  2. Install Valid SSL Certificate (Recommended for Production)

    • Obtain an SSL certificate from a trusted Certificate Authority (CA)
    • Install the certificate on the Media Gateway server
    • Configure Media Gateway to use the valid certificate
    • This is the recommended approach for production environments
  3. Install Self-Signed Certificate in Operating System (Development)

    • Export the self-signed certificate from the Media Gateway
    • Install it in the operating system's trusted root certificate store
    • Restart browser after installation
    • More permanent than browser exceptions but still not recommended for production

Important

Self-signed certificates should only be used in development/testing environments. Production environments should always use certificates from trusted Certificate Authorities.


2. 401 Unauthorized - Invalid Credentials, Privileges, or Access Rights

Symptoms:

  • HTTP 401 Unauthorized error when retrieving token
  • Error code 16 (InsufficientPrivilege)
  • Video player fails to start or shows permission error
  • "Access denied" messages

Cause: Authentication failure due to incorrect credentials, missing privileges, or lack of partition access.

Solutions:

A. Check Credentials

  1. Verify username and password are correct
  2. Verify SDK certificate string is correct
  3. Check Authorization header format: Basic <Base64(username;sdkCertificate:password)>
  4. Ensure no extra spaces or special characters in credentials
  5. Test login in Security Center Config Tool to confirm credentials work

B. Check Security Center Privileges

Required privileges for all GWP applications:

  1. "Log on using the SDK" (Application privileges)
  2. "View camera properties" (Administrative privileges - Physical entities)
  3. "Live hit monitoring" (Web App privileges)

Additional privileges depending on features used: 4. For live video: "View live video" (Action privileges - Cameras) 5. For playback: "View playback" (Action privileges - Cameras) 6. For PTZ: Check PTZ motor privileges (requires "View live video" first)

See the complete Security Center Privileges section for details

C. Check Partition Access Rights

  1. Verify the user has access rights to the partition containing the camera
  2. In Security Center Config Tool:
    • Go to User Management
    • Select the user
    • Check "Access rights" tab
    • Ensure the user has access to the camera's partition
  3. Common mistake: User has all privileges but no partition access

D. Check Camera Configuration

  1. Verify the camera GUID is correct
  2. Ensure the camera exists and is online in Security Center
  3. Check that the camera is assigned to a partition the user can access

Testing Steps:

// Test token retrieval
const testToken = async () => {
    try {
        const response = await fetch(`${mediaGatewayEndpoint}/v2/token/${cameraId}`, {
            credentials: 'include',
            headers: {
                'Authorization': `Basic ${btoa(username + ";" + sdkCertificate + ":" + password)}`
            }
        });

        console.log('Status:', response.status);
        if (response.ok) {
            console.log('Token retrieved successfully');
        } else {
            console.error('Failed:', response.status, response.statusText);
        }
    } catch (error) {
        console.error('Error:', error);
    }
};

3. CORS (Cross-Origin Resource Sharing) Errors

Symptoms:

  • Browser console shows CORS errors
  • "Access to fetch/XMLHttpRequest blocked by CORS policy" error
  • "No 'Access-Control-Allow-Origin' header is present"
  • Token retrieval or WebSocket connection fails

Cause: The Media Gateway is not configured to allow requests from your web application's origin.

Solutions:

  1. Configure Media Gateway CORS Settings

    Modify the MediaGateway.gconfig file located in the ConfigurationFiles directory:

    C:\Program Files (x86)\Genetec Security Center X.X\ConfigurationFiles\MediaGateway.gconfig
    

    Option A: Allow specific origins (Recommended)

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration>
        <MediaGateway EnforceStrictCrossOrigin="true">
            <AllowedOrigin Origin="https://yourapp.example.com" />
            <AllowedOrigin Origin="http://localhost:3000" />
        </MediaGateway>
    </Configuration>

    Option B: Allow all origins (Development only - NOT recommended for production)

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration>
        <MediaGateway EnforceStrictCrossOrigin="false"/>
    </Configuration>
  2. Restart the Media Gateway Role after modifying the configuration file

  3. Verify Your Application's Origin

    • Origin includes protocol, domain, and port
    • Examples: https://app.example.com, http://localhost:3000, https://192.168.1.100:8080
    • Make sure the exact origin is listed in the configuration
  4. Check for Multiple Origins

    • If testing from multiple locations (localhost, staging, production), add all origins

Common CORS Mistakes:

  • Forgetting to restart Media Gateway after config change
  • Origin mismatch (e.g., http vs https, different port numbers)
  • Trailing slashes in origin URLs
  • Using IP address in code but domain name in CORS config (or vice versa)

See the complete CORS Configuration section for more details.


4. GWP.js Version Mismatch

Symptoms:

  • Unexpected errors or exceptions
  • Missing methods or properties
  • Features not working as documented
  • "undefined is not a function" errors
  • Inconsistent behavior

Cause: The gwp.js file version doesn't match the Media Gateway/Security Center version.

Solutions:

  1. Always Load from Media Gateway

    Correct approach:

    <script src="https://<MediaGatewayAddress>/media/v2/files/gwp.js"></script>

    Incorrect approaches:

    • ❌ Using a downloaded/cached copy from a different Security Center version
    • ❌ Hosting gwp.js on your own server
    • ❌ Loading from a different Media Gateway than you're connecting to
  2. Verify Version Match

    // Check GWP version
    console.log('GWP Version:', gwp.version());
    // This should match your Security Center/Media Gateway version
  3. Clear Browser Cache

    • Browser may be caching an old version of gwp.js
    • Hard refresh: Ctrl+F5 (Windows) or Cmd+Shift+R (Mac)
    • Clear browser cache completely
    • Try in incognito/private browsing mode
  4. Check for Multiple Script Tags

    • Ensure you're not loading gwp.js multiple times
    • Check that no other libraries are loading an older version
  5. After Security Center Upgrade

    • If Security Center was upgraded, the gwp.js file changes automatically
    • Users with cached versions will have mismatches
    • Consider cache-busting strategies:
      <script src="https://<MediaGatewayAddress>/media/v2/files/gwp.js?v=5.12"></script>

Prevention:

  • Always reference gwp.js from the Media Gateway server
  • Don't download and host gwp.js separately
  • Document the Security Center version your application is tested with
  • Test thoroughly after Security Center upgrades

See the Installation section for more details.


Using Browser Developer Tools

Enable GWP logs and use browser developer tools to diagnose issues:

// Enable detailed GWP logging
gwp.enableLogs(true);

Check the Browser Console:

  1. Open Developer Tools (F12)
  2. Go to Console tab
  3. Look for error messages, warnings, or GWP logs
  4. Note error codes and descriptions

Check Network Tab:

  1. Open Developer Tools (F12)
  2. Go to Network tab
  3. Filter for WebSocket connections (WS/WSS)
  4. Check for failed requests or CORS errors
  5. Verify token retrieval requests succeed

Check the Debug Overlay:

// Show diagnostic overlay on the player
webPlayer.showDebugOverlay(true);

The debug overlay displays real-time information about:

  • Connection status
  • Stream statistics
  • Frame rate and codec information
  • Buffering status

Getting Additional Help

If issues persist after trying the solutions above:

  1. Enable verbose logging:

    gwp.enableLogs(true); // Enable intense logging
  2. Gather diagnostic information:

    • GWP version: gwp.version()
    • Security Center version
    • Browser and OS version
    • Error codes from console
    • Network tab screenshots showing failed requests
  3. Contact Genetec Support with the diagnostic information


Additional Debugging Tips

  • Use Logs: Enable GWP logs to gather detailed information:

    gwp.enableLogs();
  • Check Network Accessibility: Ensure the Media Gateway is reachable from your network.

  • Validate Configuration: Confirm the Media Gateway role and permissions are properly configured in Security Center.

Security Center SDK

  • Security Center SDK Developer Guide Overview of the SDK framework and how to build integrations with Security Center.

    • Platform SDK

      • Overview Introduction to the Platform SDK and core concepts.
      • Connecting to Security Center Step-by-step guide for connecting and authenticating with the SDK.
      • SDK Certificates Details certificates, licensing, and connection validation.
      • Referencing SDK Assemblies Best practices for referencing assemblies and resolving them at runtime.
      • SDK Compatibility Guide Understanding backward compatibility and versioning in the SDK.
      • Entity Guide Explains the core entity model, inheritance, and how to work with entities.
      • Entity Cache Guide Describes the engine's local entity cache and synchronization.
      • Transactions Covers batching operations for performance and consistency.
      • Events Subscribing to real-time system events.
      • Actions Sending actions to Security Center.
      • Security Desk Displaying content on monitors, reading tiles, sending tasks, and messaging operators.
      • Custom Events Defining, raising, and subscribing to custom events.
      • ReportManager Querying entities and activity data from Security Center.
      • ReportManager Query Reference Complete reference of query types, parameters, and response formats.
      • Privileges Checking, querying, and setting user privileges.
      • Partitions Entity organization and access control through partitions.
      • Logging How to configure logging, diagnostics, and debug methods.
    • Plugin SDK

    • Workspace SDK

    • Macro SDK

      • Overview How macros work, creating and configuring macro entities, automation, and monitoring.
      • Developer Guide Developing macro code with the UserMacro class and Security Center SDK.

Web SDK Developer Guide

  • Getting Started Setup, authentication, and basic configuration for the Web SDK.
  • Referencing Entities Entity discovery, search capabilities, and parameter formats.
  • Entity Operations CRUD operations, multi-value fields, and method execution.
  • Partitions Managing partitions, entity membership, and user access control.
  • Custom Fields Creating, reading, writing, and filtering custom entity fields.
  • Custom Card Formats Managing custom credential card format definitions.
  • Actions Control operations for doors, cameras, macros, and notifications.
  • Events and Alarms Real-time event monitoring, alarm monitoring, and custom events.
  • Incidents Incident management, creation, and attachment handling.
  • Reports Activity reports, entity queries, and historical data retrieval.
  • Tasks Listing and executing saved report tasks.
  • Macros Monitoring currently running macros.
  • Custom Entity Types Listing, retrieving, and deleting custom entity type descriptors.
  • System Endpoints License usage, web tokens, and exception handling.
  • Performance Guide Optimization tips and best practices for efficient API usage.
  • Reference Entity GUIDs, EntityType enumeration, and EventType enumeration.
  • Under the Hood Technical architecture, query reflection, and SDK internals.
  • Troubleshooting Common error resolution and debugging techniques.

Media Gateway Developer Guide


Web Player Developer Guide

  • Developer Guide Complete guide to integrating GWP for live and playback video streaming.
  • API Reference Full API documentation with interfaces, methods, properties, and events.
  • Sample Application Comprehensive demo showcasing all GWP features with timeline and PTZ controls.
  • Multiplexing Sample Multi-camera grid demo using a shared WebSocket connection.

Clone this wiki locally