Skip to content

VollaInc/expo-ivs-player

Repository files navigation

expo-ivs-player

An Expo module for Amazon Interactive Video Service (IVS) player, providing a complete React Native interface matching the official amazon-ivs-react-native-player.

Features

  • 🎥 Full IVS player functionality for iOS and Android
  • 📱 Picture-in-Picture support
  • 🎨 Multiple resize modes (aspectFit, aspectFill, aspectZoom)
  • 📊 Quality management and statistics
  • 🎮 Complete playback controls
  • 📝 Text and metadata cue support
  • ⚡ Low latency streaming support
  • 🔧 Configurable IVS SDK versions

Native SDK Documentation

This module wraps the native Amazon IVS Player SDKs:

Installation

npm install expo-ivs-player
# or
yarn add expo-ivs-player

iOS Setup

Add to your ios/Podfile or set environment variable to configure IVS SDK version:

ENV['IVS_PLAYER_VERSION'] = '~> 1.30.0'  # Optional, defaults to 1.30.0

Then run:

cd ios && pod install

iOS Requirements

  • iOS 15.1 or higher
  • Xcode 14.0 or higher

Android Setup

Add to your android/build.gradle to configure IVS SDK version:

ext {
    ivsPlayerVersion = "1.30.0"  // Optional, defaults to 1.30.0
}

Android Requirements

  • Android SDK 21 (Lollipop) or higher
  • Kotlin 1.6.0 or higher

Usage

Basic Example

import IVSPlayer, {
  IVSPlayerRef,
  PlayerState,
  LogLevel,
} from "expo-ivs-player";
import { useRef, useState } from "react";

function App() {
  const playerRef = useRef<IVSPlayerRef>(null);
  const [paused, setPaused] = useState(false);

  const handlePlayerStateChange = (state: PlayerState) => {
    console.log("Player state:", state);

    switch (state) {
      case PlayerState.Playing:
        console.log("Stream is playing");
        break;
      case PlayerState.Buffering:
        console.log("Stream is buffering");
        break;
      case PlayerState.Ended:
        console.log("Stream ended");
        break;
    }
  };

  const handleError = (error: string) => {
    console.error("Player error:", error);
  };

  return (
    <View style={{ flex: 1 }}>
      <IVSPlayer
        ref={playerRef}
        streamUrl="https://your-stream-url.m3u8"
        paused={paused}
        muted={false}
        autoplay={true}
        resizeMode="aspectFit"
        onPlayerStateChange={handlePlayerStateChange}
        onError={handleError}
        style={{ width: "100%", height: 300 }}
      />

      <Button
        title={paused ? "Play" : "Pause"}
        onPress={() => setPaused(!paused)}
      />
    </View>
  );
}

Advanced Example with Quality Selection

import IVSPlayer, { IVSPlayerRef, Quality } from "expo-ivs-player";

function AdvancedPlayer() {
  const playerRef = useRef<IVSPlayerRef>(null);
  const [qualities, setQualities] = useState<Quality[]>([]);
  const [currentQuality, setCurrentQuality] = useState<Quality | null>(null);

  const handleDataReady = (data: PlayerData) => {
    setQualities(data.qualities);
    console.log("Available qualities:", data.qualities);
    console.log("Player version:", data.version);
    console.log("Session ID:", data.sessionId);
  };

  const handleQualityChange = (quality: Quality | null) => {
    setCurrentQuality(quality);
    console.log("Quality changed to:", quality?.name);
  };

  const selectQuality = (quality: Quality) => {
    // Manual quality selection will be implemented in ref methods
    console.log("Selected quality:", quality.name);
  };

  return (
    <View style={{ flex: 1 }}>
      <IVSPlayer
        ref={playerRef}
        streamUrl="https://your-stream-url.m3u8"
        autoplay={true}
        autoQualityMode={true}
        onData={handleDataReady}
        onQualityChange={handleQualityChange}
        style={{ width: "100%", height: 300 }}
      />

      {qualities.map((quality) => (
        <Button
          key={quality.name}
          title={`${quality.name} (${quality.bitrate}bps)`}
          onPress={() => selectQuality(quality)}
        />
      ))}
    </View>
  );
}

API Reference

Props

Playback Control Props

Prop Type Default Description Native Mapping
streamUrl string - The URL of the stream to play iOS: IVSPlayer.load(URL), Android: Player.load(Uri)
paused boolean false Controls playback state iOS: IVSPlayer.state, Android: Player.State
muted boolean false Controls audio muting iOS: IVSPlayer.muted, Android: Player.isMuted
volume number 1.0 Volume level (0.0 to 1.0) iOS: IVSPlayer.volume, Android: Player.volume
playbackRate number 1.0 Playback speed (0.5 to 2.0) iOS: IVSPlayer.rate, Android: Player.playbackRate
loop boolean false Enable loop playback Custom implementation
autoplay boolean false Autoplay when ready iOS: IVSPlayer.autoplay, Android: Custom

Display Props

Prop Type Default Description Native Mapping
resizeMode ResizeMode 'aspectFit' Video scaling mode iOS: AVLayerVideoGravity, Android: ResizeMode
showControls boolean false Show native controls iOS: Custom, Android: PlayerView.setControlsEnabled
pipEnabled boolean false Enable Picture-in-Picture iOS: AVPictureInPictureController, Android: PictureInPictureParams

Quality & Performance Props

Prop Type Default Description Native Mapping
autoQualityMode boolean true Auto quality switching iOS: IVSPlayer.autoQualityMode, Android: Auto quality
quality Quality null Manual quality selection iOS: IVSPlayer.quality, Android: Player.quality
autoMaxQuality Quality null Max quality for auto mode iOS: IVSPlayer.autoMaxQuality, Android: Custom
maxBitrate number 0 Max bitrate (0 = unlimited) iOS: IVSPlayer.maxBitrate, Android: Custom
initialBufferDuration number 0 Initial buffer in seconds iOS: IVSPlayer.initialBufferDuration, Android: Custom

Live Streaming Props

Prop Type Default Description Native Mapping
liveLowLatency boolean true Enable low latency mode iOS: IVSPlayer.liveLowLatencyEnabled, Android: Custom
rebufferToLive boolean false Auto rebuffer to live edge iOS: IVSPlayer.rebufferToLive(), Android: Custom

Debug Props

Prop Type Default Description Native Mapping
logLevel LogLevel 'ERROR' Logging level iOS: IVSPlayer.loggingLevel, Android: Logging config
progressInterval number 1.0 Progress update interval (seconds) Custom timer implementation
breakpoints number[] [] Time points for events Custom implementation

Event Callbacks

Playback Events

Event Parameters Description Native Mapping
onPlayerStateChange (state: PlayerState) Player state changed iOS: IVSPlayer.state, Android: Player.Listener.onStateChanged
onSeek (position: number) Seek completed iOS: seekCompleted, Android: onSeekCompleted
onProgress (progress: number) Playback progress Custom timer
onTimePoint (position: number) Breakpoint reached Custom
onDurationChange (duration: number | null) Duration changed iOS: IVSPlayer.duration, Android: onDurationChanged
onLoad (duration: number | null) Stream loaded iOS: Ready state, Android: READY state
onLoadStart () Loading started Custom
onRebuffering () Rebuffering started iOS: Buffering state, Android: onRebuffering

Quality & Statistics Events

Event Parameters Description Native Mapping
onQualityChange (quality: Quality | null) Quality changed iOS: IVSPlayer.quality, Android: onQualityChanged
onData (data: PlayerData) Player data ready Native properties
onVideoStatistics (data: VideoData) Video stats updated iOS: IVSPlayer.statistics, Android: Stats

Live Streaming Events

Event Parameters Description Native Mapping
onLiveLatencyChange (latency: number) Latency changed iOS: IVSPlayer.liveLatency, Android: Live latency

Cue Events

Event Parameters Description Native Mapping
onTextCue (cue: TextCue) Text cue received iOS: didOutputCue, Android: onCue(TextCue)
onTextMetadataCue (cue: TextMetadataCue) Metadata cue received iOS: didOutputCue, Android: onCue(TextMetadataCue)

System Events

Event Parameters Description Native Mapping
onError (error: string) Error occurred iOS: IVSPlayer.error, Android: onError
onPipChange (isActive: boolean) PiP state changed iOS: AVPictureInPictureControllerDelegate, Android: isInPictureInPictureMode

Methods (via ref)

const playerRef = useRef<IVSPlayerRef>(null);

// Playback control
playerRef.current?.play();
playerRef.current?.pause();
playerRef.current?.seekTo(30); // Seek to 30 seconds

// Source management
const source = playerRef.current?.preload(url);
playerRef.current?.loadSource(source);
playerRef.current?.releaseSource(source);

// Picture-in-Picture
playerRef.current?.togglePip();

// CORS configuration
playerRef.current?.setOrigin("https://example.com");

Type Definitions

PlayerState

enum PlayerState {
  Idle = "Idle", // Player is idle, no stream loaded
  Ready = "Ready", // Stream is loaded and ready
  Buffering = "Buffering", // Stream is buffering
  Playing = "Playing", // Stream is playing
  Ended = "Ended", // Stream has ended
}

ResizeMode

type ResizeMode =
  | "aspectFill" // Scale to fill view, may crop
  | "aspectFit" // Scale to fit view, may letterbox
  | "aspectZoom"; // Zoom to fill view

LogLevel

enum LogLevel {
  IVSLogLevelDebug = "IVSLogLevelDebug",
  IVSLogLevelInfo = "IVSLogLevelInfo",
  IVSLogLevelWarning = "IVSLogLevelWarning",
  IVSLogLevelError = "IVSLogLevelError",
}

Quality

interface Quality {
  name: string; // Quality name (e.g., "720p60")
  codecs: string; // Codec information
  bitrate: number; // Bitrate in bps
  framerate: number; // Frames per second
  width: number; // Video width
  height: number; // Video height
}

PlayerData

interface PlayerData {
  qualities: Quality[]; // Available qualities
  version: string; // IVS SDK version
  sessionId: string; // Session identifier
}

VideoData

interface VideoData {
  width: number; // Video width
  height: number; // Video height
  bitrate?: number; // Current bitrate
  framerate?: number; // Current framerate
  droppedFrames?: number; // Dropped frame count
}

TextCue

interface TextCue {
  type: "text";
  text: string;
  line?: number;
  size?: number;
  position?: number;
  startTime?: number;
  endTime?: number;
}

TextMetadataCue

interface TextMetadataCue {
  type: "metadata";
  text: string;
  description?: string;
  startTime?: number;
  endTime?: number;
}

Platform Support

Platform Supported Minimum Version Notes
iOS iOS 15.1+ Full support including PiP
Android Android SDK 21+ Full support including PiP
Web ⚠️ - Basic iframe fallback (limited features)

Troubleshooting

iOS Build Issues

Pod Installation Fails

# Clean and reinstall
cd ios
rm -rf Pods Podfile.lock
pod install --repo-update

Missing IVS Framework

  • Ensure your iOS deployment target is 15.1 or higher in Xcode
  • Verify use_frameworks! :linkage => :static is in your Podfile if needed

Android Build Issues

Kotlin Version Conflicts

// In android/build.gradle
ext {
    kotlinVersion = "1.6.0" // or higher
}

IVS SDK Not Found

// In android/build.gradle
repositories {
    maven { url "https://amazon.bintray.com/ivs" }
}

Player Issues

Stream Not Loading

  1. Check stream URL is valid and accessible
  2. Verify network permissions in app manifest/Info.plist
  3. Check console for specific error messages
  4. Ensure the stream is active (IVS streams stop when not broadcasting)

Poor Performance

  1. Enable autoQualityMode for automatic quality adjustment
  2. Set appropriate maxBitrate for device capabilities
  3. Use liveLowLatency only when necessary
  4. Check device performance capabilities

PiP Not Working

iOS:

  • Add UIBackgroundModes with audio in Info.plist
  • Ensure pipEnabled prop is set to true

Android:

  • Add PiP permission in AndroidManifest.xml
  • Ensure device supports PiP (Android 8.0+)

Example App

See the example directory for a complete example app demonstrating:

  • Basic playback controls
  • Quality selection
  • Picture-in-Picture
  • Live streaming features
  • Error handling
  • Statistics display

To run the example:

cd example
npm install
# iOS
cd ios && pod install
npm run ios
# Android
npm run android

Migration from amazon-ivs-react-native-player

This module provides a compatible API with the official Amazon IVS React Native player. To migrate:

  1. Replace the import:
// Before
import IVSPlayer from "amazon-ivs-react-native-player";

// After
import IVSPlayer from "expo-ivs-player";
  1. All props and methods remain the same
  2. Event callbacks maintain the same signatures
  3. Type definitions are compatible

Contributing

Contributions are welcome! Please see our contributing guide for details.

License

MIT

Support

For issues and feature requests, please use the GitHub issues page.

For Amazon IVS specific questions, refer to:

Credits

This module provides an Expo-compatible interface matching the amazon-ivs-react-native-player API.

About

Ivs Player on Expo wrapper

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages