Troubleshooting

Common issues and solutions for MP4E integration.

Overview

This guide covers common issues encountered when integrating MP4E and their solutions.

Video Playback

Video won't play

Codec Compatibility

Ensure your video uses web-compatible codecs (H.264/AAC).

bash
// Check video codec compatibility
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 video.mp4

// Convert to web-compatible format
ffmpeg -i input.mp4 -c:v libx264 -profile:v high -level 4.0 -pix_fmt yuv420p -c:a aac output.mp4

CORS Issues

Video hosted on a different domain needs proper CORS headers.

javascript
// Express.js CORS setup
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Headers', 'Range');
  res.header('Access-Control-Expose-Headers', 'Content-Range, Content-Length');
  next();
});

// Nginx CORS setup
location /videos/ {
  add_header 'Access-Control-Allow-Origin' '*';
  add_header 'Access-Control-Allow-Headers' 'Range';
  add_header 'Access-Control-Expose-Headers' 'Content-Range, Content-Length';
}

Autoplay Blocked

Browsers block autoplay with sound. Use muted={true} for autoplay, or handle the play promise rejection gracefully.

Metadata Loading

Metadata not loading

Debug metadata loading
1// Debug metadata loading
2<MP4EPlayer
3 src="/video.mp4"
4 onEvent={(event, data) => {
5 if (event === 'metadata:loaded') {
6 // data is the document view (overrides already merged in)
7 console.log('Schema version:', data.schemaVersion);
8 console.log('Objects:', data.objectCount);
9 console.log('Layers:', data.layers.length);
10 console.log('Overlays:', data.layers.flatMap((layer) => layer.overlays).length);
11 }
12 if (event === 'metadata:error') {
13 console.error('Metadata error:', data);
14 }
15 }}
16/>
17
18// Verify embedded metadata
19ffprobe -v error -show_entries format_tags=com.mp4e.data:payload -of default=noprint_wrappers=1 video.mp4

Embedded Metadata Missing

Verify the video has embedded metadata using ffprobe. If missing, re-export from Studio or provide metadata via the metadata prop.

Metadata Prop Refused

If the engine cannot load the document you pass as metadata, init() rejects (the React player logs [MP4EPlayer] Init error) and the video plays as a plain video without interactivity or controls. Fix the document and pass it again — the player loads it as soon as the prop changes.

Schema Version Mismatch

Ensure metadata uses schema version 2.0. Older versions may not be compatible. Check metadata.schemaVersion.

Search card or chapters missing

An exported video carries a search card, and chapters from its analysis, only when the video was analysed and the card is switched on in the Studio. When a card is written, its title and description tags replace any the uploaded file had, and its chapters are added without changing any other track. If the uploaded file already has chapters of its own, those are kept and the analysis chapters are not added (the card still lists them). If the chapters themselves cannot be written (for example, malformed chapter data), the export still succeeds — with the card and tags, but without chapters. A file whose structure MP4E cannot read fails the export instead. Check the file with ffprobe; see Searching MP4E Videos for every placement.

Check the search card and chapters
# The search card (prints TAG:card={...}; nothing when the file has none)
ffprobe -v error -show_entries format_tags=card -of default=noprint_wrappers=1 video.mp4

# The chapters
ffprobe -v error -show_chapters -of compact=p=0 video.mp4

Object Tracking

Objects not appearing

Debug object visibility
1// Debug object visibility
2<MP4EPlayer
3 src="/video.mp4"
4 onEvent={(event, data) => {
5 if (event === 'playback:timeUpdate') {
6 const objects = playerRef.current?.getVisibleObjects();
7 console.log(`Frame ${data.frame}: ${objects?.length} objects visible`);
8 objects?.forEach(obj => {
9 console.log(` - ${obj.id}: ${obj.label} at (${obj.position.x}, ${obj.position.y})`);
10 });
11 }
12 if (event === 'object:visible') {
13 console.log('Object entered:', data.objectId, data);
14 }
15 if (event === 'object:hidden') {
16 console.log('Object exited:', data.objectId);
17 }
18 }}
19/>

Frame Number Mismatch

Check if the frame numbers in the timeline match the video's actual frame count. Use playerRef.current?.getTotalFrames() to verify.

Group Display Settings

Objects may be hidden by group settings. Check objectGroups[].displaySettings.showPolygon.

Coordinate System

Object coordinates are in pixels relative to the original video dimensions. Ensure your video element maintains the correct aspect ratio.

Overlays & Plugins

Overlays not showing

Debug overlay visibility
1// Debug overlay visibility
2<MP4EPlayer
3 src="/video.mp4"
4 onEvent={(event, data) => {
5 if (event === 'overlay:click') {
6 console.log('Overlay clicked:', data.overlayId, data.overlayType);
7 }
8 if (event === 'plugin:error') {
9 console.error('Plugin error:', data.pluginId, data.error);
10 }
11 }}
12/>
13
14// Check visibility conditions
15// In browser console:
16const metadata = playerRef.current?.getMetadata();
17const overlay = metadata.overlays.find(o => o.id === 'overlay_id');
18console.log('Visibility config:', overlay.visibility);
19console.log('Current time:', playerRef.current?.getCurrentTime());
20console.log('Variables:', playerRef.current?.getVariables());

Visibility Conditions

Check if visibility conditions are being met. Variable values and time ranges must match exactly for the overlay to show.

Attached Object Not Visible

Overlays attached to objects only show when the object is visible. Verify the attached object appears in the current frame.

Z-Index Conflicts

Overlays may be hidden behind other elements. Check zIndex values and layer ordering.

Performance

Sluggish performance

Performance optimizations
1// 1. Reduce timeline size for large videos
2// Use sparse timeline (only keyframes with changes)
3// Interpolate between keyframes in the player
4
5// 2. Lazy load metadata for sections
6const [loadedSections, setLoadedSections] = useState(['intro']);
7
8onEvent={(event, data) => {
9 if (event === 'playback:timeUpdate' && data.time > 60 && !loadedSections.includes('chapter1')) {
10 loadMetadataSection('chapter1');
11 setLoadedSections(prev => [...prev, 'chapter1']);
12 }
13}}
14
15// 3. Debounce variable updates
16import { debounce } from 'lodash';
17
18const debouncedUpdate = debounce((name, value) => {
19 playerRef.current?.setVariable(name, value);
20}, 100);
21
22// 4. Use CSS transforms instead of position changes
23// Good: transform: translate(10px, 20px)
24// Bad: left: 10px; top: 20px;
25
26// 5. Minimize overlay re-renders
27// Use React.memo for custom components
28// Avoid inline function props
Chrome DevTools Performance
Use Chrome DevTools Performance tab to identify bottlenecks. Look for long animation frames and excessive JavaScript execution.

Debugging Tools

Debug mode and console tools
1// Enable debug mode
2<MP4EPlayer
3 src="/video.mp4"
4 debug={true} // Enables visual debugging overlays
5/>
6
7// Debug mode shows:
8// - Object bounding boxes and IDs
9// - Overlay boundaries
10// - Frame number and time
11// - Variable values
12// - Rule triggers
13
14// Console commands (when debug mode is enabled)
15// Access player instance
16window.__mp4e_player
17
18// Get current state
19window.__mp4e_player.getState()
20
21// Inspect metadata
22window.__mp4e_player.getMetadata()
23
24// Manually trigger actions
25window.__mp4e_player.executeAction({ type: 'showNotification', message: 'Test' })
26
27// Check engine state
28window.__mp4e_player.getEngineState()

Still Having Issues?

If you can't find a solution, reach out for help: