Code Monkey home page Code Monkey logo

react-native-theoplayer's Introduction

React Native THEOplayer

License

This projects falls under the license as defined in https://github.com/THEOplayer/license-and-disclaimer.

Table of Contents

  1. Overview
  2. Prerequisites
  3. How to use these guides
  4. Features
  5. Available connectors
  6. Getting Started

Overview

The react-native-theoplayer package provides a THEOplayerView component supporting video playback on the following platforms:

  • Android, Android TV & FireTV
  • iOS & tvOS (Apple TV)
  • HTML5, Tizen & webOS (web, mobile web, smart TVs, set-top boxes and gaming consoles).

This document covers the creation of a minimal app including a THEOplayerView component, and an overview of the accompanying example app with a user interface provided by the @theoplayer/react-native-ui package.

It also gives a description of the properties of the THEOplayerView component, and a list of features and known limitations.

Prerequisites

For each platform, a dependency to the corresponding THEOplayer SDK is included through a dependency manager:

  • Gradle & Maven for Android
  • Cocoapods for iOS
  • npm for Web

In order to use one of these THEOplayer SDKs, it is necessary to obtain a valid THEOplayer license for that specific platform, i.e. HTML5, Android, and/or iOS. You can sign up for a THEOplayer SDK license through our portal.

If you have no previous experience in React Native, we encourage you to first explore the React Native Documentation, as it gives you a good start on one of the most popular app development frameworks.

How to use these guides

These are guides on how to use the THEOplayer React Native SDK in your React Native project(s) and can be used linearly or by searching the specific section. It is recommended that you have a basic understanding of how React Native works to speed up the way of working with THEOplayer React Native SDK.

Features

Depending on the platform on which the application is deployed, a different set of features is available.

If a feature missing, additional help is needed, or you need to extend the package, please reach out to us for support.

Feature Android, Android TV, Fire TV Web iOS, tvOS
Streaming MPEG-DASH (fmp4, CMAF), HLS (TS, CMAF), Progressive MP4, MP3 HLS (TS, CMAF), Progressive MP4, MP3
Content Protection Widevine Widevine, PlayReady, Fairplay Fairplay
DRM Connectors BuyDRM, EZDRM, Anvato, Titanium, Axinom, Irdeto, VuDRM, Comcast, Verimatrix, Azure, …
Analytics Connectors Adobe, Agama, Comscore, Conviva, Mux, Nielsen, Youbora
Subtitles & Closed Captions CEA-608/708, SRT, TTML, WebVTT
Metadata Event stream, emsg, ID3, EXT-X-DATERANGE, EXT-X-PROGRAM-DATE-TIME
Advertising Integration Google IMA, Google DAI
Cast Integration Chromecast Chromecast, Airplay
Presentation Mode Inline, Picture-in-Picture, Fullscreen
Audio Control Management Audio focus & Audio-Becoming-Noisy mgmt (Audio control management by platform)
Advanced APIs Background playback,
Media Session,
Media Cache (offline playback)
Background playback,
NowPlaying,
Media Cache (iOS only)
User Interface
@theoplayer/react-native-ui
Basic playback, media & text track selection, progress bar, live & vod, preview thumbnails, customisable & extensible

Available connectors

The react-native-theoplayer package can be combined with any number of connectors to provide extra functionality. Currently, the following connectors are available:

Connector npm package Source
Adobe analytics, implementing the Media Collections API %40theoplayer/react-native-analytics-adobe Adobe
Agama analytics %40theoplayer/react-native-analytics-agama Agama
Comscore analytics %40theoplayer/react-native-analytics-comscore Comscore
Conviva analytics %40theoplayer/react-native-analytics-conviva Conviva
Mux analytics %40theoplayer/react-native-analytics-mux Mux
Nielsen analytics %40theoplayer/react-native-analytics-nielsen Nielsen
Youbora analytics %40theoplayer/react-native-analytics-youbora Youbora
Content protection (DRM) %40theoplayer/react-native-drm DRM
React Native Open UI %40theoplayer/react-native-ui Open UI
A template for
react-native-theoplayer connectors.
%40theoplayer/react-native-connector-template Connector template

Creating your first app

This section starts with creating a minimal demo app that integrates the react-native-theoplayer package, followed by an overview of the available properties and functionality of the THEOplayerView component. An example application including a basic user interface and demo sources is included in the git repository, and discussed in the next section.

Knowledge Base

This section gives an overview of features, limitations and known issues:

API Reference

See the API Reference for detailed documentation about all available components and functions.

react-native-theoplayer's People

Contributors

beningo avatar dependabot[bot] avatar dev1an avatar georgechoustoulakis avatar ijzerenhein avatar jeroen-veltmans avatar kevin-kp avatar kot331107 avatar mattiasbuelens avatar tvanlaerhoven avatar webnard avatar wjoosen avatar wouterds avatar wvanhaevre avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-native-theoplayer's Issues

iOS & tvOS build fails with version 2.4.0

If we try to make build with version 2.4.0 Xcodes throws an error

Failed to build module 'THEOplayerGoogleCastIntegration'; this SDK is not supported by the compiler (the SDK is built with 'Apple Swift version 5.3.2 (swiftlang-1200.0.45 clang-1200.0.32.28)', while this compiler is 'Apple Swift version 5.7.2 (swiftlang-5.7.2.135.5 clang-1400.0.29.51)'). Please select a toolchain which matches the SDK.

We also didn't include CHROMECAST in the react-native-theoplayer.json

{
	"ios": {
		"features": [
			"GOOGLE_IMA"
		]
	}
}

Xcode version 14.2

v1.6.1 iOS build error

I'm getting build errors while updating from 1.2.0 to 1.6.1

EDIT: Just checked 1.6.0 works fine.

Screenshot at Oct 26 22-07-26

Controls not displaying with new @theoplayer/react-native-ui package

Hello! This is my code below. The controls on my player are not displaying. I have been using THEOplayer with the regular UI package for a while now and it has always worked. Now, it has stopped with the new package. Does anyone know why?

"react-native": "0.71.5",
"@theoplayer/react-native-ui": "^0.2.0",
"react-native-theoplayer": "^2.9.0",
"react-native-svg": "^13.10.0",
"@react-native-community/slider": "^4.4.2",

import React, {useState, useEffect} from 'react';
import {View, StyleSheet, Dimensions, Platform} from 'react-native';
import {Icon} from 'native-base';
import {
  CONTENT_REACHED_30_SECONDS,
  CONTENT_PLAYBACK_STARTED,
  CONTENT_COMPLETED,
  BUFFERING_STARTED,
  VIDEO_PLAYER_ERROR,
} from '../../../analytics/AnalyticsConstants';
import AsyncStorage from '@react-native-async-storage/async-storage';
import {useNavigation} from '@react-navigation/native';
import Orientation from 'react-native-orientation-locker';
import {useAnalytics} from '@segment/analytics-react-native';
import {
  PlaybackRateSubMenu,
  ChromecastButton,
  LanguageMenuButton,
  QualitySubMenu,
  UiContainer,
  DEFAULT_THEOPLAYER_THEME,
  CenteredDelayedActivityIndicator,
  CenteredControlBar,
  SkipButton,
  PlayButton,
  ControlBar,
  SeekBar,
  MuteButton,
  TimeLabel,
  Spacer,
  SettingsMenuButton,
} from '@theoplayer/react-native-ui';
import {PlayerEventType, THEOplayerView} from 'react-native-theoplayer';

export function Player({
  player,
  setPlayer,
  contentType,
  id,
  title,
  mediaId,
  premium,
  creatorId,
  creatorName,
  thumbnail,
  content,
}) {
  const [reached30seconds, setReached30Seconds] = useState(false);
  const [playbackStarted, setPlaybackStarted] = useState(false);
  const [playbackCompleted, setPlaybackCompleted] = useState(false);
  const {screen, track, identify, group, alias, reset, flush} = useAnalytics();
  const navigation = useNavigation();
  const [isFullScreen, setFullScreen] = useState(false);
  const chromeless = playerConfig?.chromeless ?? false;

  useEffect(() => {
    if (reached30seconds) {
      track(CONTENT_REACHED_30_SECONDS, {
        content_type: contentType,
        post_id: id,
        post_title: title,
        media_id: mediaId,
        premium_plan: premium,
        creator_id: creatorId,
        creator_name: creatorName,
      });
    }
  }, [reached30seconds]);

  async function onLoad(player) {
    if (!playbackStarted) {
      setPlaybackStarted(true);

      track(CONTENT_PLAYBACK_STARTED, {
        content_type: contentType,

        post_id: id,
        post_title: title,
        media_id: mediaId,
        premium_plan: premium,

        creator_id: creatorId,
        creator_name: creatorName,
      });
    }

    try {
      const value = await AsyncStorage.getItem(`POST_${id}`);

      if (value !== null) {
        setTimeout(() => {
          player.currentTime = parseInt(value);
        }, 1000);
      }
    } catch (e) {}
  }

  async function onProgress(player) {
    if (player.currentTime > 30000 && !reached30seconds) {
      await setReached30Seconds(true);
    }

    if (player.currentTime === player.duration - 1000 && !playbackCompleted) {
      setPlaybackCompleted(true);

      track(CONTENT_COMPLETED, {
        content_type: contentType,

        post_id: id,
        post_title: title,
        media_id: mediaId,
        premium_plan: premium,

        creator_id: creatorId,
        creator_name: creatorName,
      });
    }

    if (player.currentTime > 0 && player.currentTime % 1000 === 0) {
      try {
        await AsyncStorage.setItem(`POST_${id}`, player.currentTime.toString());
      } catch (e) {}
    }
  }

  useEffect(() => {
    const orientationListener = (orientation) => {
      const parent = navigation.dangerouslyGetParent();

      if (
        orientation === 'LANDSCAPE-LEFT' ||
        orientation === 'LANDSCAPE-RIGHT'
      ) {
        parent.setOptions({tabBarVisible: false});
        navigation.setOptions({headerShown: false});
        setFullScreen(true);
      }

      if (orientation === 'PORTRAIT') {
        parent.setOptions({tabBarVisible: true});
        navigation.setOptions({headerShown: true});
        setFullScreen(false);
      }
    };

    Orientation.addOrientationListener(orientationListener);

    return () => {
      Orientation.removeOrientationListener(orientationListener);
    };
  }, [isFullScreen]);

  const playerConfig = {
    mediaControl: {
      mediaSessionEnabled: true,
    },
    chromeless: true,
    cast: {
      chromecast: {
        appID: ...
      },
      strategy: 'auto',
    },
    libraryLocation: 'theoplayer',
    license: ...
  };

  const source = {
    sources: [
      {
        src: content,
        type: 'application/x-mpegurl',
      },
    ],
    poster: thumbnail,
    metadata: {
      title: title,
      subtitle: creatorName,
    },
  };

  const onReady = (player) => {
    player.autoplay = true;
    player.source = source;

    setPlayer(player);

    player.addEventListener('waiting', () => {
      console.log('Video is buffering');
      track(BUFFERING_STARTED, {
        content_type: contentType,

        post_id: id,
        post_title: title,
        media_id: mediaId,
        premium_plan: premium,

        creator_id: creatorId,
        creator_name: creatorName,
      });
    });

    player.addEventListener(PlayerEventType.ERROR, () => {
      track(VIDEO_PLAYER_ERROR, {
        content_type: contentType,

        post_id: id,
        post_title: title,
        media_id: mediaId,
        premium_plan: premium,

        creator_id: creatorId,
        creator_name: creatorName,
      });
    });

    onLoad(player);

    player.addEventListener(PlayerEventType.TIME_UPDATE, () => {
      onProgress(player);
    });

    player.backgroundAudioConfiguration = {enabled: true};
    player.pipConfiguration = {startsAutomatically: true};
  };

  function CustomFullscreenButton() {
    const toggleFullScreen = () => {
      setFullScreen(!isFullScreen);

      if (!isFullScreen) {
        Orientation.lockToLandscapeLeft();
      } else {
        Orientation.unlockAllOrientations();
      }
    };

    return (
      <TouchableOpacity onPress={toggleFullScreen}>
        <Icon
          name="arrows-alt"
          type="FontAwesome"
          style={{fontSize: 20, color: '#FFF', marginTop: 5}}
        />
      </TouchableOpacity>
    );
  }

  return (
    <View
      style={{
        borderBottomColor: '#202020',
      }}>
      <View style={isFullScreen ? styles.fullscreenPlayer : styles.player}>
        <THEOplayerView config={playerConfig} onPlayerReady={onReady}>
          {player !== undefined && chromeless && (
            <UiContainer
              theme={{
                ...DEFAULT_THEOPLAYER_THEME,
                dimensions: {
                  controlBarHeight: 32,
                  centerControlBarHeight: 42,
                },
                text: {
                  textAlignVertical: 'center',
                  textAlign: 'center',
                  alignSelf: 'center',
                  fontSize: 14,
                },
                fadeAnimationTimoutMs: 1000,
              }}
              player={player}
              top={
                <ControlBar>
                  {Platform.OS === 'android' && !Platform.isTV && (
                    <ChromecastButton />
                  )}
                  <LanguageMenuButton />
                  <SettingsMenuButton>
                    <QualitySubMenu />
                    <PlaybackRateSubMenu />
                  </SettingsMenuButton>
                </ControlBar>
              }
              behind={<CenteredDelayedActivityIndicator size={50} />}
              center={
                <CenteredControlBar
                  left={
                    <SkipButton skip={-30} style={{width: 45, height: 45}} />
                  }
                  middle={<PlayButton />}
                  right={
                    <SkipButton skip={30} style={{width: 45, height: 45}} />
                  }
                />
              }
              bottom={
                <>
                  <ControlBar>
                    <SeekBar
                      style={{marginTop: Platform.OS === 'android' ? 7 : 0}}
                    />
                  </ControlBar>
                  <ControlBar>
                    <MuteButton />
                    <TimeLabel showDuration={true} />
                    <Spacer />
                    <CustomFullscreenButton />
                  </ControlBar>
                </>
              }
            />
          )}
        </THEOplayerView>
      </View>
    </View>
  );
}

export default Player;

const styles = StyleSheet.create({
  player: {
    width: '100%',
    height: undefined,
    aspectRatio: 16 / 9,
    backgroundColor: 'black',
  },
  fullscreenPlayer: {
    marginLeft: 25,
    width: Dimensions.get('window').height - 20,
    height: Dimensions.get('window').width - 20,
    minWidth: Dimensions.get('window').height - 20,
    minHeight: Dimensions.get('window').width - 20,
  },
});

Android livestream buffering error

If we play a livestream on a player on android it sudenly starts to stutter and stops completely wiht events:

  • Buffering
  • Play
    But player is not playing it's just stopped.

I tried SDK versions:

  • 6.4.0
  • 6.3.0
  • 6.2.1
  • 6.0.0

All produces same result

Here are the logs from logcat on android:

2023-11-16 15:42:13.057  |  MediaCodec              |                     I  [c2.exynos.h264.decoder] setting surface generation to 1979394
2023-11-16 15:42:13.057  |  SurfaceUtils            |                     D  disconnecting from surface 0xb400007c954e5f30, reason connectToSurface(reconnect)
2023-11-16 15:42:13.057  |  SurfaceUtils            |                     D  connecting to surface 0xb400007c954e5f30, reason connectToSurface(reconnect)
2023-11-16 15:42:13.057  |  CCodecBufferChannel     |                     D  [c2.android.aac.decoder#28] MediaCodec discarded an unknown buffer
2023-11-16 15:42:13.057  |  CCodecBufferChannel     |                     D  [c2.android.aac.decoder#28] MediaCodec discarded an unknown buffer
2023-11-16 15:42:13.057  |  CCodecBufferChannel     |                     D  [c2.android.aac.decoder#28] MediaCodec discarded an unknown buffer
2023-11-16 15:42:13.057  |  CCodecBufferChannel     |                     D  [c2.android.aac.decoder#28] MediaCodec discarded an unknown buffer
2023-11-16 15:42:13.057  |  CCodecBufferChannel     |                     D  [c2.android.aac.decoder#28] MediaCodec discarded an unknown buffer
2023-11-16 15:42:13.057  |  CCodecBufferChannel     |                     D  [c2.android.aac.decoder#28] MediaCodec discarded an unknown buffer
2023-11-16 15:42:13.057  |  Codec2-Out...ufferQueue |                     D  remote graphic buffer migration 9/9
2023-11-16 15:42:13.058  |  Codec2Client            |                     D  setOutputSurface -- failed to set consumer usage (6/BAD_INDEX)
2023-11-16 15:42:13.058  |  Codec2Client            |                     D  setOutputSurface -- generation=1979394 consumer usage=0x900
2023-11-16 15:42:13.058  |  hw-BpHwBinder           |                     I  onLastStrongRef automatically unlinking death recipients
2023-11-16 15:42:13.059  |  MediaCodec              |                     D  flushMediametrics
2023-11-16 15:42:13.060  |  MediaCodec              |                     D  flushMediametrics
2023-11-16 15:42:13.060  |  MediaCodec              |                     W  no metrics handle found
2023-11-16 15:42:13.062  |  Codec2Client            |                     D  Surface configure completed
2023-11-16 15:42:13.062  |  SurfaceUtils            |                     D  disconnecting from surface 0xb400007c95450ed0, reason disconnectFromSurface
2023-11-16 15:42:13.064  |  CCodecBufferChannel     |                     D  [c2.exynos.h264.decoder#679] MediaCodec discarded an unknown buffer
2023-11-16 15:42:13.064  |  CCodecBufferChannel     |                     D  [c2.exynos.h264.decoder#679] MediaCodec discarded an unknown buffer
2023-11-16 15:42:13.064  |  CCodecBufferChannel     |                     D  [c2.exynos.h264.decoder#679] MediaCodec discarded an unknown buffer
2023-11-16 15:42:13.064  |  CCodecBufferChannel     |                     D  [c2.exynos.h264.decoder#679] MediaCodec discarded an unknown buffer
2023-11-16 15:42:13.064  |  CCodecBufferChannel     |                     D  [c2.exynos.h264.decoder#679] MediaCodec discarded an unknown buffer
2023-11-16 15:42:13.064  |  CCodecBufferChannel     |                     D  [c2.exynos.h264.decoder#679] MediaCodec discarded an unknown buffer
2023-11-16 15:42:13.064  |  CCodecBufferChannel     |                     D  [c2.exynos.h264.decoder#679] MediaCodec discarded an unknown buffer
2023-11-16 15:42:13.064  |  CCodecBufferChannel     |                     D  [c2.exynos.h264.decoder#679] MediaCodec discarded an unknown buffer
2023-11-16 15:42:13.064  |  CCodecBufferChannel     |                     D  [c2.exynos.h264.decoder#679] MediaCodec discarded an unknown buffer
2023-11-16 15:42:13.068  |  AudioTrack              |                     D  stop(10347): called with 1324361 frames delivered
2023-11-16 15:42:13.070  |  TrafficStats            |                     D  tagSocket(128) with statsTag=0xffffffff, statsUid=-1
2023-11-16 15:42:13.075  |  PipelineWatcher         |                     D  onInputBufferReleased: frameIndex not found (680); ignored
2023-11-16 15:42:13.076  |  PipelineWatcher         |                     D  onInputBufferReleased: frameIndex not found (681); ignored
2023-11-16 15:42:13.077  |  PipelineWatcher         |                     D  onInputBufferReleased: frameIndex not found (682); ignored
2023-11-16 15:42:13.077  |  PipelineWatcher         |                     D  onInputBufferReleased: frameIndex not found (683); ignored
2023-11-16 15:42:13.080  |  SurfaceUtils            |                     D  disconnecting from surface 0xb400007c954e5f30, reason disconnectFromSurface
2023-11-16 15:42:13.080  |  hw-BpHwBinder           |                     I  onLastStrongRef automatically unlinking death recipients
2023-11-16 15:42:13.081  |  MediaCodec              |                     D  flushMediametrics
2023-11-16 15:42:13.081  |  MediaCodec              |                     D  flushMediametrics
2023-11-16 15:42:13.081  |  MediaCodec              |                     W  no metrics handle found
2023-11-16 15:42:13.096  |  CCodec                  |                     D  allocate(c2.exynos.h264.decoder)
2023-11-16 15:42:13.098  |  CCodec                  |                     I  setting up 'default' as default (vendor) store
2023-11-16 15:42:13.099  |  CCodec                  |                     I  Created component [c2.exynos.h264.decoder]
2023-11-16 15:42:13.100  |  CCodecConfig            |                     D  read media type: video/avc
2023-11-16 15:42:13.101  |  ReflectedParamUpdater   |                     D  extent() != 1 for single value type: output.subscribed-indices.values
2023-11-16 15:42:13.101  |  ReflectedParamUpdater   |                     D  extent() != 1 for single value type: input.buffers.allocator-ids.values
2023-11-16 15:42:13.101  |  ReflectedParamUpdater   |                     D  extent() != 1 for single value type: output.buffers.allocator-ids.values
2023-11-16 15:42:13.101  |  ReflectedParamUpdater   |                     D  extent() != 1 for single value type: output.buffers.pool-ids.values
2023-11-16 15:42:13.103  |  ReflectedParamUpdater   |                     D  ignored struct field coded.color-format.locations
2023-11-16 15:42:13.104  |  CCodecConfig            |                     D  ignoring local param raw.size (0xd2001800) as it is already supported
2023-11-16 15:42:13.104  |  CCodecConfig            |                     D  ignoring local param default.color (0x5200180b) as it is already supported
2023-11-16 15:42:13.104  |  ReflectedParamUpdater   |                     D  ignored struct field raw.hdr-static-info.mastering
2023-11-16 15:42:13.105  |  CCodecConfig            |                     I  query failed after returning 15 values (BAD_INDEX)
2023-11-16 15:42:13.105  |  CCodecConfig            |                     D  c2 config diff is Dict {
                                                                                                      c2::u32 algo.low-latency.value = 0
                                                                                                      c2::i32 algo.priority.value = 0
                                                                                                      c2::float algo.rate.value = 0
                                                                                                      c2::u32 coded.pl.level = 20496
                                                                                                      c2::u32 coded.pl.profile = 20481
                                                                                                      c2::u32 coded.vui.color.matrix = 0
                                                                                                      c2::u32 coded.vui.color.primaries = 0
                                                                                                      c2::u32 coded.vui.color.range = 0
                                                                                                      c2::u32 coded.vui.color.transfer = 0
                                                                                                      c2::u32 default.color.matrix = 0
                                                                                                      c2::u32 default.color.primaries = 0
                                                                                                      c2::u32 default.color.range = 0
                                                                                                      c2::u32 default.color.transfer = 0
                                                                                                      c2::u32 input.buffers.max-size.value = 7340032
                                                                                                      string input.media-type.value = "video/avc"
                                                                                                      c2::u32 output.delay.value = 3
                                                                                                      string output.media-type.value = "video/raw"
                                                                                                      c2::u32 raw.color.matrix = 0
                                                                                                      c2::u32 raw.color.primaries = 0
                                                                                                      c2::u32 raw.color.range = 0
                                                                                                      c2::u32 raw.color.transfer = 0
                                                                                                      c2::float raw.hdr-static-info.max-cll = 0
                                                                                                      c2::float raw.hdr-static-info.max-fall = 0
                                                                                                      c2::u32 raw.max-size.height = 240
                                                                                                      c2::u32 raw.max-size.width = 320
                                                                                                      c2::u32 raw.pixel-format.value = 34
                                                                                                      c2::i32 raw.rotation.flip = 
2023-11-16 15:42:13.105  |  ColorUtils              |                     W  expected specified color aspects (0:0:0:0)
2023-11-16 15:42:13.112  |  THEO_VideoDecoder       |                     I  Decoder created successfully with name: c2.exynos.h264.decoder security: false Mime: video/avc
2023-11-16 15:42:13.112  |  MediaCodec              |                     D  flushMediametrics
2023-11-16 15:42:13.112  |  SurfaceUtils            |                     D  connecting to surface 0xb400007c95468580, reason connectToSurface
2023-11-16 15:42:13.113  |  MediaCodec              |                     I  [c2.exynos.h264.decoder] setting surface generation to 1979395
2023-11-16 15:42:13.113  |  SurfaceUtils            |                     D  disconnecting from surface 0xb400007c95468580, reason connectToSurface(reconnect)
2023-11-16 15:42:13.113  |  SurfaceUtils            |                     D  connecting to surface 0xb400007c95468580, reason connectToSurface(reconnect)
2023-11-16 15:42:13.113  |  CCodec                  |                     D  [c2.exynos.h264.decoder] buffers are bound to CCodec for this session
2023-11-16 15:42:13.114  |  CCodecConfig            |                     D  no c2 equivalents for csd-1
2023-11-16 15:42:13.114  |  CCodecConfig            |                     D  no c2 equivalents for native-window
2023-11-16 15:42:13.114  |  CCodecConfig            |                     D  no c2 equivalents for flags
2023-11-16 15:42:13.114  |  CCodecConfig            |                     D  c2 config diff is   c2::u32 input.buffers.max-size.value = 15728640
                                                                                                      c2::u32 raw.max-size.height = 3840
                                                                                                      c2::u32 raw.max-size.width = 3840
                                                                                                      c2::u32 raw.size.height = 540
                                                                                                      c2::u32 raw.size.width = 960
2023-11-16 15:42:13.114  |  Codec2Client            |                     W  query -- param skipped: index = 1107298332.
2023-11-16 15:42:13.114  |  CCodec                  |                     D  client requested max input size 4000000, which is smaller than what component recommended (15728640); overriding with component recommendation.
2023-11-16 15:42:13.114  |  CCodec                  |                     W  This behavior is subject to change. It is recommended that app developers double check whether the requested max input size is in reasonable range.
2023-11-16 15:42:13.114  |  CCodec                  |                     D  encoding statistics level = 0
2023-11-16 15:42:13.114  |  CCodec                  |                     D  setup formats input: AMessage(what = 0x00000000) = {
                                                                                                      int32_t height = 540
                                                                                                      int32_t level = 65536
                                                                                                      int32_t max-input-size = 15728640
                                                                                                      string mime = "video/avc"
                                                                                                      int32_t priority = 0
                                                                                                      int32_t profile = 65536
                                                                                                      int32_t width = 960
                                                                                                      Rect crop(0, 0, 959, 539)
                                                                                                    }
2023-11-16 15:42:13.114  |  CCodec                  |                     D  setup formats output: AMessage(what = 0x00000000) = {
                                                                                                      int32_t android._color-format = 2130708361
                                                                                                      int32_t android._video-scaling = 1
                                                                                                      int32_t rotation-degrees = 0
                                                                                                      int32_t color-standard = 1
                                                                                                      int32_t color-range = 2
                                                                                                      int32_t color-transfer = 3
                                                                                                      float cta861.max-cll = 0.000000
                                                                                                      float cta861.max-fall = 0.000000
                                                                                                      int32_t sar-height = 1
                                                                                                      int32_t sar-width = 1
                                                                                                      Rect crop(0, 0, 959, 539)
                                                                                                      int32_t width = 960
                                                                                                      int32_t height = 540
                                                                                                      int32_t max-height = 3840
                                                                                                      int32_t max-width = 3840
                                                                                                      string mime = "video/raw"
                                                                                                      int32_t priority = 0
                                                                                                      int32_t android._dataspace = 260
                                                                                                      int32_t color-format = 2130708361
                                                                                                    }
2023-11-16 15:42:13.115  |  CCodecConfig            |                     I  query failed after returning 15 values (BAD_INDEX)
2023-11-16 15:42:13.123  |  Codec2Client            |                     W  query -- param skipped: index = 1073743886.
2023-11-16 15:42:13.123  |  Codec2Client            |                     W  query -- param skipped: index = 1610614798.
2023-11-16 15:42:13.124  |  CCodecBufferChannel     |                     D  [c2.exynos.h264.decoder#386] Created input block pool with allocatorID 16 => poolID 21 - OK (0)
2023-11-16 15:42:13.124  |  CCodecBufferChannel     |                     I  [c2.exynos.h264.decoder#386] Created output block pool with allocatorID 18 => poolID 2175 - OK
2023-11-16 15:42:13.125  |  CCodecBufferChannel     |                     D  [c2.exynos.h264.decoder#386] Configured output block pool ids 2175 => OK
2023-11-16 15:42:13.125  |  Codec2-Out...ufferQueue |                     D  remote graphic buffer migration 0/0
2023-11-16 15:42:13.125  |  Codec2Client            |                     D  setOutputSurface -- failed to set consumer usage (6/BAD_INDEX)
2023-11-16 15:42:13.125  |  Codec2Client            |                     D  setOutputSurface -- generation=1979395 consumer usage=0x900
2023-11-16 15:42:13.125   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.126  |  Codec2Client            |                     D  Surface configure completed
2023-11-16 15:42:13.143  |  CCodecConfig            |                     D  c2 config diff is   c2::u32 output.delay.value = 18
2023-11-16 15:42:13.143   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.143  |  Codec2-Out...ufferQueue |                     D  set max dequeue count 25 from update
2023-11-16 15:42:13.146   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.146  |  CCodecBufferChannel     |                     D  [c2.exynos.h264.decoder#386] Ignoring stale input buffer done callback: last flush index = 0, frameIndex = 0
2023-11-16 15:42:13.147   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.147  |  Codec2-Out...ufferQueue |                     D  set max dequeue count 25 from update
2023-11-16 15:42:13.147  |  Codec2-Out...ufferQueue |                     D  set max dequeue count 25 from update
2023-11-16 15:42:13.148   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.149   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.150   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.151   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.151   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.153   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.155   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.156   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.157   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.158   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.158   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.159   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.160   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.161   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.162   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.163   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.164   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.166   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.169   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.169   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.185  |  TrafficStats            |                     D  tagSocket(412) with statsTag=0xffffffff, statsUid=-1
2023-11-16 15:42:13.228  |  WifiService             system_server                        I  acquireWifiLock uid=10461 lockMode=4 packageName=|
2023-11-16 15:42:13.240  |  WifiService             system_server                        I  acquireWifiLock uid=10461 lockMode=3 packageName=|
2023-11-16 15:42:13.256  |  WifiService             system_server                        I  acquireWifiLock uid=10461 lockMode=4 packageName=|
2023-11-16 15:42:13.266  |  WifiService             system_server                        I  acquireWifiLock uid=10461 lockMode=3 packageName=|
2023-11-16 15:42:13.289  |  WifiService             system_server                        I  acquireWifiLock uid=10461 lockMode=4 packageName=|
2023-11-16 15:42:13.300  |  WifiService             system_server                        I  acquireWifiLock uid=10461 lockMode=3 packageName=|
2023-11-16 15:42:13.313  |  WifiService             system_server                        I  acquireWifiLock uid=10461 lockMode=4 packageName=|
2023-11-16 15:42:13.326  |  WifiService             system_server                        I  acquireWifiLock uid=10461 lockMode=3 packageName=|
2023-11-16 15:42:13.332  |  CCodecConfig            |                     D  c2 config diff is   c2::u32 raw.color.matrix = 1
                                                                                                      c2::u32 raw.color.primaries = 1
                                                                                                      c2::u32 raw.color.range = 2
                                                                                                      c2::u32 raw.color.transfer = 3
                                                                                                      c2::u32 raw.crop.height = 540
                                                                                                      c2::u32 raw.crop.left = 0
                                                                                                      c2::u32 raw.crop.top = 0
                                                                                                      c2::u32 raw.crop.width = 960
                                                                                                      c2::u32 raw.size.height = 544
2023-11-16 15:42:13.332  |  CCodecBuffers           |                     D  [c2.exynos.h264.decoder#386:Output[N]] popFromStashAndRegister: at 3624074000us, output format changed to AMessage(what = 0x00000000) = {
                                                                                                      int32_t android._color-format = 2130708361
                                                                                                      int32_t android._video-scaling = 1
                                                                                                      int32_t rotation-degrees = 0
                                                                                                      int32_t color-standard = 1
                                                                                                      int32_t color-range = 2
                                                                                                      int32_t color-transfer = 3
                                                                                                      float cta861.max-cll = 0.000000
                                                                                                      float cta861.max-fall = 0.000000
                                                                                                      int32_t sar-height = 1
                                                                                                      int32_t sar-width = 1
                                                                                                      Rect crop(0, 0, 959, 539)
                                                                                                      int32_t width = 960
                                                                                                      int32_t height = 544
                                                                                                      int32_t max-height = 3840
                                                                                                      int32_t max-width = 3840
                                                                                                      string mime = "video/raw"
                                                                                                      int32_t priority = 0
                                                                                                      int32_t android._dataspace = 260
                                                                                                      int32_t color-format = 2130708361
                                                                                                    }
2023-11-16 15:42:13.342   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.343  |  WifiService             system_server                        I  acquireWifiLock uid=10461 lockMode=4 packageName=|
2023-11-16 15:42:13.354  |  WifiService             system_server                        I  acquireWifiLock uid=10461 lockMode=3 packageName=|
2023-11-16 15:42:13.354   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long
2023-11-16 15:42:13.367   612-13992 gralloc4                and...graphics.allocator-V1-service  W  Unable to set buffer name SurfaceView[|/|.MainActivity]#3(BLAST Consumer)3: File name too long

Ad Error: Integration Type

Trying out the feature/ad_events branch to get VAST/VMAP support. I'm getting an AD_ERROR related to the integration attribute. If I leave it off, the error message complains that I haven't defined the CSAI integration:

{"errorCode": "AD_ERROR", "errorMessage": "Missing CSAI integration: "}

If I set it to theo (which the docs state is the default), the error is:

`{"errorCode": "AD_ERROR", "errorMessage": "Unsupported CSAI integration: theo"}

If I set it to google-ima then the error is:

{"errorCode": "AD_ERROR", "errorMessage": "Google IMA support not enabled."}

I recognize this branch is a work in progress and under active development and it may very well be that it just isn't ready for use yet. I just want to check to make sure I'm not doing something wrong (i.e. if I need to include the IMA plugin on my own, for example).

Android: application/x-mpegurl format loading issues

WIth TheoPlayer SDK v4.0 it's possible to run application/x-mpegurl video streams. But the issue is that it does not load some video files.
Basically if the video is not a live stream it's not loaded. But if I try to run a livestream it get loaded but after 10-15 seconds and after starting playing it buffers frequently. My internet connection is stable and should not be an issue here.

I tried some of the sources from example project with type:'application/x-mpegurl' but was not able to load the video.
But the livestream source did load, I used this one.

Element type is invalid: expected a string or a class/function but got: undefined.

Screenshot 2023-07-12 at 5 58 49 PM

Has anyone seen this error? I'm getting it on my simulator for the first time.

This is my implementation of THEOplayerView, in a file called Player. I never used to get this error -- has something changed in a recent package? Something with THEOplayerView?

import React, {useState, useEffect} from 'react';
import {
  View,
  StyleSheet,
  Dimensions,
  TouchableOpacity,
  Platform,
} from 'react-native';
import {Icon} from 'native-base';
import {
  CONTENT_REACHED_30_SECONDS,
  CONTENT_PLAYBACK_STARTED,
  CONTENT_COMPLETED,
  BUFFERING_STARTED,
  VIDEO_PLAYER_ERROR,
} from '../../../analytics/AnalyticsConstants';
import AsyncStorage from '@react-native-async-storage/async-storage';
import {useNavigation} from '@react-navigation/native';
import Orientation from 'react-native-orientation-locker';
import {useAnalytics} from '@segment/analytics-react-native';
import {
  PlaybackRateSubMenu,
  ChromecastButton,
  LanguageMenuButton,
  QualitySubMenu,
  UiContainer,
  DEFAULT_THEOPLAYER_THEME,
  CenteredDelayedActivityIndicator,
  CenteredControlBar,
  SkipButton,
  PlayButton,
  ControlBar,
  SeekBar,
  MuteButton,
  TimeLabel,
  Spacer,
  SettingsMenuButton,
  PlayerEventType,
  THEOplayerView,
} from 'react-native-theoplayer';

function Player({
  player,
  setPlayer,
  contentType,
  id,
  title,
  mediaId,
  premium,
  creatorId,
  creatorName,
  thumbnail,
  content,
}) {
  const [reached30seconds, setReached30Seconds] = useState(false);
  const [playbackStarted, setPlaybackStarted] = useState(false);
  const [playbackCompleted, setPlaybackCompleted] = useState(false);
  const {screen, track, identify, group, alias, reset, flush} = useAnalytics();
  const navigation = useNavigation();
  const [isFullScreen, setFullScreen] = useState(false);

  useEffect(() => {
    if (reached30seconds) {
      track(CONTENT_REACHED_30_SECONDS, {
        content_type: contentType,
        post_id: id,
        post_title: title,
        media_id: mediaId,
        premium_plan: premium,
        creator_id: creatorId,
        creator_name: creatorName,
      });
    }
  }, [reached30seconds]);

  async function onLoad(player) {
    if (!playbackStarted) {
      setPlaybackStarted(true);

      track(CONTENT_PLAYBACK_STARTED, {
        content_type: contentType,

        post_id: id,
        post_title: title,
        media_id: mediaId,
        premium_plan: premium,

        creator_id: creatorId,
        creator_name: creatorName,
      });
    }

    try {
      const value = await AsyncStorage.getItem(`POST_${id}`);

      if (value !== null) {
        setTimeout(() => {
          player.currentTime = parseInt(value);
        }, 1000);
      }
    } catch (e) {}
  }

  async function onProgress(player) {
    if (player.currentTime > 30000 && !reached30seconds) {
      await setReached30Seconds(true);
    }

    if (player.currentTime === player.duration - 1000 && !playbackCompleted) {
      setPlaybackCompleted(true);

      track(CONTENT_COMPLETED, {
        content_type: contentType,

        post_id: id,
        post_title: title,
        media_id: mediaId,
        premium_plan: premium,

        creator_id: creatorId,
        creator_name: creatorName,
      });
    }

    if (player.currentTime > 0 && player.currentTime % 1000 === 0) {
      try {
        await AsyncStorage.setItem(`POST_${id}`, player.currentTime.toString());
      } catch (e) {}
    }
  }

  useEffect(() => {
    const orientationListener = (orientation) => {
      const parent = navigation.dangerouslyGetParent();

      if (
        orientation === 'LANDSCAPE-LEFT' ||
        orientation === 'LANDSCAPE-RIGHT'
      ) {
        parent.setOptions({tabBarVisible: false});
        navigation.setOptions({headerShown: false});
        setFullScreen(true);
      }

      if (orientation === 'PORTRAIT') {
        parent.setOptions({tabBarVisible: true});
        navigation.setOptions({headerShown: true});
        setFullScreen(false);
      }
    };

    Orientation.addOrientationListener(orientationListener);

    return () => {
      Orientation.removeOrientationListener(orientationListener);
    };
  }, [isFullScreen]);

  const playerConfig = {
    mediaControl: {
      mediaSessionEnabled: true,
    },
    chromeless: true,
    cast: {
      chromecast: {
        appID: ...
      },
      strategy: 'auto',
    },
    libraryLocation: 'theoplayer',
    license: ...
  };

  const source = {
    sources: [
      {
        src: content,
        type: 'application/x-mpegurl',
      },
    ],
    poster: thumbnail,
    metadata: {
      title: title,
      subtitle: creatorName,
    },
  };

  const onReady = (player) => {
    player.autoplay = true;
    player.source = source;

    setPlayer(player);

    player.addEventListener('waiting', () => {
      console.log('Video is buffering');
      track(BUFFERING_STARTED, {
        content_type: contentType,

        post_id: id,
        post_title: title,
        media_id: mediaId,
        premium_plan: premium,

        creator_id: creatorId,
        creator_name: creatorName,
      });
    });

    player.addEventListener(PlayerEventType.ERROR, () => {
      track(VIDEO_PLAYER_ERROR, {
        content_type: contentType,

        post_id: id,
        post_title: title,
        media_id: mediaId,
        premium_plan: premium,

        creator_id: creatorId,
        creator_name: creatorName,
      });
    });

    onLoad(player);

    player.addEventListener(PlayerEventType.TIME_UPDATE, () => {
      onProgress(player);
    });

    player.backgroundAudioConfiguration = {enabled: true};
    player.pipConfiguration = {startsAutomatically: true};
  };

  function CustomFullscreenButton() {
    const toggleFullScreen = () => {
      setFullScreen(!isFullScreen);

      if (!isFullScreen) {
        Orientation.lockToLandscapeLeft();
      } else {
        Orientation.unlockAllOrientations();
      }
    };

    return (
      <TouchableOpacity onPress={toggleFullScreen}>
        <Icon
          name="arrows-alt"
          type="FontAwesome"
          style={{fontSize: 20, color: '#FFF', marginTop: 5}}
        />
      </TouchableOpacity>
    );
  }

  return (
    <View
      style={{
        borderBottomColor: '#202020',
      }}>
      <View style={isFullScreen ? styles.fullscreenPlayer : styles.player}>
        <THEOplayerView config={playerConfig} onPlayerReady={onReady}>
          {player !== undefined && (
            <UiContainer
              theme={{
                ...DEFAULT_THEOPLAYER_THEME,
                dimensions: {
                  controlBarHeight: 32,
                  centerControlBarHeight: 42,
                },
                text: {
                  textAlignVertical: 'center',
                  textAlign: 'center',
                  alignSelf: 'center',
                  fontSize: 14,
                },
                fadeAnimationTimoutMs: 1000,
              }}
              player={player}
              top={
                <ControlBar>
                  {Platform.OS === 'android' && !Platform.isTV && (
                    <ChromecastButton />
                  )}
                  <LanguageMenuButton />
                  <SettingsMenuButton>
                    <QualitySubMenu />
                    <PlaybackRateSubMenu />
                  </SettingsMenuButton>
                </ControlBar>
              }
              behind={<CenteredDelayedActivityIndicator size={50} />}
              center={
                <CenteredControlBar
                  left={
                    <SkipButton skip={-30} style={{width: 45, height: 45}} />
                  }
                  middle={<PlayButton />}
                  right={
                    <SkipButton skip={30} style={{width: 45, height: 45}} />
                  }
                />
              }
              bottom={
                <View>
                  <ControlBar>
                    <SeekBar
                      style={{marginTop: Platform.OS === 'android' ? 7 : 0}}
                    />
                  </ControlBar>
                  <ControlBar>
                    <MuteButton />
                    <TimeLabel showDuration={true} />
                    <Spacer />
                    <CustomFullscreenButton />
                  </ControlBar>
                </View>
              }
            />
          )}
        </THEOplayerView>
      </View>
    </View>
  );
}

export default Player;

const styles = StyleSheet.create({
  player: {
    width: '100%',
    height: undefined,
    aspectRatio: 16 / 9,
    backgroundColor: 'black',
  },
  fullscreenPlayer: {
    marginLeft: 25,
    width: Dimensions.get('window').height - 20,
    height: Dimensions.get('window').width - 20,
    minWidth: Dimensions.get('window').height - 20,
    minHeight: Dimensions.get('window').width - 20,
  },
});

Type mismatch when defining kotlinVersion

Since we've explicitly defined kotlinVersion in our build.gradle, THEOplayer struggles to build with the following error:

'compileDebugJavaWithJavac' task (current target is 11) and 'compileDebugKotlin' task (current target is 1.8) jvm target compatibility should be set to the same Java version.
e: /Users/jasper/code/my-demo-app/node_modules/react-native-theoplayer/android/src/main/java/com/theoplayer/presentation/PipUtils.kt: (75, 39): Type mismatch: inferred type is EventListener<PlayerEvent<*>>? but EventListener<in TypeVariable(T)!> was expected
e: /Users/jasper/code/my-demo-app/node_modules/react-native-theoplayer/android/src/main/java/com/theoplayer/presentation/PipUtils.kt: (78, 43): Type mismatch: inferred type is EventListener<GoogleImaAdEvent>? but EventListener<in TypeVariable(T)!> was expected
e: /Users/jasper/code/my-demo-app/node_modules/react-native-theoplayer/android/src/main/java/com/theoplayer/presentation/PipUtils.kt: (92, 42): Type mismatch: inferred type is EventListener<PlayerEvent<*>>? but EventListener<in TypeVariable(T)!> was expected
e: /Users/jasper/code/my-demo-app/node_modules/react-native-theoplayer/android/src/main/java/com/theoplayer/presentation/PipUtils.kt: (95, 46): Type mismatch: inferred type is EventListener<GoogleImaAdEvent>? but EventListener<in TypeVariable(T)!> was expected

I must say I'm not entirely confident about what causes this issue, but some remarks we've found while debugging this:

  • Most libraries base their version of org.jetbrains.kotlin:kotlin-gradle-plugin on kotlinVersion defined in the root-project, while react-native-theoplayer has this hardcoded to 1.7.21. Setting our kotlinVersion to the same version doesn't fix our issue, but it seems to be a good practice not to fixate this. Not sure why it is?
  • We've tried different versions of Kotlin (1.7.21, 1.8.22 for example), but this all leads to the same error it seems.
Screenshot 2023-07-12 at 14 43 45

Subtitles still on after disabling them on sample ui iOS

I added a switch to enable and disable subtitles to the sample ui. in order to disable the subtitle I just pass an index =-1 to the onItemSelected function. on Android it works fine however on iOS I can see that the uid becomes undefined but the subtitle is still showing.

Player events callback bug (onReadyStateChange & onTimeUpdate ) after seek

Currently on version 1.7.1.

We have a situation where we switch from live to an open recording
When this happens the source changes and we seek to the last position ( paused property is set to true ).

We notice that the onReadyStateChange is not called when the source changes with the paused prop set to true. The onTimeUpdate callback is also not triggered when the paused prop is set to true.

if we briefly change the paused property from true to false it works but it includes a dirty hack on our side.

Is this intended behaviour? For us it seems more logic to trigger all the callbacks after a seek disregard of the paused property set too true or false.

Module not found when building iOS release with custom framework

When loading in a custom framework (from the theoplayer portal) for iOS (to get Google IMA support), We follow the instructions found here to set up the xcframework in a location that can be found by the compiler. The react-native app build completes just fine in debug; however, when running a release build (using something like npx react-native run-ios --configuration Release is what we normally do, but we also see the issue when trying to build an archive through xcode), the build process fails even though the location of the framework hasn't changed (swift throws a "module not found" error when trying to run import THEOplayerSDK). Are there additional steps needed to get it to do a release build with the custom xcframework?

We are running this on a machine with an Apple M1 chip but have also tried an Intel chip. It just seems unable to find the sdk ... we have tried both the "npm local paths" approach, tried patching the npm module, tried forking and pulling in ourselves from github, etc.

Running the Android example app fails with a flipper error

Trying to run the example on Android TV throws the following exception:

E/SoLoader: couldn't find DSO to load: libflipper.so caused by: dlopen failed: cannot locate symbol "_Unwind_Resume" referenced by "/data/app/com.reactnativetheoplayer-q9EeEDXLB83p_FfRf7E25A==/lib/x86/libflipper.so"... result: 0
E/AndroidRuntime: FATAL EXCEPTION: FlipperConnectionThread
    Process: com.reactnativetheoplayer, PID: 3402
    java.lang.NoClassDefFoundError: <clinit> failed for class com.facebook.flipper.android.EventBase; see exception in other thread
        at com.facebook.flipper.android.FlipperThread.run(FlipperThread.java:25)
E/AndroidRuntime: FATAL EXCEPTION: FlipperEventBaseThread
    Process: com.reactnativetheoplayer, PID: 3402
    java.lang.UnsatisfiedLinkError: couldn't find DSO to load: libflipper.so caused by: dlopen failed: cannot locate symbol "_Unwind_Resume" referenced by "/data/app/com.reactnativetheoplayer-q9EeEDXLB83p_FfRf7E25A==/lib/x86/libflipper.so"... result: 0
        at com.facebook.soloader.SoLoader.doLoadLibraryBySoName(SoLoader.java:918)
        at com.facebook.soloader.SoLoader.loadLibraryBySoNameImpl(SoLoader.java:740)
        at com.facebook.soloader.SoLoader.loadLibraryBySoName(SoLoader.java:654)
        at com.facebook.soloader.SoLoader.loadLibrary(SoLoader.java:634)
        at com.facebook.soloader.SoLoader.loadLibrary(SoLoader.java:582)
        at com.facebook.flipper.android.EventBase.<clinit>(EventBase.java:19)
        at com.facebook.flipper.android.FlipperThread.run(FlipperThread.java:25)
     Caused by: java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_Unwind_Resume" referenced by "/data/app/com.reactnativetheoplayer-q9EeEDXLB83p_FfRf7E25A==/lib/x86/libflipper.so"...
        at java.lang.Runtime.load0(Runtime.java:938)
        at java.lang.System.load(System.java:1631)
        at com.facebook.soloader.SoLoader$1.load(SoLoader.java:405)
        at com.facebook.soloader.DirectorySoSource.loadLibraryFrom(DirectorySoSource.java:77)
        at com.facebook.soloader.DirectorySoSource.loadLibrary(DirectorySoSource.java:50)
        at com.facebook.soloader.ApplicationSoSource.loadLibrary(ApplicationSoSource.java:89)
        at com.facebook.soloader.SoLoader.doLoadLibraryBySoName(SoLoader.java:860)
        at com.facebook.soloader.SoLoader.loadLibraryBySoNameImpl(SoLoader.java:740) 
        at com.facebook.soloader.SoLoader.loadLibraryBySoName(SoLoader.java:654) 
        at com.facebook.soloader.SoLoader.loadLibrary(SoLoader.java:634) 
        at com.facebook.soloader.SoLoader.loadLibrary(SoLoader.java:582) 
        at com.facebook.flipper.android.EventBase.<clinit>(EventBase.java:19) 
        at com.facebook.flipper.android.FlipperThread.run(FlipperThread.java:25) 

It appears that Flipper is misconfigured in this project.

No controls on Android !!

On iOS when chromeless it set to false the controls are there. on Android there are no controls whether chromeless is set to true or false.
Also there is no back arrow to exit the player.

Layout position incorrect when placed in container view

In certain layout setups, the THEOplayerView is not positioned correctly according to the flex-box styling rules.

example:

const App = () => {
  return (
    <View style={styles.container}>
      <Text style={styles.text}>
        Press enter to show the on-screen keyboard
      </Text>
      <TextInput style={styles.textInput} placeholderTextColor="#888888" />
      <THEOplayerView style={styles.video} config={CONFIG} source={SOURCE} />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#333333',
  },
  text: {
    fontSize: 40,
    color: 'white',
    marginBottom: 20,
  },
  textInput: {
    width: 800,
    fontSize: 40,
    padding: 8,
  },
  video: {
    marginTop: 50,
    width: 640,
    height: 400,
  },
});

which produces the following layout:

note that the height of the video-player also appears clipped here

image

where you would expect:

image

I only tested this on tvOS

Repository containing the example and workaround:
https://github.com/IjzerenHein/ReactNativeTheoplayerKeyboardIssue

No sound on tvOS

In version 1.7.2 i have no sound on tvOS. On other platforms Android & iOS the sound is playing.

Type argument in android bridge with SDK 4.12

It appears that the latest Android SDK release (4.12) breaks react-native-theoplayer. We just started getting this error when trying to build for react-native Android.

e:  /home/projects/playerapp/node_modules/react-native-theoplayer/android/src/main/java/com/theoplayer/PlayerEventEmitter.kt: (497, 96): Type argument is not within its bounds: should be subtype of 'QualityChangedEvent<Q!, ActiveQualityChangedEvent!>!'
e: /home/projects/playerapp/node_modules/react-native-theoplayer/android/src/main/java/com/theoplayer/PlayerEventEmitter.kt: (499, 115): Type argument is not within its bounds: should be subtype of 'QualityChangedEvent<Q!, ActiveQualityChangedEvent!>!'
e: /home/projects/playerapp/node_modules/react-native-theoplayer/android/src/main/java/com/theoplayer/PlayerEventEmitter.kt: (502, 121): Type argument is not within its bounds: should be subtype of 'QualityChangedEvent<Q!, ActiveQualityChangedEvent!>!'

Pinning any earlier version of the SDK with (for example):

THEOplayer_sdk = "4.11.0"

works fine; however, since that's not the default, the backwards incompatibility means that 4.12 will likely be grabbed by existing CI/CD pipelines and fail.

Please do let us know when there's a version of react-native-theoplayer that works with SDK 4.12.

AdEvent `timeOffset` is always 0 after first ad break for IMA ads on iOS

I'm getting an issue where the timeOffset property of an AdBreak is always 0 for all ad breaks except for the first.

With ads set at 5, 10, and 15 seconds, within the callback for an event listener on AD_EVENT, the timeOffset is 5000 for the first set of events (as expected) but becomes 0 for the ads at 10 and 15 seconds. I've tested this on iOS on a simulated iPhone 15 with react-native-theoplayer 3.0.2. The issue is demonstrated in the following video

timeoffsets.webm

Example code

import React from 'react';
import {useState} from 'react';
import {
  DEFAULT_THEOPLAYER_THEME,
  CenteredDelayedActivityIndicator,
  UiContainer,
  ControlBar,
  SeekBar,
  MuteButton,
  TimeLabel,
  Spacer,
  FullscreenButton,
  CenteredControlBar,
  PlayButton,
  SkipButton,
} from '@theoplayer/react-native-ui';
import {
  THEOplayerView,
  AdDescription,
  PlayerConfiguration,
  SourceDescription,
  THEOplayer,
  AdIntegrationKind,
  PlayerEventType,
  AdBreak,
  AdEvent,
  Ad,
  AdEventType,
} from 'react-native-theoplayer';
import {View, StyleSheet, Text} from 'react-native';

function Player(): JSX.Element {
  const [player, setPlayer] = useState<THEOplayer | undefined>(undefined);
  const [timeOffset, setTimeOffset] = useState<AdBreak['timeOffset'] | undefined>(undefined); // prettier-ignore
  const [adEvent, setAdEvent] = useState<AdEventType | undefined>(undefined)
  const ads: AdDescription[] = [
    {
      integration: 'google-ima' as AdIntegrationKind,
      sources: {
        src: 'https://cdn.theoplayer.com/demos/preroll.xml',
        type: 'vast',
      },
      timeOffset: 5,
    },
    {
      integration: 'google-ima' as AdIntegrationKind,
      sources: {
        src: 'https://cdn.theoplayer.com/demos/preroll.xml',
        type: 'vast',
      },
      timeOffset: 10,
    },
    {
      integration: 'google-ima' as AdIntegrationKind,
      sources: {
        src: 'https://cdn.theoplayer.com/demos/preroll.xml',
        type: 'vast',
      },
      timeOffset: 15,
    },
  ];
  const imaSource: SourceDescription = {
    sources: [
      {
        src: 'https://cdn.theoplayer.com/video/big_buck_bunny/big_buck_bunny_metadata.m3u8',
        type: 'application/x-mpegurl',
      },
    ],
    ads,
  };
  const playerConfig: PlayerConfiguration = {
    license: process.env.THEO_LICENSE,
    chromeless: true,
    libraryLocation: 'theoplayer',
    cast: {
      chromecast: {
        appID: 'CC1AD845',
      },
      strategy: 'auto',
    },
    mediaControl: {
      mediaSessionEnabled: true,
    },
  };

  const onPlayerReady = async (p: THEOplayer) => {
    p.addEventListener(PlayerEventType.AD_EVENT, function (event: AdEvent) {
      const offset =
        (event?.ad as AdBreak)?.timeOffset ||
        (event?.ad as Ad)?.adBreak?.timeOffset;

      setAdEvent(event.subType);

      if (offset !== undefined) {
        setTimeOffset(offset);
      }
    });
    p.source = imaSource;
    p.autoplay = true;
    p.play();

    setPlayer(p);
  };

  return (
    <View>
      <View style={{height: 100, width: 100}}>
        <Text>Ad time offset: {timeOffset}</Text>
        <Text>Ad Event: {adEvent}</Text>
      </View>
      <View style={{height: 300, width: 600}}>
        <THEOplayerView config={playerConfig} onPlayerReady={onPlayerReady}>
          {player !== undefined && (
            <UiContainer
              theme={DEFAULT_THEOPLAYER_THEME}
              player={player}
              behind={<CenteredDelayedActivityIndicator size={50} />}
              center={
                <CenteredControlBar
                  left={<SkipButton skip={-10} />}
                  middle={<PlayButton />}
                  right={<SkipButton skip={30} />}
                />
              }
              bottom={
                <>
                  <ControlBar>
                    <SeekBar />
                  </ControlBar>
                  <ControlBar>
                    <MuteButton />
                    <TimeLabel showDuration={true} />
                    <Spacer />
                    <FullscreenButton />
                  </ControlBar>
                </>
              }
            />
          )}
        </THEOplayerView>
      </View>
    </View>
  );
}

export default Player;

onDurationChange reports duration in seconds on iOS, but in milliseconds on Android

It appears the duration is mis-reported in iOS/tvOS. On nearly all instances, the currentTime and duration are reported in milliseconds. However on iOS/tvOS the duration is reported in Seconds instead. This causes time progress indicators to display the duration incorrectly.

tvOS:

image

Android:

image

Problem is most likely caused by a missing multiplication in:
https://github.com/THEOplayer/react-native-theoplayer/blob/develop/ios/THEOplayerRCTViewEventHandler.swift#L148

Feature Request: Use Document Picture-in-Picture Web API

Users should be able to use THEOplayer in a Picture-in-Picture window, not just the HTML video inside the web player.

image

Before the Document Picture-in-Picture API, it was only possible to put an HTML <video> element into a Picture-in-Picture window. This new API makes it possible to open an always-on-top window that can be populated with arbitrary HTML content. It is available as an origin trial starting in Chrome 111 on desktop.

async function togglePictureInPicture() {
  // Close Picture-in-Picture window if any.
  if (documentPictureInPicture.window) {
    documentPictureInPicture.window.close();
    return;
  }

  // Open a Picture-in-Picture window.
  const pipWindow = await documentPictureInPicture.requestWindow({
    initialAspectRatio: 640 / 360,
    copyStyleSheets: true,
  });

  // Move video to the Picture-in-Picture window.
  const video = document.querySelector("#video");
  pipWindow.document.body.append(video);

  // Listen for the PiP closing event to move the video back.
  pipWindow.addEventListener("unload", (event) => {
    const videoContainer = document.querySelector("#videoContainer");
    const pipVideo = event.target.querySelector("#video");
    videoContainer.append(pipVideo);
  });
}

Documentation:

Android build fails with Duplicate class errors

Following the instructions and attempting to build an app for Android TV fails with duplicate class errors:

...
Duplicate class com.theoplayer.mediacodec.event.MediaReadyState found in modules jetified-theoplayer-android-dist-sdkdemo-3.5.0-unifiedAndroid-release-runtime (theoplayer-android-dist-sdkdemo-3.5.0-unifiedAndroid-release.aar) and jetified-unified-3.6.1-runtime (com.theoplayer.theoplayer-sdk-android:unified:3.6.1)
     Duplicate class com.theoplayer.mediacodec.event.ProgressEvent found in modules jetified-theoplayer-android-dist-sdkdemo-3.5.0-unifiedAndroid-release-runtime (theoplayer-android-dist-sdkdemo-3.5.0-unifiedAndroid-release.aar) and jetified-unified-3.6.1-runtime (com.theoplayer.theoplayer-sdk-android:unified:3.6.1)
     Duplicate class com.theoplayer.mediacodec.event.ResizeVideoEvent found in modules jetified-theoplayer-android-dist-sdkdemo-3.5.0-unifiedAndroid-release-runtime (theoplayer-android-dist-sdkdemo-3.5.0-unifiedAndroid-release.aar) and jetified-unified-3.6.1-runtime (com.theoplayer.theoplayer-sdk-android:unified:3.6.1)
...

This seems to happen because the library is both importing dependencies from the local libs folder as well as Maven. And since a newer version has been published to maven, this is causing issues.

build.gradle

dependencies {
  //noinspection GradleDynamicVersion
  implementation "com.facebook.react:react-native:+"  // From node_modules
  implementation "com.theoplayer.theoplayer-sdk-android:unified:${safeExtGet('THEOplayer_sdk', '+')}"
  implementation "com.theoplayer.theoplayer-sdk-android:unified-ads:${safeExtGet('THEOplayer_sdk', '+')}"
  implementation "com.theoplayer.theoplayer-sdk-android:unified-ads-ima:${safeExtGet('THEOplayer_sdk', '+')}"
  implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
}

After disabling the import from libs, the build succeeds succesfully.

react-native-theplayer folder after installing it using npm

image

New V2 breaks web builds

Compiled with problems:X

ERROR in ./node_modules/react-native-theoplayer/node_modules/react-native-svg/lib/module/ReactNativeSVG.web.js 8:22-24

export 'createElement' (imported as 'cE') was not found in 'react-native' (possible exports: AccessibilityInfo, ActivityIndicator, Alert, Animated, AppRegistry, AppState, Appearance, BackHandler, Button, CheckBox, Clipboard, DeviceEventEmitter, DeviceInfo, Dimensions, DrawerLayoutAndroid, Easing, FlatList, I18nManager, Image, ImageBackground, InputAccessoryView, InteractionManager, Keyboard, KeyboardAvoidingView, LayoutAnimation, Linking, LogBox, Modal, NativeEventEmitter, NativeModules, PanResponder, PermissionsAndroid, Picker, PixelRatio, Platform, Pressable, ProgressBar, RefreshControl, SafeAreaView, ScrollView, SectionList, Settings, Share, StatusBar, StyleSheet, Switch, Systrace, TVEventHandler, Text, TextInput, ToastAndroid, Touchable, TouchableHighlight, TouchableNativeFeedback, TouchableOpacity, TouchableWithoutFeedback, UIManager, Vibration, View, VirtualizedList, YellowBox, findNodeHandle, processColor, render, unmountComponentAtNode, unstable_createElement, useColorScheme, useLocaleContext, useWindowDimensions)

textTrackStyle for iOS/Android

Hi there,

First of all: great lib :)

We're currently evaluating if THEOplayer is the right way to go for us.
One potential blocker is that textTrackStyle is not available for iOS/Android according to the docs:

/**
 * The text track style API.
 *
 * @remarks
 * Only available for Web.
 */
readonly textTrackStyle: TextTrackStyle;

Is there some other way to achieve this? If not, are there any plans to support this? If so, is there a timeline for it?

Thanks!

Is it only for video player?

Is it only for video player? or we can use this library for any type of view? Like in my case I want to show map view with rider's location in picture-in-picture just like google map.

Conflicting frameworks googlecast.xcframework

When installing version 2.3.0 with config

{ "ios": { "features": [ "GOOGLE_IMA", "CHROMECAST" ] } }
We get the error when we run pod install

target has frameworks with conflicting names: googlecast.xcframework.

When we remove CHROMECAST from the features pod install completes

Update on the older issues?

I did not wanted to make a new issue but no one is responding inside the older issues...

Is there any update regarding those issues?
Fullscreen support - #13
Controls for android - #11

Setting `currentTime` during an `AD_BREAK_END` event does not work

I am testing IMA ads on iOS and trying to implement a workaround for #207. The player ignores setting the currentTime value during an AD_BREAK_END AD_EVENT callback.

  const onPlayerReady = async (p: THEOplayer) => {
    p.addEventListener(PlayerEventType.AD_EVENT, function (event: AdEvent) {
      if (event.subType === AdEventType.AD_BREAK_END) {
        p.currentTime = 35000 // is ignored
      }
    });

Add info on transitive dependencies

Autolinking does not work on transitive dependencies:
react-native-community/cli#1347

So when installing this package you might be missing react-native bindings to some components used in the player UI. The simplest fix is to just add them as a root dependency as well.

yarn add react-native-svg @react-native-community/slider

Maybe adding this info to creating-minimal-app.md is enough?

Android error on build (Unresolved reference: setAllowBackgroundPlayback)

When I build my project in Android Studio, I get the following error:

e: /Users/.../.../.../node_modules/react-native-theoplayer/android/src/main/java/com/theoplayer/ReactTHEOplayerContext.kt: (123, 25): Unresolved reference: setAllowBackgroundPlayback

Would anyone happen to know what is causing this, and what the fix is? I haven't changed my code and have never gotten this. Using version 2.11...

Android full screen support

Looking at the android native source there is no actual full screen support.
Setting an activity to immersive mode and hiding system bar is just a part of it.
But what happens if I have a video player that is small on the screen? Or what if I have a scroll view with few players?
Current example does not reflect actual player usage within the app unless you app is only having a video on a single screen.

Since there is no native controls it's impossible (or maybe not?) to add native full screen support as for now, but here is some inspiration from other projects.

JWPlayer
Fullscreen implementation by moving player view to activity root content layout (which I tested on your player and it works great but since there is no controls it's not a solution for now).
https://github.com/chaimPaneth/react-native-jw-media-player/blob/365977b4bbe23695cc996f40c4e5da0cf4fbc7e4/android/src/main/java/com/appgoalz/rnjwplayer/RNJWPlayerView.java#L372

AVPlayer
Fullscreen player dialog popup:
https://github.com/expo/expo/blob/main/packages/expo-av/android/src/main/java/expo/modules/av/video/FullscreenVideoPlayer.java

Error while building on React Native Android

I was facing an error while building on Android that says duplicate classes. I commented this in the build.gradle file of react-native-theoplayer:
implementation fileTree(include: ['.jar', '.aar'], dir: 'libs') and now I'm getting another error that says:
More than one file was found with OS independent path 'META-INF/fragment_release.kotlin_module'.
Thank you.

iOS Home indicator visible

Currently when doing playout on fullscreen on an iOS device the Home Indicator is visible on the bottom of the screen. Can we provide a property to toggle this on and off? Or make sure it disappears after a few seconds?

IMG_8570

Too many logs causing the app to freeze for a few seconds.

We are using the sample ui in our app and I noticed many logs on events. When enabling a subtitle there are about 50+ cue logs that cause the app to freeze until the logs are done. On the example app I can comment the prints but how can I do that on our app ?
I only copied the example/src folder to our app. I tried copying the swift files but that changed nothing.
And also I implemented a play next functionality. on iOS when I play next episode it auto plays but on Android it stays paused.

DRM content-protected won't play on tvOS/Android TV

Hi there, I would like to start by saying thank you so much for this library, and thanks to the maintainer for working hard in adding support to all platforms ❤️❤️

Currently, I am having an issue when trying to play DRM content-protected videos on tvOS/Android TV.

I am using:

I'm providing the following sources to THEOplayer:

const url = Platform.select({
    ios: hlsUrl ?? dashUrl,
    android: dashUrl ?? hlsUrl,
});

const sourceContentProtection: DRMConfiguration = {
        integration: 'keyos',
        fairplay: {
            licenseAcquisitionURL: XXXXXXXX,
            certificateURL: YYYYYYYYY,
        },
        // some custom protection data generated by our backend
        ...(authXML && {
            customdata: authXML,
        }),
    };

const source: Sources | undefined = url
    ? {
          type:
              url === dashUrl
                  ? 'application/dash+xml'
                  : 'application/x-mpegurl',
          src: url,
          contentProtection: sourceContentProtection,
      }
    : undefined;

....
return(
  <THEOplayerView
      source={{
          sources: source ? [source] : [],
      }}
  />
)

Android TV is reporting the following error:

Error during license server request

Screenshot 2022-09-13 at 15 40 51

tvOS instead:

Something went wrong while trying to play the content.

Simulator Screen Shot - Apple TV - 2022-09-13 at 15 40 56

Note that the same stream is playing perfectly on THEOplayer web and that other not DRM content-protected videos are working perfectly on this tvOS and Android TV 📺

react-native-theoplayer not properly handling IMA ads on iOS

We have upgraded from the 1.x.x branch to the 2.x.x branch and made all the configuration changes, with the goal of being able to use version 5.x.x of the THEO sdk. For Android, everything works great. For iOS, however, this upgrade has created a couple of issues for iOS devices when trying to play IMA ads. Here are the issues:

  1. When seeking over a scheduled ad, the IMA plugin does not play the adbreak that was scheduled. It does play the adbreak on Android (and used to when using the 1.x.x branch with THEO-ios sdk 4.11). This problem does not occur when the scheduled ad is reached linearly (i.e. when it encounters it during normal playback) ... only when seeking past the adbreak.

  2. After having played an ad, or after seeking past the place where a scheduled as is (even if it doesn't play because of the above issue), destroying the player crashes the app. Again, this does not happen on Android, or on the 1.x.x branch (using sdk 4.11).

To help troubleshoot, we have taken the sample react-native app and modified it to easily reproduce. it can be found at https://content.vidangel.com/theo-ad-test.zip -- after building, playing it on iOS should:

  1. play all ads fine straight through
  2. fail to play ads if you scrub past the adbreaks
  3. crash the app if you play through an ad or scrub past an ad and then use the "toggle off" button (which destroys the player)

If this would be better submitted as a helpdesk ticket, let us know. We're hoping there's something that can be addressed to resolve this, though.

When screen is off and PIP is playing, phone gets really hot and drains battery fast

We are using react-native-theoplayer, and a recent issue has arisen when playing a video, the screen is off and PIP is playing, the phone gets really hot and drains the battery fast.

We were wondering if any recent update of react-native-theoplayer has contributed to this, and what a possible solution would be.

Using version 2.11...

DRM content-protected won't play on tvOS

Hi there, I'm creating this issue to report that I cannot play DRM content-protected videos on tvOS

I am using:

I'm providing the following sources to THEOplayer:

const url = Platform.select({
    ios: hlsUrl ?? dashUrl,
    android: dashUrl ?? hlsUrl,
});

const sourceContentProtection: DRMConfiguration = {
        integration: 'keyos',
        fairplay: {
            licenseAcquisitionURL: XXXXXXXX,
            certificateURL: YYYYYYYYY,
        },
        // some custom protection data generated by our backend
        ...(authXML && {
            customdata: authXML,
        }),
    };

const source: Sources | undefined = url
    ? {
          type:
              url === dashUrl
                  ? 'application/dash+xml'
                  : 'application/x-mpegurl',
          src: url,
          contentProtection: sourceContentProtection,
      }
    : undefined;

....
return(
  <THEOplayerView
      source={{
          sources: source ? [source] : [],
      }}
  />
)

tvOS is reporting the following error:

Something went wrong while trying to play the content.

image

Note that the same stream is playing perfectly on THEOplayer web and that other not DRM content-protected videos are working perfectly on this tvOS 📺

Related to issue #29

Reloading iOS/tvOS app causes exception when removing TextTrack event listeners

First of all, thank you so much for this library, we (the community) really appreciate all the hard work put into this and the dedication of THEOPlayer to support the react-native platform ❤️ ❤️

To reproduce:

  • Launch the iOS or tvOS example app
  • Press Ctrl+R to reload the app
  • Exception occurs in native code when calling player.textTracks.removeEventListener

image

Investigated:

  • Out-commenting the whole content of dettachTextTrackListListeners prevents the exception from happening

Android PIP layout is broken

When trying to use PIP on android while player is not a fullscreen view it renders just the top of the screen:

image

Here is that screen:
image

currentProgramDateTime is undefined on Android

When listening to the PlayerEventType.TIME_UPDATE event, property currentProgramDateTime is undefined on Android.

Using react-native-theoplayer": "^2.5.0"

Stream: https://tagesschau.akamaized.net/hls/live/2020115/tagesschau/tagesschau_1/master.m3u8

iOS:
{"currentProgramDateTime": 1683017551409.3333, "currentTime": 7188009.333333333, "date": 2023-05-02T08:52:45.167Z, "type": "timeupdate"}

Web:
DefaultTimeupdateEvent {type: 'timeupdate', date: Tue May 02 2023 10:53:11 GMT+0200 (Central European Summer Time), currentTime: 7189027.979, currentProgramDateTime: 1683017576427}

Android:
{"currentProgramDateTime": undefined, "currentTime": 7188273, "date": 2023-05-02T08:54:01.091Z, "type": "timeupdate"}

Youbora integration

Hi there guys,

We are interested in using Youbora on AndroidTV and tvOS in react-native. From the official THEOPlayer docs I see that Youbora is not available on tvOS. I saw that in order to integrate it at least with AndroidTV, I need to add the analytics key to any of the video sources, but this doesn't seem to work yet with react-native-theoplayer.

Do you have any recommendations to make it work?

Thank you!! 🤗

HH:MM:SS timestamps do not work for IMA ads on iOS

On iOS, setting an ad like this does not work

    {
      integration: 'google-ima' as AdIntegrationKind,
      sources: {
        src: 'https://cdn.theoplayer.com/demos/preroll.xml',
        type: 'vast',
      },
      timeOffset: "00:00:10",
    },

For the above to work, it must be converted to a number type: timeOffset: 10

Android works fine in both instances.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.