Audio/video playback for NativePHP Mobile: a shared background player driven from PHP, a full-screen system player, and an inline <video-player> element for native (Edge) views.
The plugin provides three ways to play media:
- Shared player —
MediaPlayer::play()plays audio or video sources app-wide (AVPlayer on iOS, MediaPlayer on Android) with pause/resume/seek/volume control from PHP. - Full-screen presentation —
MediaPlayer::present()opens the system player UI (AVPlayerViewController on iOS, a dedicated full-screen activity on Android); the user dismisses it natively. - Inline
<video-player>element — a video surface for native UI views, rendered as SwiftUIVideoPlayer(AVKit) on iOS and aVideoViewinside Compose on Android.
composer require nativephp/mobile-media-playerDon't forget to register the plugin:
php artisan native:plugin:register nativephp/mobile-media-playeruse NativePHP\MediaPlayer\Facades\MediaPlayer;
// Play a bundled file, storage path, or URL
MediaPlayer::play(storage_path('app/theme.mp3'));
// With options
MediaPlayer::play('https://example.com/stream.mp3', [
'loop' => true,
'volume' => 0.5,
]);
// Transport controls
MediaPlayer::pause();
MediaPlayer::resume();
MediaPlayer::seek(42.5); // seconds
MediaPlayer::setVolume(0.8); // 0.0 – 1.0
MediaPlayer::stop(); // stops and releases the player
// Poll playback state
$status = MediaPlayer::getStatus();
// ['state' => 'playing', 'position' => 12.3, 'duration' => 180.0, 'source' => '...']play() and present() return false when the source can't be started (or when
running outside the native runtime).
MediaPlayer::present(storage_path('app/videos/intro.mp4'));<video-player :src="$video['path']" controls class="w-full aspect-video rounded-2xl"/>Attributes:
| Attribute | Default | Description |
|---|---|---|
src |
— | File path or URL |
controls |
true |
Show native transport chrome |
autoplay |
false |
Start playback on mount |
loop |
false |
Restart when playback ends |
muted |
false |
Start muted |
Sizing follows the element's layout props (width/height/aspect classes), like Image.
With controls=false you get a bare video surface — overlay your own Element UI
and drive playback through the MediaPlayer facade:
<stack class="w-full aspect-video">
<video-player :src="$src" :controls="false" autoplay muted class="w-full h-full"/>
<button @press="togglePlayback" icon="pause.fill" class="absolute bottom-2 right-2"/>
</stack>use NativePHP\MediaPlayer\Elements\VideoPlayer;
VideoPlayer::make($path)
->controls(false)
->autoplay()
->loop()
->muted();Fired when the shared player reaches the end of the source.
Payload: string $source
use Native\Mobile\Attributes\OnNative;
use NativePHP\MediaPlayer\Events\PlaybackEnded;
#[OnNative(PlaybackEnded::class)]
public function handlePlaybackEnded(string $source)
{
$this->playNext();
}Fired when the shared player fails to load or play a source.
Payload: string $source, string $message
use Native\Mobile\Attributes\OnNative;
use NativePHP\MediaPlayer\Events\PlaybackError;
#[OnNative(PlaybackError::class)]
public function handlePlaybackError(string $source, string $message)
{
$this->status = "Playback failed: {$message}";
}MediaPlayer::getStatus()['state'] is one of: idle, playing, paused.
- iOS: 16.0+ (AVPlayer / AVKit)
- Android: API 26+ (MediaPlayer / Media3 UI)
- One shared player: calling
play()replaces whatever is currently playing. - Remote URLs require network access; local paths must be readable by the app
(e.g.
storage_path()or bundled assets). - No runtime permissions are required.