Giter VIP home page Giter VIP logo

react-responsive-video's Introduction

React Responsive Video

Pass all your video files (different aspect ratios and formats) to this React component, it will choose the best one for each browser and will avoid downloading the rest.

Summary

This library provides a React component that will allow you to have different video (and poster images) versions for different device sizes.

The HTML <video> tag does not allow you to have different sources for different media queries as <picture> does. This component solves this issue with a 2-step process (there is a more detailed description below):

  1. In Server Side Rendering (SSR), it paints a <picture> element with all your poster image sources.
  2. Once on the client, it is replaced with a <video> element with the right video sources and the right poster image source

It is important that the <picture> and the <video> elements have similar styles (i.e: width:100%;height:auto; ) so that replacing one by the other does not change the layout.

More details

It is very nice to be able to optimize your site performance by providing your browser with multiple URLs for each <picture>. The browser selects the best one based on the device size (via media queries) and the supported format. Add this piece of code and the browser will magicaly select the best file for your user

<picture>
  <source
    width="666"
    height="666"
    srcset="https://example.com/big.avif"
    type="image/avif"
    media="(min-width: 1200px)"
  />
  <source
    width="666"
    height="666"
    srcset="https://example.com/big.webp"
    type="image/webp"
    media="(min-width: 1200px)"
  />
  <source
    width="666"
    height="666"
    srcset="https://example.com/big.jpg"
    media="(min-width: 1200px)"
  />
  <source
    width="200"
    height="300"
    srcset="https://example.com/small.avif"
    type="image/avif"
  />
  <source
    width="200"
    height="300"
    srcset="https://example.com/small.webp"
    type="image/webp"
  />
  <source width="200" height="300" srcset="https://example.com/small.jpg" />
</picture>

With the video tag, you cannot add media queries in the <source>s. It is not so easy to send different resolutions (different aspect ratios and differnt content alltogehter) to different devices. There are some reasons why this is not natively supported in HTML.

The easy solution is to add one <video> element for each device size and hide the invalid ones with CSS. The drawback is that your browser will download one video file for each <video> (display:none does not avoid downloading the assets!)

This component provides the best solution. It downloads only one poster image and one video. It does this by being opinionated. It assumes that if the user changes the window width, it is OK to change the video sources accordingly. It assumed that the poster images of each size have the same resolution as the videos of that size. It is also assumed that the <picture> and the <video> tags that the component renders during the page load have similar styles (i.e: width:100%;height:auto; ).

How to use it?

Installation

You need to install this package via your preferred JS package manager. As an example, with NPM:

npm i @damiarita/react-responsive-video

Usage

You have all the details in the docs.

The most important prop of the component is sizes. It is an array. Each item of the array should have a media query, an array of video sources, an array of poster image sources, a height and a width. The media query must define the devices where the sources are valid. The video sources should be different formats of the same video (mp4, webm...). The poster image sources should be different formats of the same image (ideally the first frame of the video). The height of the width define the resolution of the poster images and videos (which should have the same resolution).

The component will create a <video> tag and some temporary <img> and <picture> tags. You can pass any props (id, className, alt, autoPlay...) to them via videoProps, pictureProps and imgProps.

This is an example of a call to the component

import ReactResponsiveVideo from '@damiarita/react-responsive-video';

<ReactResponsiveVideo
  videoProps={{
      id:"my-video",
      className:"responsive video",
      autoPlay:true,
      controls:true,
      muted:true
  }}
  pictureProps={{
      id:"poster-image",
      className:"responsive picture"
  }}
  imgProps={{
      alt:"Poster image of the video you are about to see"
  }}
  sizes={[
      {
        width: 2000,
        height: 972,
        mediaQuery: '(min-width: 1200px)',
        videoSources: [
          {
            url: 'https://www.example.com/big.mp4',
            format: 'video/mp4',
          },
          {
            url: 'https://www.example.com/big.webm',
            format: 'video/webm',
          },
        ],
        posterSources: [
          {
            url: 'https://www.example.com/big.avif',
            format: 'image/avif',
          },
          {
            url: 'https://www.example.com/big.webp',
            format: 'image/webp',
          },
          {
            url: 'https://www.example.com/big.jpg',
            format: 'image/jpeg',
          },
        ],
      },
      {
        width: 1024,
        height: 1024,
        videoSources: [
          {
            url: 'https://www.example.com/small.mp4',
            format: 'video/mp4',
          },
          {
            url: 'https://www.example.com/small.webm',
            format: 'video/webm',
          },
        ],
        posterSources: [
          {
            url: 'https://www.example.com/small.avif',
            format: 'image/avif',
          },
          {
            url: 'https://www.example.com/small.webp',
            format: 'image/webp',
          },
          {
            url: 'https://www.example.com/small.jpg',
            format: 'image/jpeg',
          },
        ],
      },
    ]}
/>

Make sure that your pictureProps and your videoProps give similar styles via class or style (i.e: width:100%;height:auto; ) so that replacing the <picture> by the <video> does not change the layout.

More details of what happens in the browser

There are three different moments during the page load of a page that contains the ReactResponsiveVideo component:

  1. Initial page load. If your website uses SSR, the component cannot evaluate the media queries and decide which video source to show to the browser. Therefore it only renders one <picture> element with all the <source>s
  2. Once on the browser, we can select the correct <video> s. Therefore, a <video> element it is rendered. Initially, it is rendered with display:none alongside the <picture> element. This is becasue we still don't know which poster image has been chosen by the browser. Adding the video to the DOM makes sure the browser begins downloading the video file.
  3. After the browser has loaded a poster image, the display:none is removed from the <video>, the poster property is added to it and the <picture> is removed from the DOM. While the video file loads, the user sees the poster image (just like in the previous step). If the video loads first, the same thing happens (we remove display:none and the picture element)

Contributing

Does this package almost solve your problem? Help me help you! Send a PR and let's discuss it!

Contributors

Christianjhm and I developed the idea for this component together.

License

This project is distributed under the MIT License. Check the LICENSE file for details!

react-responsive-video's People

Contributors

damiarita avatar deepsource-io[bot] avatar

Watchers

 avatar

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.