> For the complete documentation index, see [llms.txt](https://docs.firework.com/firework-for-developers/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.firework.com/firework-for-developers/react-native-sdk/integration-guide-v2/customization-react-native/player-configurations-react-native.md).

# Player configurations (React Native)

We have the following four entries to open the player.

1. `VideoFeed` component
2. `StoryBlock` component
3. `PlayerDeck` component
4. `openVideoPlayer` API

When customizing the player, you need to handle the above entries if you use them.

### Configuration reference <a href="#configuration-reference" id="configuration-reference"></a>

1. [VideoPlayerConfiguration](https://eng.firework.com/react-native-firework-sdk/v2/interfaces/VideoPlayerConfiguration.html)
2. [StoryBlockConfiguration](https://eng.firework.com/react-native-firework-sdk/v2/interfaces/StoryBlockConfiguration.html)
3. [OpenVideoPlayerConfiguration](https://eng.firework.com/react-native-firework-sdk/v2/interfaces/OpenVideoPlayerConfiguration.html)

### Customize player styles

As the following code snippets, we could customize styles for video overlay CTA, countdown timer, etc.

```tsx
// Configure player configuration for VideoFeed component
<VideoFeed
  style={{ height: 200 }}
  source="discover"
  videoPlayerConfiguration={{
    // Customize the video overlay CTA button style
    ctaButtonStyle: {
      backgroundColor: '#2089ff',
      textColor: '#ffffff',
      fontSize: 14,
      shape: 'roundRectangle',
      iOSFontInfo: {
        fontName: 'Helvetica',
        systemFontStyle: 'italic',
        systemFontWeight: 'bold',
      },
    },
    countdownTimerConfiguration: { appearance: 'light' },
  }}
/>;

// Configure player configuration for StoryBlock component
<StoryBlock
  style={{ height: 200 }}
  source="discover"
  storyBlockConfiguration={{
    // Customize the video overlay CTA button style
    ctaButtonStyle: {
      backgroundColor: '#2089ff',
      textColor: '#ffffff',
      fontSize: 14,
      shape: 'roundRectangle',
      iOSFontInfo: {
        fontName: 'Helvetica',
        systemFontStyle: 'italic',
        systemFontWeight: 'bold',
      },
    },
    countdownTimerConfiguration: { appearance: 'light' },
  }}
/>;

// Configure player configuration for PlayerDeck component
<PlayerDeck
  style={{ height: 580 }}
  source="discover"
  videoPlayerConfiguration={{
    // Customize the video overlay CTA button style
    ctaButtonStyle: {
      backgroundColor: '#2089ff',
      textColor: '#ffffff',
      fontSize: 14,
      shape: 'roundRectangle',
      iOSFontInfo: {
        fontName: 'Helvetica',
        systemFontStyle: 'italic',
        systemFontWeight: 'bold',
      },
    },
    countdownTimerConfiguration: { appearance: 'light' },
  }}
/>;

// Configure player configuration for openVideoPlayer API
FireworkSDK.getInstance().openVideoPlayer(url, {
  // Customize the video overlay CTA button style
  ctaButtonStyle: {
    backgroundColor: '#2089ff',
    textColor: '#ffffff',
    fontSize: 14,
    shape: 'roundRectangle',
    iOSFontInfo: {
      fontName: 'Helvetica',
      systemFontStyle: 'italic',
      systemFontWeight: 'bold',
    },
  },
  countdownTimerConfiguration: { appearance: 'light' },
});
```

### Enable PiP(Picture in Picture)

Please refer to <https://docs.firework.com/firework-for-developers/react-native-sdk/integration-guide-v2/customization-react-native/player-configurations-react-native#enable-pip-picture-in-picture>

#### Set up the iOS project

To enable PiP outside the iOS app, you also need to add "Audio, Airplay, and Picture in Picture" background mode via Signing & Capabilities in your iOS project settings(as shown in the following screenshot). More information about this can be found here: [Apple Documentation](https://developer.apple.com/documentation/avfoundation/media_playback/configuring_the_audio_playback_of_ios_and_tvos_apps)

<figure><img src="/files/WKWATSXvTrLwuiHFwgzt" alt=""><figcaption></figcaption></figure>

#### Set enablePictureInPicture to true on JS side

```tsx
// Enable PiP for VideoFeed component
<VideoFeed
  style={{ height: 200 }}
  source="discover"
  enablePictureInPicture={true}
/>

// Enable PiP for StoryBlock component
<StoryBlock
  style={{ height: 400 }}
  source="discover"
  enablePictureInPicture={true}
/>

// Enable PiP for PlayerDeck component
<PlayerDeck
  style={{ height: 580 }}
  source="discover"
  enablePictureInPicture={true}
/>

// Enable PiP for openVideoPlayer API
FireworkSDK.getInstance().openVideoPlayer(url, {
  enablePictureInPicture: true,
});
```

### Customize player button icons

#### **Set up the iOS project**

Add your custom button icons to the asset catalogs(e.g. Images.xcassets, Assets.xcassets or other names) in your iOS project. Such as:

<figure><img src="/files/rnrx2GiDe7CQJRU63jkk" alt=""><figcaption></figcaption></figure>

**For more details, please refer to** [**https://developer.apple.com/documentation/xcode/adding-images-to-your-xcode-project**](https://developer.apple.com/documentation/xcode/adding-images-to-your-xcode-project)**.**

#### **Set up the Android project**

Add your custom button icons to the drawable directory([<mark style="color:orange;">App resources overview</mark>](https://developer.android.com/guide/topics/resources/providing-resources#ResourcesFromCode) and [<mark style="color:orange;">Support different pixel densities</mark>](https://developer.android.com/training/multiscreen/screendensities)) in your Android project. Such as:

<figure><img src="/files/4ePrGu4jaZREIJthJ9NJ" alt=""><figcaption></figcaption></figure>

#### **Config player button icon names on the JS side**

<pre class="language-tsx"><code class="lang-tsx"><strong>// Configure button icon names for video feed component
</strong><strong>&#x3C;VideoFeed
</strong>  style={{ height: 200 }}
  source="discover"
  mode="row"
  videoFeedConfiguration={videoFeedConfiguration}
  videoPlayerConfiguration={{
    buttonConfiguration: {
      videoDetailButton: { imageName: 'custom_more' },
<strong>      closeButton: { imageName: 'custom_close' },
</strong>      muteButton: { imageName: 'custom_mute' },
      unmuteButton: { imageName: 'custom_unmute' },
      playButton: { imageName: 'custom_play' },
      pauseButton: { imageName: 'custom_pause' },
    },
  }}
/>

// Configure button icon names for story block component
&#x3C;StoryBlock
  style={{ height: 200 }}
  source="discover"
  storyBlockConfiguration={{
    buttonConfiguration: {
      videoDetailButton: { imageName: 'custom_more' },
      closeButton: { imageName: 'custom_close' },
      muteButton: { imageName: 'custom_mute' },
      unmuteButton: { imageName: 'custom_unmute' },
      playButton: { imageName: 'custom_play' },
      pauseButton: { imageName: 'custom_pause' },
    },
  }}
/>;

// Configure button icon names for player deck component
&#x3C;PlayerDeck
  style={{ height: 580 }}
  source="discover"
  videoPlayerConfiguration={{
    buttonConfiguration: {
      videoDetailButton: { imageName: 'custom_more' },
      closeButton: { imageName: 'custom_close' },
      muteButton: { imageName: 'custom_mute' },
      unmuteButton: { imageName: 'custom_unmute' },
      playButton: { imageName: 'custom_play' },
      pauseButton: { imageName: 'custom_pause' },
    },
  }}
/>;

// Configure button icon names for openVideoPlayer API
FireworkSDK.getInstance().openVideoPlayer(url, {
  buttonConfiguration: {
    videoDetailButton: { imageName: 'custom_more' },
    closeButton: { imageName: 'custom_close' },
    muteButton: { imageName: 'custom_mute' },
    unmuteButton: { imageName: 'custom_unmute' },
    playButton: { imageName: 'custom_play' },
    pauseButton: { imageName: 'custom_pause' },
  },
});
</code></pre>

Please refer to [buttonConfiguration](https://eng.firework.com/react-native-firework-sdk/v2/interfaces/VideoPlayerConfiguration.html#buttonConfiguration) for more details.

### Customize player logo

To display the channel logo instead of the more icon (three dots) in the player, you could refer to the following code snippets.

```tsx
// Customize player logo for video feed component
<VideoFeed
  style={{ height: 200 }}
  source="discover"
  videoPlayerConfiguration={{
    videoPlayerLogoConfiguration: {
      option: 'creator',
      encodedId: 'encoded channel id', // encoded channel id
    }
  }}
/>

// Customize player logo for story block component
<StoryBlock
  style={{ height: 400 }}
  source="discover"
  storyBlockConfiguration={{
    videoPlayerLogoConfiguration: {
      option: 'creator',
      encodedId: 'encoded channel id', // encoded channel id
    }
  }}
/>

// Customize player logo for player deck component
<PlayerDeck
  style={{ height: 580 }}
  source="discover"
  videoPlayerConfiguration={{
    videoPlayerLogoConfiguration: {
      option: 'creator',
      encodedId: 'encoded channel id', // encoded channel id
    }
  }}
/>

// Customize player logo for openVideoPlayer API
FireworkSDK.getInstance().openVideoPlayer(url, {
  videoPlayerLogoConfiguration: {
    option: 'creator',
    encodedId: 'encoded channel id', // encoded channel id
  },
});
```

### Customize Ad badge

We offer a global API for customizing ad badges, and these configurations are applicable to both the player and the video feed. The API is `FireworkSDK.getInstance().adBadgeConfiguration`.

```dart
FireworkSDK.getInstance().adBadgeConfiguration = {
  badgeTextType: 'ad', // or sponsored
  backgroundColor: '#ffffff',
  textColor: '#000000',
  androidFontInfo: {
    isCustom: false,
    typefaceName: 'SANS_SERIF',
  },
};
```

### Customize other player configurations

```tsx
// Customize other player configurations for video feed component
<VideoFeed
  style={{ height: 200 }}
  source="discover"
  // Configure player configuration for VideoFeed component
  videoPlayerConfiguration={{
    // Configure player style: full or fit
    playerStyle: 'fit',
    // Configure video complete action: advanceToNext or loop
    videoCompleteAction: 'advanceToNext',
    // Indicates if the video player shows share button
    showShareButton: true,
    // Indicates if the video player shows playback button
    showPlaybackButton: true,
    // Indicates if the video player shows mute button
    showMuteButton: true,
    // Specifies if the video detail title should be showed
    showVideoDetailTitle: true,
    // Enable vertical scroll for player
    scrollDirection: 'vertical',
    // Hide prev/next navigation arrow buttons
    isArrowButtonVisible: false,
    // Loop back to the first video when the feed reaches the end
    feedCompleteAction: 'loop',
  }}
/>;

// Customize other player configurations for story block component
<StoryBlock
  style={{ height: 200 }}
  source="discover"
  storyBlockConfiguration={{
    // Configure player style: full or fit
    playerStyle: 'fit',
    // Configure video complete action: advanceToNext or loop
    videoCompleteAction: 'advanceToNext',
    // Indicates if the video player shows share button
    showShareButton: true,
    // Indicates if the video player shows playback button
    showPlaybackButton: true,
    // Indicates if the video player shows mute button
    showMuteButton: true,
    // Specifies if the video detail title should be showed
    showVideoDetailTitle: true,
    // Enable vertical scroll for player
    scrollDirection: 'vertical',
    // Hide prev/next navigation arrow buttons for embedded mode
    isArrowButtonVisible: false,
    // Hide prev/next navigation arrow buttons for fullscreen mode
    isFullscreenArrowButtonVisible: false,
    // Loop back to the first video when the feed reaches the end
    // This property only applies to fullscreen mode
    feedCompleteAction: 'loop',
    // Additional controls inset for embedded mode
    // This adds extra margin/padding to controls in the embedded story block
    additionalControlsInset: {
      top: 20, 
      bottom: 30,
    },
  }}
/>;

// Customize other player configurations for player deck component
<PlayerDeck
  style={{ height: 580 }}
  source="discover"
  videoPlayerConfiguration={{
    // Configure player style: full or fit
    playerStyle: 'fit',
    // Configure video complete action: advanceToNext or loop
    videoCompleteAction: 'advanceToNext',
    // Indicates if the video player shows share button
    showShareButton: true,
    // Indicates if the video player shows playback button
    showPlaybackButton: true,
    // Indicates if the video player shows mute button
    showMuteButton: true,
    // Specifies if the video detail title should be showed
    showVideoDetailTitle: true,
    // Hide prev/next navigation arrow buttons for embedded mode
    isArrowButtonVisible: false,
    // Hide prev/next navigation arrow buttons for fullscreen mode
    isFullscreenArrowButtonVisible: false,
    // Loop back to the first video when the feed reaches the end
    // This property only applies to fullscreen mode
    feedCompleteAction: 'loop',
  }}
/>;

// Customize other player configurations for openVideoPlayer API
FireworkSDK.getInstance().openVideoPlayer(url, {
  // Configure player style: full or fit
  playerStyle: 'fit',
  // Configure video complete action: advanceToNext or loop
  videoCompleteAction: 'advanceToNext',
  // Indicates if the video player shows share button
  showShareButton: true,
  // Indicates if the video player shows playback button
  showPlaybackButton: true,
  // Indicates if the video player shows mute button
  showMuteButton: true,
  // Specifies if the video detail title should be showed
  showVideoDetailTitle: true,
  // Enable vertical scroll for player
  scrollDirection: 'vertical',
  // Hide prev/next navigation arrow buttons
  isArrowButtonVisible: false,
  // Loop back to the first video when the feed reaches the end
  feedCompleteAction: 'loop',
});
```
