This document is about: VOICE 2
SWITCH TO

Voice Moderation with Photon Voice

Introduction

If your application uses integrated voice chat, you may need to add moderation to meet local privacy and compliance requirements. While Photon does not provide a built-in moderation service, it supports secure server-to-server integrations with trusted providers:

A server-to-server integration offers the following advantages compared to client-side solutions:

  • Increased security: Prevents client-side manipulation of moderation features.
  • Optimized bandwidth usage: Eliminates redundant client-to-service streams and avoids transmitting muted streams from the server to clients.

To enable external moderation, configure the service credentials in the Photon Dashboard. Photon Cloud will automatically forward the voice streams to the selected provider’s API endpoint.

Keep in mind:

  • You need a paid account with the moderation provider.
  • Bandwidth usage of your app on Photon Cloud will increase depending on your voice quality settings.
  • All streams are sent securely via HTTPS directly to the provider. Photon does not log or store any audio data.

How to setup Voice Moderation for your Photon Voice app

Note: A paid Photon Cloud plan greater 100 CCU is required to activate voice moderation forwarding

Step 1: Create an account and subscribe to the voice moderation service of your choice. Make sure you’ll have all required information at hand (see config details below).

Step 2: Contact us via email to [email protected] and ask to unlock the voice moderation feature.

Step 3: Go to dashboard.photonengine.com, “YOUR > APPS > Premium Cloud” and click on “Manage” in your Voice application box.

Step 4: In the Plugins section, activate either the ToxMod or GGWP config by clicking on the “Create [...] Plugin” button and enter all required information to the config

Although ToxMod and GGWP configuration and features are similar, there are some differences.

ToxMod

ApiKey
The API key used to authenticate within the voice moderation service

AccountId
Name of the account used to authenticate with ToxMod API

IsActive
Can be used to temporarily disable the service without removing the plugin setup.

SingleTenantPrefix
This value is provided by Modulate.AI to be used as additional information within their API. Usually it is empty.

GGWP

ApiKey
The API key used to authenticate within the voice moderation service

IsActive
Can be used to temporarily disable the service without removing the plugin setup.

Additional options for Enterprise Customers

The Photon Voice Moderation integration is based on the battle-tested Photon Server Plugin-architecture (doc.photonengine.com/server/current/plugins/manual). It offers a valuable set of additional features for Enterprise customers in their Private Cloud environment. If you are interested in operating your own plugin, please contact us via mail: [email protected].

Overview

Server-to-Server integration and additional features using the Enterprise custom plugin

ForwardPercentage

Percentage of rooms that are forwarded to the voice moderation service. GGWP expects to use lower numbers for testing purposes. ToxMod does expect to always have 100%.

UseAnonIDs

Indicates whether anonymized UserIDs and SessionIDs are used when forwarding to voice moderation service. Works currently for GGWP only. ToxMod requires to use UUID values, so it is always anonymized (using a method designed by them)

MutePollInterval

Interval in milliseconds, how often to ask HTTP service for a list of muted users. 5000 is the default value.

MutePollUrl

URL of the HTTP service that provides a list of muted users (customer's backend)
The mute poll configuration expects a HTTP service that provides a list of players who are globally muted (this can be used for moderation). Each request is a POST request with application/json content in format:

{users:[

  —-Comma separated list of UserIDs of currently active users—-

]}

And the response would again be a application/json array of UserIDs, that are muted:

[user1,user2,...]

Enterprise Client Features

Clients can provide muting and proximity data to the plugin. It uses RaiseEvent operation, with a s system command event code - 220. The expected data is an object array with 3 fields.

  • First field is a byte value indicating the subcode of the operation
    • 2 = UpdateMute
    • 3 = UpdateProximity
  • Second field is an integer or string array - a list of players (ActorNrs or UserIds)
  • Third optional field is an operation type,
    • 0 or not set means Set operation - the list of players is set as a value for muted players or players in proximity,
    • 1 is Remove - players from the list are removed from muted players or players in proximity
    • 2 is Add - players from the list are added to muted players or players in proximity

Here is a code snippet for PhotonTransport.cs of PhotonVoice SDK, to simplify the client-server communication regarding muting and proximity.

C#

#if USE_VOICE_PLUGIN  
    public void AddToProximity(IEnumerable<int> playersInProximity)  
    {  
        this.UpdateProximity(playersInProximity, CommandEventMethod.Add);  
    }

    public void RemoveFromProximity(IEnumerable<int> playersInProximity)  
    {  
        this.UpdateProximity(playersInProximity, CommandEventMethod.Remove);  
    }

    public void SetProximity(IEnumerable<int> playersInProximity)  
    {  
        this.UpdateProximity(playersInProximity, CommandEventMethod.Set);  
    }

    private void UpdateProximity(IEnumerable<int> playersInProximity, CommandEventMethod method)  
    {  
        PluginCommand(CommandEventSubcode.UpdateProximity, playersInProximity, method);  
    }

    public void AddMuted(IEnumerable<int> playersMuted)  
    {  
        this.UpdateMuted(playersMuted, CommandEventMethod.Add);  
    }

    public void RemoveMuted(IEnumerable<int> playersMuted)  
    {  
        this.UpdateMuted(playersMuted, CommandEventMethod.Remove);  
    }

    public void SetMuted(IEnumerable<int> playersMuted)  
    {  
        this.UpdateMuted(playersMuted, CommandEventMethod.Set);  
    }

    private void UpdateMuted(IEnumerable<int> playersMuted, CommandEventMethod method)
    {  
        PluginCommand(CommandEventSubcode.UpdateMute, playersMuted, method);  
    }

    private void PluginCommand(CommandEventSubcode subCode, IEnumerable<int> players, CommandEventMethod method)
    {  
        var data = new object[3];  
        data[0] = (byte)subCode;  
        data[1] = players.ToArray();  
        data[2] = (byte)method;

        this.OpRaiseEvent(220, data, RaiseEventOptions.Default, SendOptions.SendReliable);  
    }  
#endif  
Back to top