Handling common player errors
This document provides solutions and best practices for addressing common errors encountered during video playback using the rn-qp-nxg-player library. These errors include issues related to live streaming, DRM, session expiry, and more. By following the guidelines here, you can ensure a smoother playback experience.
Mitigating Player Errors
BehindLiveWindowException (Error: 40020d)
The Player throws a BehindLiveWindowException when the playback strays so far away from live edge that it falls behind the available live window. The playback can fall behind because of continuous buffering or pausing of a live stream. This exception can be prevented by turning on the live monitor via PlaybackProperties and passing a LiveStreamMonitorConfiguration, if needed.
Live stream monitoring is disabled by default.
| Property Name | Type | Default Value | Description |
|---|---|---|---|
| liveStreamMonitorConfiguration | LiveStreamMonitorConfiguration | monitoringTimeIntervalMs = 10000 liveEdgePositionThreshold = 20 currentWindowBufferedPositionThreshold = 40 | The live stream configuration to be employed. |
| monitorLiveStream | Boolean | false | Represents whether to monitor live stream position or not. |
let liveStreamMonitorConfig: LiveStreamMonitorConfiguration = {
monitoringTimeIntervalMs: 3000,
currentWindowBufferedPositionThreshold: 40
}
}
DECODER_INIT_FAILURE (Error: 400208)
One possible cause of this error is when the app attempts to play DRM streams exceeding the device's supported limit. To address this, a new parameter, shouldCleanupPreviousPlayers, has been added to PlayerConfig. This ensures that any existing player is stopped before creating a new one.
let playerConfig: PlayerConfig = {
...
shouldCleanupPreviousPlayers: true
...
}
let player = await createPlayer(playerConfig)
Handling Player Error
Here is step-by-step guide to handle playback errors
export interface PlatformError {
errorCode: number;
errorDescription: string;
contextDescription?: string;
httpStatusCode?: number;
internalError?: PlatformError;
readonly componentErrorCode: number;
readonly hexErrorCode: string;
doesBelongToCategory:(category: number) => boolean;
toString: () => string;
}
When the player encounters a failure, we report the playback error using the `onError` callback:
onError(error: PlatformError): void {
...
// Handle error
},
SSAI Session Expiry
In SSAI playbacks, ads are added dynamically from the server, so the server needs to keep a session for each playback to handle the ads properly. It's important for the server to end sessions when playback finishes or if the user takes action. Also, the server usually cleans up idle sessions after a while. But in iOS apps, playback can pause for a long time, causing sessions to be removed from the server. When users come back to the app, errors can occur because the player tries to resume the previous playback. To fix this, ad-serving companies suggest apps close the playback session before the app becomes idle. However, just relying on the app's background and foreground states isn't enough because some app features like Picture-in-Picture mode and Airplay support need special consideration. To prevent session problems, the app needs to handle these cases properly.
Background
App become background
- Open the iOS/tvOS app.
- Play any SSAI stream.
- Pause the playback.
- Put the app on a background.
- Open the app after the SSAI session keep-alive time has elapsed, causing the player to throw a session expiry error.
Solution
Deinitialize the player instance when the app is backgrounded. This prevents the player from encountering errors when it becomes active after a session expiry.
Implementation
import { AppState, AppStateStatus } from 'react-native';
import React, { useRef, useEffect } from 'react';
const appState = useRef<AppStateStatus>(AppState.currentState);
useEffect(() => {
const handleAppStateChange = async (nextAppState: AppStateStatus) => {
if (nextAppState === "background") {
appState.current = nextAppState;
appState.current = nextAppState;
}
};
const subscription = AppState.addEventListener("change", handleAppStateChange);
return () => {
subscription.remove();
};
}, []);
Picture-in-Picture
Scenario
- Open the iOS app
- Play any SSAI-enabled stream
- Put the app in the background; the stream should resume playing in PiP window
- Close the pip window
- Open the app after the SSAI session elapses, causing the player to throw a session expiry error.
Solution
Deinitialize the player instance when the PiP window is closed. This prevents the player from encountering errors when it becomes active after a session expiry.
Implementation
let playerListener = {
async onPictureInPictureStopped(): Promise<void> {
if (appState.current === "background") {…}
if (appState.current === "background") {
// TODO: Deinitialize the player
}
},
};
Airplay
Scenario
- Open the iOS App.
- Play any Server-Side Ad Insertion (SSAI) stream.
- Airplay the playback on an external device.
- Put the iOS app in the background and close the playback on the external device using a remote.
- Open the app after the SSAI session keep-alive time has elapsed, causing the player to throw a session expiry error.
Solution
Deinitialize the player instance when the app is backgrounded and the Airplay device quits the playback. This prevents the player from encountering errors when it becomes active after a session expiry.
Implementation
let playerListener = {
async onAudiorouteChanged(routeChange: string, fromPort: string, toPort: string): Promise<void> {
if (fromPort === "AirPlay" && toPort !== "AirPlay" && appState.current === "background") {
console.log("AirPlay stopped in background, stopping player...");
// TODO: Deinitialize the player
}
},
};
HTTP Failures
Playback may pause for an extended period, causing sessions to be removed from the server. When users return, errors can occur as the player tries to resume the previous session
onError(error: PlatformError): void {
// Check if httpStatusCode is available in the error
if (error.httpStatusCode) {
switch (error.httpStatusCode) {
case 410:
}
}
}
Note SSAI session expiry varies for different SSAI vendors and environments. Picture-in-Picture and Airplay not applicable for tvOS