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)
- Enable PiP in app config with the
expo-videoplugin (supportsPictureInPicture) as described in the Expo Video docs. - Enable
@moviie/player-expowith{ "pictureInPicture": true }so iOS receivesUIBackgroundModes→picture-in-pictureandaudio, and Android getssupportsPictureInPictureandresizeableActivityon the main activity (applied at prebuild). - Spread
videoPresentationfromuseMoviiePlayerontoMoviieVideo. Presentation defaults followplayback.controls(showPipfor PiP; the seek/progress booleans for linear playback); optionalpictureInPicture/pictureInPictureAutoStarton the hook orMoviieVideo, orVideoViewPiP props onMoviieVideo, 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.showSpeedisfalse(e.g. a VSL-style preset), viewers cannot change the speed: the rate stays locked at the configured value. - When
playback.controls.showSpeedistrue, 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 iOSUIBackgroundModes→audiowhentrue.pictureInPicture: adds iOSUIBackgroundModes→picture-in-pictureandaudio; sets Androidandroid:supportsPictureInPictureandandroid:resizeableActivityon the main activity.
Configure expo-video separately for supportsPictureInPicture / supportsBackgroundPlayback and rebuild native projects after changing plugins.