1.1.7 • Published 28 days ago

react-tv-player v1.1.7

Weekly downloads
-
License
MIT
Repository
github
Last release
28 days ago

https://lewhunt.github.io/react-tv-player/

Installation

npm install react-tv-player

Usage

Just import the player and render it in your app or page with props:

import { TVPlayer } from "react-tv-player";

function App() {
  return (
    <>
      <TVPlayer url="https://www.youtube.com/watch?v=SkVqJ1SGeL0" />
    </>
  );
}

👉 Try out the Demo (on TV and desktop browsers)

The demo source code App.tsx illustrates how the component can be initialised with more props such as metadata, custom buttons, preview images and multiple media, enabling the user to cycle through videos with next/previous buttons:

<TVPlayer
  title={mediaList[mediaIndex].title}
  subTitle={mediaList[mediaIndex].subTitle}
  url={mediaList[mediaIndex].url}
  light={mediaList[mediaIndex].preview}
  customButtons={customButtons}
  mediaCount={mediaList.length}
  onLikePress={handleLike}
/>

https://github.com/lewhunt/react-tv-player/assets/9886284/7baa4b75-491b-49f3-8cf1-698ae7f55941

Why Another Player?

I've dedicated years working with various OTT players on big-screen devices. During this journey, two persistent challenges surfaced time and again: performant UI and compatible media encodings. These hurdles often forced us to heavily customise libraries and tackle streaming difficulties, leading to added costs and frustrating delays. 😫

Enter ReactTVPlayer, an open-source media player component for TV devices that lowers the barrier to entry and seamlessly integrates with your React applications. :muscle:

What Sets It Apart?

It's designed for TV experiences out of the box, complete with customisable UI buttons and intuitive cursor plus arrow key navigation. 🎮 In addition to handling HLS and Dash streams effortlessly, it tackles the formidable challenge of playing YouTube and Vimeo urls directly on TV, saving you the hassle and cost of additional video encoding. 🎉

How Does It Work?

Under the hood, this component harnesses the power of open-source libraries like Norigin Media's spatial navigation hook. It builds upon the excellence of React Player, which utilises hls.js and dash.js. Powered by React TypeScript (although you don't need to use TypeScript to make the most of it), this library is packaged efficiently using Vite, making integration a breeze. 🙌

Key Features

  • Versatility: Customisable UI buttons, title metadata and preview images to suit your needs. It can effortlessly handle a variety of URLs, from mp4 file paths and HLS/DASH streams to services like YouTube and Vimeo.
  • Intuitive Navigation: The player has been designed with TV experiences in mind. Cursor and arrow-key navigation make the user experience smooth and intuitive across big-screen platforms.
  • YouTube Integration: One of its unique strengths is its ability to play URLs directly from the likes of YouTube, Vimeo, SoundCloud and Twitch, eliminating the need for additional video encoding when it's not needed.
  • DRM Considerations: While it supports HLS AES Encryption, it’s built with flexibility in mind, allowing for future DRM integration with hls.js and dash.js.
  • Broad Device Support: From Amazon Fire TV, LG webOS and Samsung Tizen Smart TVs to Xbox consoles and desktop web browsers, ReactTVPlayer covers most big-screen devices running web apps with post-2017 Chromium browsers.

Props

The full list of props are below. Media related values such as playing, loop and muted are also mapped to state which can be accessed via the useTVPlayerStore hook instead of updating props.

PropDescriptionDefault
urlThe url of the media to play   This can be an embedded url from YouTube/SoundCloud, a file path or a HLS or Dash manifest stream
playingSet to true or false to pause or play the media.   Set to true to autoplay the media (muted may also be needed in some browsers)false
loopSet to true to loop the mediafalse
controlsSet to true to display native HTML5 media controls instead of custom TV Player UI controlsfalse
lightSet to true or a url string to show a preview image, which then loads the full player on selecting play  Pass in true to use the default preview image associated with an embeded media url (e.g. YouTube/SoundCloud urls)  Pass in an image URL to override any default preview imagefalse
volumeSet the volume of the player, between 0 and 1null
mutedSet to true to mute the player  may be required if you intend to autoplay mediafalse
playbackRateSet the playback rate of the player  Only supported by YouTube, Wistia, and file paths1
disableFullscreenSet to true to disable the defaulted fullscreen width and height of the player.   Width and height values below should be definedfalse
widthSet the width of the player when fullscreen is disabled100%
heightSet the height of the player when fullscreen is disabled350px
styleAdd inline styles to the root element{}
customButtonsSpecify a collection of custom buttons for the player UI   A set of default buttons will be used otherwise.null
titleSet a string title for the current media.  Embedded media urls such as YouTube will attempt to pull in the default media title if not overridden here.
subTitleSet a string sub-title for the current media.  Embedded media urls such as YouTube will attempt to pull in the default author name if not overridden here.
mediaCountSet the total number of media items if you have multiple media and want player to display next and previous buttons0
mediaIndexSet the initial media index number if you have multiple media and want player to handle next and previous buttons0
hideControlsOnArrowUpSet to true to hide the player UI by using the up arrow key when focussed on the player buttonsfalse

Callback Props

Callback props take a function that gets fired on various player events and UI button actions:

PropDescription
onReadyCalled when media is loaded and ready to play. If playing is set to true, media will play immediately
onStartCalled when media starts playing
onPlayCalled when media starts or resumes playing after pausing or buffering
onPauseCalled when media is paused
onBufferCalled when media starts buffering
onEndedCalled when media finishes playing  Does not fire when loop is set to true
onErrorCalled when an error occurs whilst attempting to play media
onSkipBackPressCalled when the Skip Back button is pressed
onSkipForwardPressCalled when the Skip Forward button is pressed
onPreviousPressCalled when the Previous button is pressed
onNextPressCalled when the Next button is pressed
onLikePressCalled when the Like button is pressed
onLoopPressCalled when the Loop button is pressed
onMutePressCalled when the Mute button is pressed
onFullscreenPressCalled when the Fullscreen button is pressed

Custom Buttons

As illustrated in the sample demo app, the player can be overridden with custom buttons. There is a selection of pre-built action types with their own icons and behaviours or you can add your own with the "custom" action type.

import { TVPlayer, TVPlayerButtonProps } from "react-tv-player";
import { faGithub } from "@fortawesome/free-brands-svg-icons";

const customButtons: TVPlayerButtonProps[] = [
  { action: "loop", align: "left" },
  { action: "like", align: "left" },
  { action: "previous", align: "center" },
  { action: "playpause", align: "center" },
  { action: "next", align: "center" },
  { action: "mute", align: "right" },
  {
    action: "custom",
    align: "right",
    label: "About",
    faIcon: faGithub,
    onPress: () => {
      window.location.href = "https://github.com/lewhunt/react-tv-player";
    },
  },
];

<TVPlayer
  url="https://www.youtube.com/watch?v=SkVqJ1SGeL0"
  customButtons={customButtons}
/>;
Button PropsDescription
actionChoose from custom or one of the pre-built actions: like, loop, mute,next,playpause,previous,skipforward, skipback, fullscreen
alignAlignment of the button. Choose from left,center, right
labelA hint text label to appear below the current button in focus. Pre-built button actions use relevent labels.
faIconA font-awesome icon. Pre-built button actions use relevent icons.
onPressCalled when a button is pressed. Pre-built button actions have their own behaviours.
onReleaseCalled when a button is released. Currently unused.
isSelectedFillAllows support of toggle behaviour (in the form of a button fill) when set to true.
disablePrevents button action when set to true.

useTVPlayerStore Hook

For more control you can import the useTVPlayerStore custom hook to globally access player state (zustand store). View the sample app and the TVPlayerUI inner component for examples of use. Below shows the basics:

// 1. import useTVPlayerStore
import { TVPlayer, useTVPlayerStore } from "react-tv-player";

// 2. get state values (there are more availble, see TVPlayerUI.ts for reference)
const actions = useTVPlayerStore((s) => s.actions);
const playing = useTVPlayerStore((s) => s.playing);
const player = useTVPlayerStore((s) => s.player);
const likeToggle = useTVPlayerStore((s) => s.likeToggle);
s;

const logPlaybackState = () => console.log(playing);

//3. set state using the actions object
const handleLike = () => {
  console.log("like button pressed");
  actions.setLikeToggle(!likeToggle);
};

const togglePlayback = () => {
  actions.setPlaying(!playing);
};

//4. access player instance methods via the player state
const customSeek = () => player.seekTo(player.getCurrentTime() + 10);

<TVPlayer
  url="https://www.youtube.com/watch?v=SkVqJ1SGeL0"
  onLikePress={handleLike}
/>;

Instance Methods

Use the state's player reference - as in the above example - to call instance methods on the player.

MethodDescription
seekTo(amount, type)Seek to the given number of seconds, or fraction if amount is between 0 and 1  type parameter lets you specify 'seconds' or 'fraction' to override default behaviour
getCurrentTime()Returns the number of seconds that have been played  Returns null if unavailable
getSecondsLoaded()Returns the number of seconds that have been loaded  Returns null if unavailable or unsupported
getDuration()Returns the duration (in seconds) of the currently playing media  Returns null if duration is unavailable
getInternalPlayer()Returns the internal player of whatever is currently playing  eg the YouTube player instance, or the <video> element when playing a video file  Use getInternalPlayer('hls') to get the hls.js player  Use getInternalPlayer('dash') to get the dash.js player  Returns null if the internal player is unavailable

👉 Try out the Demo (on TV and desktop browsers)

1.1.7

28 days ago

1.1.6

2 months ago

1.1.5

3 months ago

1.1.4

4 months ago

1.1.3

5 months ago

1.1.2

5 months ago

1.1.1

5 months ago

1.1.0

5 months ago

1.0.25

7 months ago

1.0.19

8 months ago

1.0.18

8 months ago

1.0.17

8 months ago

1.0.16

8 months ago

1.0.22

7 months ago

1.0.21

7 months ago

1.0.20

8 months ago

1.0.24

7 months ago

1.0.15

8 months ago

1.0.14

8 months ago

1.0.13

8 months ago

1.0.12

8 months ago

1.0.11

8 months ago

1.0.10

8 months ago

1.0.9

8 months ago

1.0.8

8 months ago

1.0.7

8 months ago

1.0.6

8 months ago

1.0.5

8 months ago

1.0.4

8 months ago

1.0.3

8 months ago

1.0.2

8 months ago

1.0.1

8 months ago

1.0.0

8 months ago

0.1.2

8 months ago

0.1.1

8 months ago

0.1.0

8 months ago

0.0.9

8 months ago

0.0.8

8 months ago

0.0.7

8 months ago

0.0.6

8 months ago

0.0.5

9 months ago

0.0.4

9 months ago

0.0.3

9 months ago

0.0.2

9 months ago

0.0.1

9 months ago