THEOplayer / react-native-theoplayer

A React Native THEOplayerView component
https://theoplayer.github.io/react-native-theoplayer/
MIT License
65 stars 21 forks source link

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

Open webnard opened 1 year ago

webnard commented 1 year ago

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;
tvanlaerhoven commented 1 year ago

@webnard thanks for your detailed issue description. We'll pick it up.

wvanhaevre commented 1 year ago

We can reproduce the issue. We'll investigate the issue and get back to you when we have more info. EDIT: This seems to be an issue on the underlying iOS SDK. We will look into it and prepare a fix on that SDK.