Docs

Native playback features

Picture-in-Picture, background audio, lock screen controls, resume position, and linear-playback defaults on Expo.

Native playback features

Playback metadata from getPlayback reflects dashboard / embed configuration (playback.controls, branding, etc.). Native wiring also uses the @moviie/player-expo config plugin, useMoviiePlayer flags that only exist on the device, videoPresentation, and expo-video's own plugin where required.

Dashboard as source of truth and explicit overrides

By default, what is configured in the Moviie dashboard (exposed via the playback API, e.g. playback.controls) is the source of truth: autoplay, PiP, remember position, control visibility in the player chrome, etc.

The integrator can override this behaviour explicitly through the player's public APIs: optional props on useMoviiePlayer (e.g. autoplay, pictureInPicture, rememberPosition), on MoviieVideo, or via VideoView native props. Omitting an optional prop preserves the dashboard value.

App-only native options (backgroundPlayback, lockScreenNowPlaying, config plugin options) do not come from the dashboard; they are application-level choices with their own defaults when omitted.

Picture-in-Picture (PiP)

  1. Enable PiP in app config with the expo-video plugin (supportsPictureInPicture) as described in the Expo Video docs.
  2. Enable @moviie/player-expo with { "pictureInPicture": true } so iOS receives UIBackgroundModespicture-in-picture and audio, and Android gets supportsPictureInPicture and resizeableActivity on the main activity (applied at prebuild).
  3. Spread videoPresentation from useMoviiePlayer onto MoviieVideo. Presentation defaults follow playback.controls (showPip for PiP; the seek/progress booleans for linear playback); optional pictureInPicture / pictureInPictureAutoStart on the hook or MoviieVideo, or VideoView PiP props on MoviieVideo, apply explicit overrides (see section above).

Background audio & lock screen

Pass backgroundPlayback: true to useMoviiePlayer to set VideoPlayer.staysActiveInBackground.

Pass lockScreenNowPlaying: true to set VideoPlayer.showNowPlayingNotification. These flags are native app choices (not embed controls); each defaults to false when omitted.

Resume position

Persistence follows playback.controls.rememberPosition unless rememberPosition on useMoviiePlayer forces true / false. When enabled, currentTime is stored in SecureStore (debounced while playing, flushed on pause) under MOVIIE_REMEMBER_POSITION_STORAGE_PREFIX + embedId; progress clears on playToEnd.

Player chrome (native)

By default, MoviieVideo renders the Moviie custom chrome over expo-video (omit native or pass native={false}). Pass playback from useMoviiePlayer so controls, branding, and layout match the embed contract.

Set native={true} to use the platform VideoView chrome instead (nativeControls defaults follow the linear-playback rules below).

Smart Progress (Moviie skin)

When the playback API sets smartProgressEnabled: true (same eligibility rules as the web embed: VSL-style preset and known duration), the Moviie skin draws a thin accent-coloured bar at the bottom of the video. Mapped progress follows the web curve; the bar stays hidden while muted until the viewer has unmuted or raised volume (then it stays visible if muted again). Scrubbing on the timeline updates the bar without forcing monotonic progress during the drag.

Linear playback

Control behavior is fully described by playback.controls — the server resolves the AI/creator-curated control list into booleans (the legacy profile field was retired). When the resolved controls expose no scrub or skip affordance (showProgress, seekBackwardEnabled, and seekForwardEnabled all false — e.g. a VSL-style preset), playback is linear: with native={true}, MoviieVideo defaults nativeControls to false and sets requiresLinearPlayback on VideoView, matching the web embed where those controls simply never render.

Playback rate

The dashboard accepts an initial playback rate between 1.0 and 1.5 (choices: 1, 1.1, 1.25, 1.5). The playback API exposes it as playback.controls.playbackRate and the web embed applies it automatically once the player is ready.

  • When playback.controls.showSpeed is false (e.g. a VSL-style preset), viewers cannot change the speed: the rate stays locked at the configured value.
  • When playback.controls.showSpeed is true, the value is the initial rate and viewers can still change speed.

On Expo, read playback.controls.playbackRate from getPlayback and set it on the VideoPlayer after the player is ready (e.g. on the first playbackStatusUpdate). Reapply on resume if the platform resets it.

Config plugin (@moviie/player-expo)

[
  "@moviie/player-expo",
  { "backgroundPlayback": true, "pictureInPicture": true }
]
  • backgroundPlayback: adds iOS UIBackgroundModesaudio when true.
  • pictureInPicture: adds iOS UIBackgroundModespicture-in-picture and audio; sets Android android:supportsPictureInPicture and android:resizeableActivity on the main activity.

Configure expo-video separately for supportsPictureInPicture / supportsBackgroundPlayback and rebuild native projects after changing plugins.

On this page