Viewer Preferences

Give end-users control over privacy and accessibility settings.

Overview

Viewer preferences give end-users control over privacy and accessibility. They are the third tier of the MP4E permission model, applied after creator restrictions (embedded in metadata) and host config (set by the hosting application).

The permission model uses an intersection approach: each tier can only restrict capabilities, never expand them. If a creator blocks seeking, the viewer cannot re-enable it. Viewer preferences focus on privacy and presentation concerns that the viewer has final say over.

Preferences are stored in localStorage and persist across videos and sessions.

Permission Model
// Three-tier permission model (intersection — each layer restricts, never expands)

// Tier 1: Creator restrictions (embedded in metadata)
// metadata.settings.restrictions = { sequential: true, actions: { navigate: false } }

// Tier 2: Host config (set via config prop)
// <MP4EPlayer config={{ sandbox: { actions: { seek: false } } }} />

// Tier 3: Viewer preferences (set at runtime)
// playerRef.current?.setViewerPreferences({ doNotTrack: true })

// The engine applies ALL tiers. If ANY tier blocks an action, it is blocked.

Privacy Settings

Privacy settings let the viewer control what data is shared with plugins and whether tracking is allowed.

PropTypeDefaultDescription
doNotTrackbooleanfalseDisables analytics and tracking actions. The engine suppresses trackEvent and similar actions, preventing them from reaching plugins.
doNotShareIdentitybooleanfalseSuppresses user ID and email in plugin context. Plugins see anonymized data instead of host-provided identity variables.
limitStoragebooleanfalsePrevents localStorage usage by plugins. The plugin storage API returns empty values, and only session-level preferences are retained.
Privacy enforcement
When doNotTrack is enabled, the engine silently suppresses tracking actions. Plugins are not notified that tracking was requested — the action is simply dropped. This prevents plugins from detecting and working around the preference.

Accessibility Settings

Accessibility settings let the viewer adjust how overlays and plugins are presented.

PropTypeDefaultDescription
reducedMotionbooleanfalseDisables animations and transitions. Overlays appear and disappear instantly without fade or slide effects.
highContrastbooleanfalseEnables high contrast mode. Affects overlay borders and text rendering for improved readability.
System preference detection
Consider reading the operating system's prefers-reduced-motion and prefers-contrast media queries to automatically set these preferences on first load.

API

Use the player ref to set and get viewer preferences programmatically. Partial updates are supported — only the specified fields are changed.

ViewerPreferencesExample.tsx
1import { useRef } from 'react';
2import { MP4EPlayer, type MP4EPlayerRef } from '@mp4e/react';
3import '@mp4e/react/styles.css';
4
5function PrivacyAwarePlayer() {
6 const playerRef = useRef<MP4EPlayerRef>(null);
7
8 // Set viewer preferences
9 const enablePrivacyMode = () => {
10 playerRef.current?.setViewerPreferences({
11 doNotTrack: true,
12 doNotShareIdentity: true,
13 limitStorage: true,
14 });
15 };
16
17 // Set accessibility preferences
18 const enableAccessibility = () => {
19 playerRef.current?.setViewerPreferences({
20 reducedMotion: true,
21 highContrast: true,
22 });
23 };
24
25 // Get current preferences
26 const logPreferences = () => {
27 const prefs = playerRef.current?.getViewerPreferences();
28 console.log('Current viewer preferences:', prefs);
29 };
30
31 return (
32 <div>
33 <MP4EPlayer ref={playerRef} src="/video.mp4" />
34 <button onClick={enablePrivacyMode}>Privacy Mode</button>
35 <button onClick={enableAccessibility}>Accessibility Mode</button>
36 <button onClick={logPreferences}>Log Preferences</button>
37 </div>
38 );
39}

Player Menu Integration

Viewers can toggle these preferences directly from the player settings menu (gear icon) without any host code. The player menu exposes toggle switches for each preference, and changes take effect immediately.

Preferences set through the menu are persisted to localStorage and apply across all videos on the same domain. When a viewer returns to any video, their preferences are automatically restored.

How Preferences Flow

Viewer preferences flow through the system in a predictable pipeline:

  1. Host or menu sets preferences — The host application calls setViewerPreferences(), or the viewer toggles a setting in the player menu.
  2. Bridge passes to engine — The bridge layer forwards the preferences object to the Rust engine via the WASM boundary.
  3. Engine adjusts behavior — The engine stores the preferences and enforces them during action execution. Tracking actions are suppressed, identity variables are anonymized, animations are disabled, and contrast modes are applied.
  4. Preferences persist — The bridge writes the preferences to localStorage so they survive page reloads and apply to future videos.
Engine-enforced
Viewer preferences are enforced at the engine level, not at the UI level. Plugins cannot bypass them — the engine will not emit suppressed events regardless of what plugins request.