Search by

pushinbr / pam-native-video

DavidWilliamBalbino

Adaptive streaming, subtitles and native Media3/AVPlayer playback for PAM Native.

Package info

github.com/push-in/pam-native-video

Language:Swift

Type:pam-native-plugin

pkg:composer/pushinbr/pam-native-video

Statistics

Installs: 216

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.4.0 2026-10-04 22:25 UTC

This package is auto-updated.

Last update: 2026-10-06 03:56:28 UTC


README

PAM Native Video

Adaptive streaming and native playback for serious media apps.

Play HLS on iOS, HLS/DASH on Android, subtitles, tracks, DRM-ready sources, and picture-in-picture while decode and rendering stay native.

Latest version CI PHP Android iOS

Documentation · Quick start · What you can build · PAM ecosystem · Issues

Why PAM Native Video

Play HLS on iOS, HLS/DASH on Android, subtitles, tracks, DRM-ready sources, and picture-in-picture while decode and rendering stay native. The public API is strictly typed for PHP 8.5; expensive or frame-sensitive work stays in Rust or the platform SDK instead of crossing the application boundary every frame.

Best for A focused capability you can add to any PAM Native application
Native path Android Media3 · AVPlayer
Application model Composer package + generated native integration
Design rule Independent module; no feed, vertical, or application template bundled

What you can build

  • Streaming and IPTV applications
  • Social and editorial video
  • Offline-aware playback with native controls and subtitles

Quick start

Already have a PAM Native project? Add only this capability:

pam composer require pushinbr/pam-native-video
pam doctor --fix

New to PAM? Follow the five-minute PAM Native setup once, then return here. Your application stays a normal Composer project with a committed lockfile.

See it in action

This package is a horizontal playback primitive. It does not install a feed, social network, or streaming application template.

Adaptive HLS and local video playback through Android Media3 and Apple AVPlayer; Android also supports DASH. Decoder, buffering, controls and progress timing remain native rather than crossing the PHP bridge per frame.

pam composer require pushinbr/pam-native-video
pam doctor --fix
use Pam\Native\Video\VideoEventKind;
use Pam\Native\Video\VideoPlayer;
use Pam\Native\Video\VideoResizeMode;

return VideoPlayer::make('https://cdn.example.com/master.m3u8')
    ->autoPlay()
    ->controls()
    ->resizeMode(VideoResizeMode::Cover)
    ->onEvent(function (VideoEventKind $kind, array $event): void {
        // Progress: $event['positionMillis'], ['durationMillis'], ['bufferedMillis'].
    });

Protected playback supports Widevine and ClearKey on Android and FairPlay on iOS. An incompatible DRM scheme produces a native playback error instead of silently playing without DRM. License exchange runs inside the native player; credentials should be short-lived.

use Pam\Native\Video\VideoDrmConfiguration;
use Pam\Native\Video\VideoDrmScheme;
use Pam\Native\Video\VideoPlayer;

return VideoPlayer::make('https://cdn.example.com/movie/master.m3u8')
    ->drm(new VideoDrmConfiguration(
        scheme: VideoDrmScheme::FairPlay,
        licenseUrl: 'https://license.example.com/fps',
        authorization: 'Bearer '.$shortLivedToken,
        contentId: 'movie-42',
        certificateUrl: 'https://license.example.com/fairplay.cer',
    ))
    ->subtitle('https://cdn.example.com/subtitles/pt-BR.vtt')
    ->preferredForwardBuffer(15_000)
    ->autoPlay();

Features include adaptive HLS playback, embedded subtitle/audio tracks, native controls, autoplay, looping, mute/volume, deterministic seek commands, configurable progress events and sandboxed local files. Android also supports DASH. External WebVTT, SRT and TTML subtitles are supported on both platforms; iOS loads at most 2 MiB and displays them in the AVKit content overlay. Embedded subtitles retain the platform's native track selection. Android dependencies are pinned to Media3 1.9.3; iOS uses AVFoundation/AVKit.

On macOS, run the focused subtitle, time and sandbox checks with swiftc ios/Sources/ExternalSubtitles.swift ios/Sources/VideoSafety.swift tests/ios-subtitles/main.swift -o /tmp/pam-video-ios-check && /tmp/pam-video-ios-check.

Platform support: Android API 26+, iOS 15+, PAM Native 0.8–1.x.

What installation does

pam composer require pushinbr/pam-native-video installs the package through the project's normal composer.json and composer.lock. Run pam doctor --fix afterward to validate the environment and regenerate native integration when required. The package is a PAM Native plugin with one native view (video.player); nothing is added to pam-native.json.

Use pam packages to inspect direct installed Composer dependencies and pam composer remove pushinbr/pam-native-video to uninstall the capability.

  • Android: no permissions besides network access. Dependencies: androidx.media3:media3-exoplayer, -exoplayer-dash, -exoplayer-hls and -ui 1.9.3. When pam-native-media, pam-native-audio or pam-native-media-editor (Media3 1.10.1) are installed too, Gradle resolves every Media3 artifact to the newest requested version.
  • iOS: frameworks AVFoundation and AVKit; no Info.plist keys. FairPlay needs a certificate and license server of your own.

When to use it

The PAM Native core already ships <MediaPlayer> (Pam\Native\UI\MediaPlayer) for feed, story and chat media; Zé Chat plays its gallery, story and editor videos with it. Add this package when you need what the core player does not do: DRM (Widevine, ClearKey, FairPlay), DASH on Android, external WebVTT/SRT/ TTML subtitles, bitrate caps, forward-buffer tuning and native transport controls.

API reference

All classes live in Pam\Native\Video.

VideoPlayer (Renderable, immutable)

Method Description
make(string $source) HTTPS URL (HLS, DASH on Android, progressive) or a relative sandbox path.
autoPlay(bool = true), controls(bool = true) (default on), loop(bool = true), muted(bool = true), volume(float) (0–1) Playback.
seekTo(int $milliseconds) Seek command; a new value seeks once (keep it in state, do not recompute it every render).
resizeMode(VideoResizeMode) Contain (default), Cover, Fill.
progressEvery(int $milliseconds) Progress event interval, 100–10000 ms (default 500).
playbackRate(float) 0.25–4.
preferredPeakBitRate(int $bitsPerSecond), preferredForwardBuffer(int $milliseconds) (0–120000) Adaptive streaming hints.
subtitle(string $source) External WebVTT, SRT or TTML (HTTPS or sandbox path).
drm(VideoDrmConfiguration) Protected playback.
onEvent(Closure(VideoEventKind, array) $handler) Native events.
toElement(): Element A CustomView of kind video.player; style it to give it a size.

Events

VideoEventKind Payload keys
State = 1 state (VideoPlaybackState value)
Progress = 2 positionMillis, durationMillis, bufferedMillis
Error = 3 state (Failed), message
Tracks = 4 Reserved; not emitted by 0.4

VideoPlaybackState: Idle = 1, Buffering = 2, Ready = 3, Ended = 4, Failed = 5. Convert with VideoPlaybackState::tryFrom((int) $event['state']).

VideoDrmConfiguration (readonly)

(VideoDrmScheme $scheme, string $licenseUrl, string $authorization = '', string $contentId = '', string $certificateUrl = '', bool $multiSession = false); properties(). License and certificate URLs must be HTTPS; FairPlay needs contentId and certificateUrl; authorization ≤ 8192 bytes, contentId ≤ 2048. VideoDrmScheme: Widevine = 1, FairPlay = 2, ClearKey = 3 (Widevine/ClearKey on Android, FairPlay on iOS).

Errors

InvalidArgumentException for non-HTTPS URLs, empty or oversized sources and DRM configurations that break the rules above. Playback problems (network, codec, DRM, unsupported scheme on a platform) arrive as Error events with a message; a repeated error for the same request is reported once.

Production checklist

  • Prefer adaptive HLS for both platforms; use DASH only for Android.
  • Keep progress intervals coarse enough for the product experience.
  • Pause or release playback when the owning screen loses visibility.
  • Run pam doctor, pam test, and a signed release build on every supported platform.
  • Exercise denial, cancellation, backgrounding, process restart, and offline behavior before release.

Troubleshooting

  • Remote playback fails: verify HTTPS, codec, manifest, and segment accessibility.
  • Seek appears ignored: issue it as an intentional state revision, not every render.
  • Subtitles are absent: inspect the embedded track, or check the external subtitle URL, format and 2 MiB iOS size limit.
  • Native integration is stale: run pam doctor --fix, rebuild the native host, and inspect the first reported diagnostic.

Compatibility and support

pushinbr/pam-native-video pushinbr/pam-native Android iOS
0.4.x >=0.8.0 <2.0.0 (tested with 1.14.x) API 26+, Media3 1.9.3 15+, external subtitles
0.3.x >=0.8.0 <1.0.0 API 26+ 15+, no external subtitles

This package targets PAM Native 0.8–1.x, Android API 26+, and iOS 15+ unless a platform-specific section above states a stricter requirement. Platform SDKs, credentials, entitlements, physical hardware, and store configuration remain application responsibilities.

Security vulnerabilities should be reported through the repository security policy or GitHub private vulnerability reporting, not a public issue.