VideoPlayer aspect ratio


:backhand_index_pointing_right: Bug Description


1. Summary

Videos with an aspect ratio of 9:16 are not being reproduced using:
{VideoPlayer, KeplerVideoView } from ‘@amazon-devices/react-native-w3cmedia’;

App Name: N/A (in development)

Bug Severity
Select one that applies

  • Impacts operation of app
  • Blocks current development
  • Improvement suggestion
  • Issue with documentation (If selected, please share the doc link and describe the issue)
  • Other

2. Steps to Reproduce

  1. import the library (import { VideoPlayer, KeplerVideoView } from ‘@amazon-devices/react-native-w3cmedia’:wink:
  2. set the video src to your video and initialize your player
  3. run the player
    <KeplerVideoView
    videoPlayer={video.current as VideoPlayer}
    />

3. Observed Behavior

Explain what actually happened, noting any discrepancies or malfunctions.

When reproducing videos with an aspect ratio of 9:16, it just shows a black screen

4. Expected Behavior

Describe what you expected the SDK to do under normal operation.

It should reproduce videos regarding of their aspect ratio

4.a Possible Root Cause & Temporary Workaround

Fill out anything you have tried. If you don’t know, N/A is acceptable

N/A

5. Logs or crash report

There is no crash or logs, it just doesn’t work..

6. Environment

Please fill out the fields related to your bug below:

  • SDK Version: 0.21.4726

  • App State: [Foreground]

  • OS Information
    Please ssh into the device via kepler exec vda shelland copy the output from cat /etc/os-releaseinto the answer section below. Note, if you don’t have a simulator running or device attached kepler exec vda shell will respond with vda: no devices/emulators found

    NAME="OS"
    OE_VERSION="4.0.0"
    OS_MAJOR_VERSION="1"
    OS_MINOR_VERSION="1"
    RELEASE_ID="10"
    OS_VERSION="1.1"
    BRANCH_CODE="TV Ship"
    BUILD_DESC="OS 1.1 (TV Ship/10240280)"
    BUILD_FINGERPRINT="1.0.24028.0(c449c30bb1fb0cc8)/10240280N:user/dev-keys"
    BUILD_VARIANT="user"
    BUILD_TAGS="dev-keys"
    BUILD_DATE="Thu Sep 25 10:31:39 UTC 2025"
    BUILD_TIMESTAMP="1758796299"
    VERSION_NUMBER="1002034028030"
    

7. Example Code Snippet / Screenshots / Screengrabs

Include any relevant code or component setup in React Native that can help reproduce the bug.

import { VideoPlayer, KeplerVideoView } from '@amazon-devices/react-native-w3cmedia';

const video = useRef<VideoPlayer | null>(null);
const [useKeplerVideoView, setUseKeplerVideoView] = useState(false);

useEffect(() => {
    initializingPreBuffering();
 }, []);


const initializingPreBuffering = async () => {

    video.current = new VideoPlayer();
    await video.current.initialize();

    video.current.src = 'video source'
    setUseKeplerVideoView(true);
  };


return (
    <>
      {useKeplerVideoView && (
        <KeplerVideoView
          showControls={config.controls}
          videoPlayer={video.current as VideoPlayer}
        />
      )}
    </>
  );


:backhand_index_pointing_right: Playback Issues


If this is a playback issue, please provide your content URL, any pre-conditions (like geo-location), and let us know if it’s x86 or arm7.


//VIDEO WITH THE RATIO SET TO 9:16
https://www.dropbox.com/scl/fi/dkmgxfo6hxbvzwuknrrk6/HunterClickerOpenBeta2.mp4?rlkey=rlg5oyyf6cy55ne7eouh3h4wv&e=1&st=xsdf77ug&dl=0

//SAME VIDEO CONVERTED TO 16:9
https://www.dropbox.com/scl/fi/pnpqk09fhcvhaothbrp5e/Hunterclickeropenbeta2Ratio.mp4?rlkey=h4kebem0ib9m7r83bqqw264lf&e=1&st=dwn60pm5&dl=0

If you are going to paste this video in the example code URL, please first delete generate a proper link and use that instead (by adding raw=1 instead of dl=0 at the end of the link):

https://www.dropbox.com/scl/fi/dkmgxfo6hxbvzwuknrrk6/HunterClickerOpenBeta2.mp4?rlkey=rlg5oyyf6cy55ne7eouh3h4wv&e=1&st=xsdf77ug&raw=1

Please share the following details in addition:_

  • Player SDK: [@amazon-devices/react-native-w3cmedia]
  • Player SDK Version: [e.g. ~2.1.80]
    • Audio Codecs: [AAC]
    • Video Codecs: [mp4]
    • Manifest Types: [not sure]

Q: If applicable, please provide your media/content url
If this is created dynamically, tokenized, etc please provide a way for us to access it

//VIDEO WITH THE RATIO SET TO 9:16
https://www.dropbox.com/scl/fi/dkmgxfo6hxbvzwuknrrk6/HunterClickerOpenBeta2.mp4?rlkey=rlg5oyyf6cy55ne7eouh3h4wv&e=1&st=xsdf77ug&dl=0

//SAME VIDEO CONVERTED TO 16:9
https://www.dropbox.com/scl/fi/pnpqk09fhcvhaothbrp5e/Hunterclickeropenbeta2Ratio.mp4?rlkey=h4kebem0ib9m7r83bqqw264lf&e=1&st=dwn60pm5&dl=0

If you are going to paste this video in the example code URL, please first delete generate a proper link and use that instead (by adding raw=1 instead of dl=0 at the end of the link):

https://www.dropbox.com/scl/fi/dkmgxfo6hxbvzwuknrrk6/HunterClickerOpenBeta2.mp4?rlkey=rlg5oyyf6cy55ne7eouh3h4wv&e=1&st=xsdf77ug&raw=1

Q: Are there any special headers required to reproduce the issue you are facing?

[N/A or Insert Headers]

Additionally please provide the following if possible
Provide Screenshots / Screengrabs / Logs. Please include as much information as you can that will help debug.

<!-- Answer here if applicable --> 

:backhand_index_pointing_right: Additional Context


Any Additional Context you would like to provide?
Add any other relevant information, such as recent updates to the SDK, dependencies, or device OS that may affect the bug.

Tested in the app virtual device only.

Hi @Yorki_Bonilla

Thanks for reporting this issue.
I could not replicate it. Can you please help me with relevant logs or since you mentioned there’s no crash report or logs, maybe a recording of the issue and more detailed code snippets?

Warm regards,
Ivy

when you say you could not reproduce, you mean you were able to show the vertical video just fine or with the code provided you couldn’t show any video at all?

I’ll share with you what you asked in a few hours

Hey @Yorki_Bonilla

With the code you provided, I could see no video at all, even after updating the url.

Warm regards,
Ivy

Great, knowing this, I’ll generate a totally new project and share the entire code with minimal set up, that way it will be easier to replicate and I’ll be able to test outside my own project too.

I’ll be back soon, thanks.

1 Like

These steps assume you already have your vega environment set up, if it is not set up, check the last 2 documentations provided at the end of this comment.

I recreated a basic project to be able to provide and recreate the error, this confirmed something for me.. the issue exists, and my implementation works. Please let me know if you need anything else to be able to replicate this issue.

There are 3 types of videos in the attached code that you can use to test this.. if for some reason the video doesn’t work anymore recreate the link using the https links provided on top of each video.current.src var.

  1. copy that url
  2. paste it in any browser
  3. it will generate a different link that directly sends you to the video
  4. use that link to assign it to video.current.src

Gif of the application working and how to test:

BugVegaCommunity

Step-by-step project setup:

  1. Create a new template project from the hello-world vega project list
  2. Add this to the package.json file, in dependecies: “@amazon-devices/react-native-w3cmedia”: “~2.1.80”,
  3. replace the code in your app.tsx file with the following code:

import React, {useEffect, useState} from 'react';
import {Text, View, TouchableOpacity, StyleSheet} from 'react-native';
import {VideoPlayerScreen} from './components/VideoPlayerScreen';

export const App = () => {
  const [currentScreen, setCurrentScreen] = useState<'welcome' | 'player'>('welcome');

   useEffect(() => {
    console.log('currentScreen changed to: ', currentScreen);
   },[currentScreen]);

  const loadVideo = () => {
    setCurrentScreen('player');
  }

   let content = null;
   if (currentScreen === 'welcome') {
    console.log('loading welcome screen');
    content = (
      <TouchableOpacity
        style={[styles.loadMenuButton, styles.focusedButton]}
        activeOpacity={1}
        onPress={loadVideo}
      >
        <Text>LOAD VIDEO</Text>
      </TouchableOpacity>
    );
   } else if(currentScreen === 'player') {
     console.log('loading player screen');
     content = (
    <VideoPlayerScreen
      onClose={ () => setCurrentScreen('welcome')}
    />
    );
   } else {
     console.log('invalid screen, defaulting to welcome screen');
     setCurrentScreen('welcome');
   }
  return (
    <View style={styles.outerContainer}>
      <View style={[styles.container]}>
        {content}
      </View>
    </View>
  );
};

// ------------------------------------------------------------------
// STYLES
// ------------------------------------------------------------------
const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  overlayText: {
  color: 'white',
  marginLeft: 10,
  fontSize: 22,  focusedButton: {
    borderWidth: 6,
    borderColor: '#FFD700',
    transform: [{ scale: 1.1 }],
  },
},
outerContainer: {
  flex: 1,
  backgroundColor: 'black',
},
loadMenuButton: {
    backgroundColor: '#2fadd3ff',
    borderRadius: 12,
    paddingVertical: 30,
    paddingHorizontal: 160,
    width: 800,
  },
    focusedButton: {
    borderWidth: 6,
    borderColor: '#FFD700',
    transform: [{ scale: 1.1 }],
  },
});
  1. create a new file for the videoPlayer in components/VideoPlayerScreen.tsx with the following code
import React, { useRef, useEffect, useState } from 'react';
import { BackHandler } from 'react-native';
import { VideoPlayer, KeplerVideoView } from '@amazon-devices/react-native-w3cmedia';

type VideoConfigScreenProps = {
  onClose: () => void;
};

export const VideoPlayerScreen: React.FC<VideoConfigScreenProps> = ({
  onClose,
}) => {
  const video = useRef<VideoPlayer | null>(null);
  const [useKeplerVideoView, setUseKeplerVideoView] = useState(false);

  useEffect(() => {
    console.log('loaded videoPlayerScreen');
    initializingPreBuffering();

    const back = BackHandler.addEventListener('hardwareBackPress', () => {
      video.current?.pause();
      onClose();
      return true;
    });

    return () => {
      video.current?.deinitialize();
      back.remove();
    };
  }, []);

  // -------------------------------------------------
   // PLAYER INITIALIZATION
   // ------------------------------------------------- 
  const initializingPreBuffering = async () => {

    video.current = new VideoPlayer();
    await video.current.initialize();

    video.current.autoplay = true;
    // video.current.loop = true;
    // video.current.muted = true;

    //VERTICAL 9:16 VIDEO THIS ONE DOESN'T WORK: ----------------------------------------1-----------------------------------
    //https://www.dropbox.com/scl/fi/dkmgxfo6hxbvzwuknrrk6/HunterClickerOpenBeta2.mp4?rlkey=rlg5oyyf6cy55ne7eouh3h4wv&e=1&st=xsdf77ug&raw=1
    //video.current.src = 'https://ucc16797826a6777b6e9a6a330f9.dl.dropboxusercontent.com/cd/0/inline/C4R4bh6tYtd9eVDAAY1SwOdPIq5PT_Ffc2OV5W5802Eob9QGO4fxhl_56qrilQgbWsDgoikf6zTDvl47TptIscx1x6_jSGF9RgeBnm4nnJnxhZqjQqpL4JXrBY-lfCujrwdCwKOdWtT1EmjBdwsjl_3z/file#'

    //VERTICAL CONVERTED TO 16:9 (WITH HANDBRAKE APP) THIS ONE WORKS: ------------------------------2---------------------------------------------
    //https://www.dropbox.com/scl/fi/pnpqk09fhcvhaothbrp5e/Hunterclickeropenbeta2Ratio.mp4?rlkey=h4kebem0ib9m7r83bqqw264lf&e=1&st=dwn60pm5&raw=1
    video.current.src = 'https://ucd152fb256736bd6b3ba2354cdb.dl.dropboxusercontent.com/cd/0/inline/C4Q2sPjg7QZ1T1bU8rsWMUakjSS3uHij9zqKQC45F6lGqeY9fIPQeolx8vVzpSh-K1_QMzv4kcZQ5WkT-r042nTWB_VUc4v9uLiA-DWQ701wzXag8RTEQHJHt9oagWRcgonqBPVQXNcIV0Q8ohLJFFC5/file#'

    //HORIZONTAL VIDEO THIS ONE WORKS: -----------------------------------3----------------------------------------
    //https://www.dropbox.com/scl/fi/9e1uare2s3rn617yljonv/La-gloria-de-Dios2.mp4?rlkey=wkcr4j6fjzspdi0c2rkf9z6fq&st=hyzlx7z4&raw=1
    //video.current.src = 'https://ucf51548182dd3fe753cd83b6f9f.dl.dropboxusercontent.com/cd/0/inline/C4R0CPEdu0l2V9XJ6xmpJAvnZMaZxxAH8X2k1rDk2nnLOVun833cwbOHwml4AavdlwpqmjgZ2Gn9P-FiuYd5EG0H2Kc_OceGk721ulEr4peVmqsW-vbRELF9IiEtx0mE4ZyZTCyUMRUjBdeuW08f_wi7/file#'
    setUseKeplerVideoView(true);
  };
  

  // Add KeplerVideoView component to the render trese
  return (
    <>
      {useKeplerVideoView && (
        <KeplerVideoView
          showControls={true}
          videoPlayer={video.current as VideoPlayer}
        />
      )}
    </>
  );
};
  1. Add this to the end of your manifeset.toml file
[wants]
[[wants.service]]
id = "com.amazon.mediametrics.service" # Required for metrics service

[[wants.service]]
id = "com.amazon.media.server"

[[wants.service]]
id = "com.amazon.gipc.uuid.*"

[[wants.service]]
id = "com.amazon.media.playersession.service"

[[wants.privilege]]
id = "com.amazon.devconf.privilege.accessibility" # Required for captions

[[wants.service]]
id = "com.amazon.mediabuffer.service"

[[wants.service]]
id = "com.amazon.mediatransform.service"

[[wants.service]]
id = "com.amazon.audio.stream"

[[wants.service]]
id = "com.amazon.audio.control"

[offers]
[[offers.service]]
id = "com.amazon.gipc.uuid.*"

[[wants.service]]
id = "com.amazon.audio.system"
  1. add this to your babel.config.js file
module.exports = {
    presets: [ ['module:metro-react-native-babel-preset', { useTransformReactJSXExperimental: true }] ],
    plugins: [
      [
        '@babel/plugin-transform-react-jsx',
        {
          runtime: 'automatic',
        },
      ],
    ]
  };
  1. run npm install and build your app
  2. test in the virtual device

Related documentation that helps rebuild this basic setup:

Thank you @Yorki_Bonilla for the detailed snippets. I was able to replicate the issue you have reported.
I’m working on a fix and will update you ASAP.

Warm regards,
Ivy

Hi @Yorki_Bonilla

The code here seems to be a little wrong as KeplerVideoView wasn’t being given proper dimensions. I have added the dimensions and iterated upon the code to test all the scenario together, the VPKGs for device and simulator are : vertivalvideo_armv7-1.vpkg. vertivalvideo_aarch64-1.vpkg

I do not see any issue in the device:

rbaid@bcd0749acb40 ~ % vda shell cat /etc/os-release NAME="OS" OE_VERSION="4.0.0" OS_MAJOR_VERSION="1" OS_MINOR_VERSION="1" RELEASE_ID="14" OS_VERSION="1.1" BRANCH_CODE="TV Ship day60" BUILD_DESC="OS 1.1 (TV Ship day60/10019)" BUILD_FINGERPRINT="4.0.193707.0(3072cab629675a74)/10019N:user/release-keys" BUILD_VARIANT="user" BUILD_TAGS="release-keys" BUILD_DATE="Wed Dec 10 01:52:36 UTC 2025" BUILD_TIMESTAMP="1765331556" VERSION_NUMBER="1401011001920"

But the issue persists on the simulator with build:

rbaid@bcd0749acb40 ~ % vda shell cat /etc/os-release NAME="OS" OE_VERSION="4.0.0" OS_MAJOR_VERSION="1" OS_MINOR_VERSION="1" RELEASE_ID="10" OS_VERSION="1.1" BRANCH_CODE="TV Ship" BUILD_DESC="OS 1.1 (TV Ship/10240300)" BUILD_FINGERPRINT="1.0.24030.0(9a1d8dfa7da5d600)/10240300N:user/dev-keys" BUILD_VARIANT="user" BUILD_TAGS="dev-keys" BUILD_DATE="Thu Sep 25 10:32:58 UTC 2025" BUILD_TIMESTAMP="1758796378" VERSION_NUMBER="1002034030030"

From the logs I can see that the Media player is running into error while initiating the playback:

// No code found error Jan 05 14:24:30.681889 amazon-b4dccd9f80950a96 local0.err r.vertivalvideo[2784]: 1637 E GSTLOG: 0x7f880c6860, ERROR , keplermxformwrapper, mediaxformwrapper.cpp, 1003, MediaTransformWrapper, <video-decoder>, !!! no matching codec found Jan 05 14:24:30.681896 amazon-b4dccd9f80950a96 local0.err r.vertivalvideo[2784]: 1637 E GSTLOG: 0x7f880c6860, ERROR , keplermediaxformviddec, gstmediaxformviddec.cpp, 1243, gst_mediaxform_vid_dec_set_format, <video-decoder>, mediaxform_create failed Jan 05 14:24:30.682062 amazon-b4dccd9f80950a96 local0.err r.vertivalvideo[2784]: 1637 E GSTLOG: 0x7f880c6860, ERROR , keplermxformwrapper, mediaxformwrapper.cpp, 1003, MediaTransformWrapper, <video-decoder>, !!! no matching codec found Jan 05 14:24:30.682069 amazon-b4dccd9f80950a96 local0.err r.vertivalvideo[2784]: 1637 E GSTLOG: 0x7f880c6860, ERROR , keplermediaxformviddec, gstmediaxformviddec.cpp, 1243, gst_mediaxform_vid_dec_set_format, <video-decoder>, mediaxform_create failed // Playback errored out Jan 05 14:24:30.823487 amazon-b4dccd9f80950a96 local0.err r.vertivalvideo[2784]: 1631 E MEDIA_PLAYER:DefaultMediaPlayer.cpp(4786) bus_call [0x7f84007650] Error: Internal data stream error., domain: 2669, code: 1 Jan 05 14:24:30.823493 amazon-b4dccd9f80950a96 local0.err r.vertivalvideo[2784]: 1631 E MEDIA_PLAYER:DefaultMediaPlayer.cpp(4055) translateToPlayerError GST stream error: 1

We are working on a solution for the VVD, in the meantime, can you please test this out on the device once?

PFA the video:

Warm regards,
Ivy

do you mind sharing your code? Looks like an improvement.. (you can just share what changed instead of all if that is too much)

So i can copy it and try to understand what changed.

I haven’t test in a physical device, I only have a non-select firestick. (lite and 4k one).. I was developing the application testing it directly in the virtual device. (Not sure if I can test in those devices or not to be honest.. which one did you use?)

I’ll soon get one firestick select and test directly.

Hi @Yorki_Bonilla

Here’s the code snippets we used. Please try this out and let me know if you need more help.

App.tsx

import React, {useEffect, useState} from 'react';
import {Text, View, TouchableOpacity, StyleSheet} from 'react-native';
import {VideoPlayerScreen} from './components/VideoPlayerScreen';

// Video test configurations
const VIDEO_OPTIONS = [
  {
    id: 'vertical_9_16',
    title: '9:16 Vertical Video (BUG - Shows Black Screen)',
    url: 'https://www.dropbox.com/scl/fi/dkmgxfo6hxbvzwuknrrk6/HunterClickerOpenBeta2.mp4?rlkey=rlg5oyyf6cy55ne7eouh3h4wv&e=1&st=xsdf77ug&raw=1',
    buttonColor: '#e74c3c', // Red - indicates bug
  },
  {
    id: 'vertical_converted_16_9',
    title: '16:9 Converted Video (Works)',
    url: 'https://www.dropbox.com/scl/fi/pnpqk09fhcvhaothbrp5e/Hunterclickeropenbeta2Ratio.mp4?rlkey=h4kebem0ib9m7r83bqqw264lf&e=1&st=dwn60pm5&raw=1',
    buttonColor: '#27ae60', // Green - works
  },
  {
    id: 'horizontal',
    title: 'Horizontal Video (Works)',
    url: 'https://www.dropbox.com/scl/fi/9e1uare2s3rn617yljonv/La-gloria-de-Dios2.mp4?rlkey=wkcr4j6fjzspdi0c2rkf9z6fq&st=hyzlx7z4&raw=1',
    buttonColor: '#27ae60', // Green - works
  },
];

type SelectedVideo = {
  url: string;
  title: string;
} | null;

export const App = () => {
  const [currentScreen, setCurrentScreen] = useState<'welcome' | 'player'>(
    'welcome',
  );
  const [selectedVideo, setSelectedVideo] = useState<SelectedVideo>(null);

  useEffect(() => {
    console.log('currentScreen changed to: ', currentScreen);
  }, [currentScreen]);

  const loadVideo = (video: typeof VIDEO_OPTIONS[0]) => {
    setSelectedVideo({url: video.url, title: video.title});
    setCurrentScreen('player');
  };

  const handleClose = () => {
    setCurrentScreen('welcome');
    setSelectedVideo(null);
  };

  let content = null;

  if (currentScreen === 'welcome') {
    console.log('loading welcome screen');
    content = (
      <View style={styles.menuContainer}>
        <Text style={styles.headerText}>Video Aspect Ratio Test</Text>
        <Text style={styles.subHeaderText}>
          PROJVEGA-357155: Testing 9:16 video playback issue
        </Text>
        <View style={styles.buttonContainer}>
          {VIDEO_OPTIONS.map((video) => (
            <TouchableOpacity
              key={video.id}
              style={[
                styles.loadMenuButton,
                {backgroundColor: video.buttonColor},
              ]}
              activeOpacity={0.7}
              onPress={() => loadVideo(video)}>
              <Text style={styles.buttonText}>{video.title}</Text>
            </TouchableOpacity>
          ))}
        </View>
      </View>
    );
  } else if (currentScreen === 'player' && selectedVideo) {
    console.log('loading player screen');
    content = (
      <VideoPlayerScreen
        onClose={handleClose}
        videoUrl={selectedVideo.url}
        videoTitle={selectedVideo.title}
      />
    );
  } else {
    console.log('invalid screen, defaulting to welcome screen');
    setCurrentScreen('welcome');
  }

  return (
    <View style={styles.outerContainer}>
      <View
        style={
          currentScreen === 'player'
            ? styles.playerContainer
            : styles.container
        }>
        {content}
      </View>
    </View>
  );
};

// ------------------------------------------------------------------
// STYLES
// ------------------------------------------------------------------
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  playerContainer: {
    flex: 1,
    width: '100%',
    height: '100%',
  },
  outerContainer: {
    flex: 1,
    backgroundColor: 'black',
  },
  menuContainer: {
    alignItems: 'center',
    padding: 40,
  },
  headerText: {
    color: 'white',
    fontSize: 48,
    fontWeight: 'bold',
    marginBottom: 10,
    textAlign: 'center',
  },
  subHeaderText: {
    color: '#aaa',
    fontSize: 24,
    marginBottom: 40,
    textAlign: 'center',
  },
  buttonContainer: {
    gap: 20,
  },
  loadMenuButton: {
    borderRadius: 12,
    paddingVertical: 25,
    paddingHorizontal: 40,
    minWidth: 600,
    alignItems: 'center',
    marginVertical: 10,
  },
  buttonText: {
    color: 'white',
    fontSize: 22,
    fontWeight: 'bold',
    textAlign: 'center',
  },
});

Link.tsx

import React, {useState} from 'react';
import {Image, StyleSheet, Text, TouchableOpacity, View} from 'react-native';

interface LinkProps {
  linkText: string;
  onPress: Function;
  testID?: string;
}

export const Link = ({linkText, onPress, testID}: LinkProps) => {
  const [focused, setFocused] = useState(false);

  return (
    <>
      <TouchableOpacity
        style={[styles.linkContainer, focused && styles.focusedContainer]}
        onPress={() => onPress()}
        onFocus={() => setFocused(true)}
        onBlur={() => setFocused(false)}
        testID={testID}>
        <View style={styles.linkTextContainer}>
          {focused ? (
            <Image source={require('../assets/focusedStar.png')} />
          ) : (
            <Image source={require('../assets/star.png')} />
          )}
          <Text style={styles.linkText}>{linkText}</Text>
        </View>
      </TouchableOpacity>
    </>
  );
};

const styles = StyleSheet.create({
  linkContainer: {
    width: 420,
    paddingBottom: 10,
    borderBottomWidth: 5,
    borderBottomColor: 'transparent',
  },
  focusedContainer: {
    borderBottomWidth: 5,
    borderBottomColor: '#ff9900',
  },
  linkTextContainer: {
    display: 'flex',
    alignItems: 'center',
    flexDirection: 'row',
    marginLeft: 200,
    width: 300,
  },
  linkText: {
    color: 'white',
    fontSize: 45,
    marginLeft: 30,
  },
});

VideoPlayerScreen.tsx

import React, {useRef, useEffect, useState} from 'react';
import {BackHandler, View, StyleSheet, Text} from 'react-native';
import {
  VideoPlayer,
  KeplerVideoView,
} from '@amazon-devices/react-native-w3cmedia';

type VideoConfigScreenProps = {
  onClose: () => void;
  videoUrl: string;
  videoTitle: string;
};

export const VideoPlayerScreen: React.FC<VideoConfigScreenProps> = ({
  onClose,
  videoUrl,
  videoTitle,
}) => {
  const video = useRef<VideoPlayer | null>(null);
  const [useKeplerVideoView, setUseKeplerVideoView] = useState(false);

  useEffect(() => {
    console.log('loaded videoPlayerScreen with URL:', videoUrl);
    initializingPreBuffering();

    const back = BackHandler.addEventListener('hardwareBackPress', () => {
      video.current?.pause();
      onClose();
      return true;
    });

    return () => {
      video.current?.deinitialize();
      back.remove();
    };
  }, []);

  // -------------------------------------------------
  // PLAYER INITIALIZATION
  // -------------------------------------------------
  const initializingPreBuffering = async () => {
    video.current = new VideoPlayer();
    await video.current.initialize();

    video.current.autoplay = true;
    // video.current.loop = true;
    // video.current.muted = true;

    video.current.src = videoUrl;
    console.log('Playing video:', videoTitle);

    setUseKeplerVideoView(true);
  };

  // Add KeplerVideoView component to the render tree
  return (
    <View style={styles.container}>
      <View style={styles.titleContainer}>
        <Text style={styles.titleText}>{videoTitle}</Text>
      </View>
      <View style={styles.videoContainer}>
        {useKeplerVideoView && (
          <KeplerVideoView
            style={styles.videoPlayer}
            showControls={true}
            videoPlayer={video.current as VideoPlayer}
          />
        )}
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    width: '100%',
    height: '100%',
    backgroundColor: 'black',
  },
  titleContainer: {
    paddingVertical: 10,
    paddingHorizontal: 20,
    backgroundColor: 'rgba(0, 0, 0, 0.7)',
  },
  titleText: {
    color: 'white',
    fontSize: 20,
    fontWeight: 'bold',
    textAlign: 'center',
  },
  videoContainer: {
    flex: 1,
  },
  videoPlayer: {
    flex: 1,
    width: '100%',
    height: '100%',
  },
});

Package.json

{
  "name": "@amazon-devices/vertivalvideo",
  "version": "0.0.1",
  "private": true,
  "files": ["dist"],
  "scripts": {
    "clean": "rm -rf node_modules buildinfo.json dist build",
    "start": "react-native start",
    "test": "jest --colors ",
    "test:snapshot": "jest --colors --updateSnapshot",
    "lint": "eslint src test --ext .ts,.tsx",
    "lint:fix": "eslint src test --ext .ts,.tsx --fix",
    "build:release": "react-native build-kepler --build-type Release",
    "build:debug": "react-native build-kepler --build-type Debug",
    "build:app": "npm-run-all build:release",
    "build": "npm-run-all build:release",
    "release": "npm-run-all lint test build:app"
    },
  "dependencies": {
    "@amazon-devices/react-native-kepler": "^2.0.0",
    "@amazon-devices/react-native-w3cmedia": "~2.1.80",
    "react": "18.2.0",
    "react-native": "0.72.0"
  },
  "devDependencies": {
    "@amazon-devices/kepler-cli-platform": "^0",
    "@react-native/eslint-config": "0.72.2",
    "@react-native/metro-config": "^0.72.6",
    "@react-native-community/cli": "11.3.2",
    "@testing-library/react-native": "^7.2.0",
    "@tsconfig/react-native": "^3.0.2",
    "@types/jest": "^28.0.0",
    "@types/react": "^18.0.24",
    "@types/react-test-renderer": "^18.0.0",
    "@typescript-eslint/eslint-plugin": "^5.30.0",
    "babel-jest": "^28.0.0",
    "eslint": "^8.12.0",
    "jest": "^28.0.0",
    "metro-react-native-babel-preset": "^0.76.5",
    "mustache": "^4.2.0",
    "npm-run-all": "^4.1.5",
    "prettier": "^2.6.2",
    "react-test-renderer": "18.2.0",
    "ts-jest": "^28.0.0",
    "typescript": "4.8.4"
  },
  "kepler": {
    "projectType": "application",
    "appName": "vertivalvideo",
    "targets": ["tv"]
  }
}

Manifest.toml

schema-version = 1

[package]
title = "Basic UI React Native Application for project vertivalvideo"
version = "0.1.0"
id = "com.amazondeveloper.vertivalvideo"

[components]
[[components.interactive]]
id = "com.amazondeveloper.vertivalvideo.main"
runtime-module = "/com.amazon.kepler.keplerscript.runtime.loader_2@IKeplerScript_2_0"
launch-type = "singleton"
categories = ["com.amazon.category.main"]

[wants]
[[wants.service]]
id = "com.amazon.mediametrics.service" # Required for metrics service

[[wants.service]]
id = "com.amazon.media.server"

[[wants.service]]
id = "com.amazon.gipc.uuid.*"

[[wants.service]]
id = "com.amazon.media.playersession.service"

[[wants.privilege]]
id = "com.amazon.devconf.privilege.accessibility" # Required for captions

[[wants.service]]
id = "com.amazon.mediabuffer.service"

[[wants.service]]
id = "com.amazon.mediatransform.service"

[[wants.service]]
id = "com.amazon.audio.stream"

[[wants.service]]
id = "com.amazon.audio.control"

[[wants.service]]
id = "com.amazon.audio.system"

[offers]
[[offers.service]]
id = "com.amazon.gipc.uuid.*"

Warm regards,
Ivy