{"id":28094,"date":"2022-03-21T18:41:57","date_gmt":"2022-03-21T18:41:57","guid":{"rendered":"http:\/\/Build-a-Live-Event-Simulator-with-Recorded-Video"},"modified":"2022-03-21T18:41:57","modified_gmt":"2022-03-21T18:41:57","slug":"build-a-live-event-simulator-with-recorded-video","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/","title":{"rendered":"Build a Live Event Simulator with Recorded Video"},"content":{"rendered":"<div class=\"wp-block-cloudinary-markdown \"><p>Live streaming events have become more of the norm these last years. They give a sense of urgency to your content, boost online interaction between you and your users, and help reach a wider audience.<\/p>\n<p>This tutorial will walk through handling video player events by building a live event simulator in Next.js.<\/p>\n<h2>What we will be building<\/h2>\n<p>The live event simulator mimics live events where we want to play a video starting from a specified time. The video starting position for the user is adjusted based on how much time has passed since the actual video started. For example, a video that is 1 hour long but that started 45 minutes ago, would have any new user that visits the page automatically start at the 45 minute mark in the video time.<\/p>\n<p>Also when the recorded video is done, we want an overlay with the text \u2018This stream has ended\u2019 and our native player controls hidden.<\/p>\n<h2>CodeSandbox<\/h2>\n<p>This project was completed in a Codesandbox. To get started quickly, fork the <a href=\"https:\/\/codesandbox.io\/s\/nextjs-live-event-3lulr?file=\/pages\/index.js\">codesandbox<\/a> or run the project.<\/p>\n<\/div>\n  \n  <div class=\"wp-block-cloudinary-code-sandbox \">\n    <iframe\n      src=\"https:\/\/codesandbox.io\/embed\/nextjs-live-event?theme=dark&amp;codemirror=1&amp;highlights=&amp;editorsize=50&amp;fontsize=14&amp;expanddevtools=0&amp;hidedevtools=0&amp;eslint=0&amp;forcerefresh=0&amp;hidenavigation=0&amp;initialpath=%2F&amp;module=&amp;moduleview=0&amp;previewwindow=&amp;view=&amp;runonclick=1\"\n      height=\"500\"\n      style=\"width: 100%;\"\n      title=\"Live Event Simulator\"\n      loading=\"lazy\"\n      allow=\"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking\"\n      sandbox=\"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts\"\n    ><\/iframe>\n  <\/div>\n\n  <div class=\"wp-block-cloudinary-markdown \"><p>GitHub Repository<\/p>\n<p><a href=\"https:\/\/github.com\/Iheanacho-ai\/live-event-simulator\">https:\/\/github.com\/Iheanacho-ai\/live-event-simulator<\/a><\/p>\n<h2>Prerequisites<\/h2>\n<p>To get the most out of this tutorial, we need the following:<\/p>\n<ul>\n<li>A basic understanding of CSS and React.<\/li>\n<li>Node and it\u2019s package manager, <code>npm<\/code>. Run the command <code>node -v<\/code> &amp;&amp; <code>npm -v<\/code> to verify we have them installed, or install them from <a href=\"https:\/\/nodejs.org\/en\/\">here<\/a>.<\/li>\n<li>Alternatively, we can use another package manager, <a href=\"https:\/\/yarnpkg.com\/\">Yarn<\/a>.<\/li>\n<li>Understanding Next.js would help us follow through with this tutorial quicker, but it is not a necessity.<\/li>\n<\/ul>\n<h2>Setting up the Next.js application<\/h2>\n<p><a href=\"https:\/\/nextjs.org\/\">Next.js<\/a> is an open-source React framework that enables us to build server-side rendering, static web applications. With built-in CSS, Sass, and any CSS-in-JS library support, Next.js allows us to create web applications easily.<\/p>\n<p>To create our Next.js app, we go to our terminal or command prompt, using the git <code>cd<\/code> command, we navigate to the directory we want our app to be created in.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\">    cd <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">name<\/span> <span class=\"hljs-attr\">of<\/span> <span class=\"hljs-attr\">the<\/span> <span class=\"hljs-attr\">directory<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Next we run:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">    npx create-next-app\n    <span class=\"hljs-comment\"># or<\/span>\n    yarn create next-app\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<!-- Hi, removing the 's I' in code above -->\n<p>We then change directory to the app we just created and run it.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\">    cd <span class=\"hljs-tag\">&lt; <span class=\"hljs-attr\">name<\/span> <span class=\"hljs-attr\">of<\/span> <span class=\"hljs-attr\">our<\/span> <span class=\"hljs-attr\">app<\/span> &gt;<\/span>\n    npm run dev\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>To see our app in our browser, go to <code>http:\/\/localhost:3000\/<\/code><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/media_jams\/s_EEF0CADCB8202E0C4228163C3069F5FC30159D16FE318256EE9DB9AFE46013C9_1630266547827_welcome+nextjs.png\" alt=\"\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1346\" height=\"619\"\/><\/p>\n<h2>Installing dependencies<\/h2>\n<p>In this section of the tutorial we will install React Player to handle our video and video player events.<\/p>\n<p><strong>React Player<\/strong>\n<a href=\"https:\/\/www.npmjs.com\/package\/react-player\">React Player<\/a> is a React component for playing a variety of URLs. React Player allows us to create and personalize our video player with callback props for almost every player event. It also offers an excellent media experience in web applications.<\/p>\n<p>To install React Player in our app, we run the command.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">    npm install react-player \n    <span class=\"hljs-comment\"># or<\/span>\n    yarn add react-player\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<h2>Creating the video player<\/h2>\n<p>To create our video player, we first create a <code>component<\/code> folder in the root of our app. In this folder we will create our <code>video-player.jsx<\/code> file.<\/p>\n<p>To use the <code>ReactPlayer<\/code> component, we import it from the <code>react-library<\/code> into our <code>video-player.jsx<\/code> file.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> React <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'react'<\/span>\n    <span class=\"hljs-keyword\">import<\/span> ReactPlayer <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'react-player'<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>This <code>ReactPlayer<\/code> component allows us to use a wide range of props. We then pass values into these props to personalize our player.<\/p>\n<p>In the next piece of code, we use the <code>url<\/code> prop, the <code>controls<\/code> prop, and finally the <code>playing<\/code> prop.<\/p>\n<p>The <code>url<\/code> prop takes in a value that points to the media path we are looking to play. To display the native player controls, we use the <code>controls<\/code> prop. This prop takes in a boolean value. When the <code>controls<\/code> prop set to true, the controls are displayed, and hidden when set to false.\nNext, we have the <code>playing<\/code> prop. The <code>playing<\/code> prop plays or pauses the media when set to true or false, respectively.<\/p>\n<p>The <code>ReactPlayer<\/code> component also allows us to set the width and height of the player using the <code>width<\/code> and <code>height<\/code> prop, respectively.\nFailing to do so sets our video player to this default dimensions <code>width: 640px; height: 360px;<\/code> which we will use in this tutorial.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> React <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'react'<\/span>\n    <span class=\"hljs-keyword\">import<\/span> ReactPlayer <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'react-player'<\/span>\n    <span class=\"hljs-keyword\">const<\/span> VideoPlayer = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n        <span class=\"hljs-keyword\">return<\/span>(\n            <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"video-player\"<\/span>&gt;<\/span>\n                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ReactPlayer<\/span> \n                <span class=\"hljs-attr\">url<\/span>= <span class=\"hljs-string\">'https:\/\/res.cloudinary.com\/amarachi-2812\/video\/upload\/v1630370229\/videoplayback_1_pr2hzi.mp4'<\/span>\n                <span class=\"hljs-attr\">playing<\/span> = <span class=\"hljs-string\">{true}<\/span> \n                <span class=\"hljs-attr\">controls<\/span> = <span class=\"hljs-string\">{true}<\/span>\n                \/&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n        )\n    }\n\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> MemoizedVideoPlayer = React.memo(VideoPlayer);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>We memoized the video player component to prevent any re-rendering triggered by its parent component, except a dependency changes.<\/p>\n<p>&lt;!\u2014 It looks like you are missing \u2018\/&gt;\u2019 closing the <code>&lt;reactplayer&gt;<\/code> div \u2014&gt;<\/p>\n<p>Setting our <code>playing<\/code> and <code>controls<\/code> prop to true, our video player plays our video as it renders on our screen and displays our native player controls.<\/p>\n<p>Next, we import our video player to our <code>index.js<\/code> file to see our video player in our browser.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> Head <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'next\/head'<\/span>\n    <span class=\"hljs-keyword\">import<\/span> styles <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'..\/styles\/Home.module.css'<\/span>\n    <span class=\"hljs-keyword\">import<\/span> { MemoizedVideoPlayer } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'..\/component\/video-player'<\/span>;\n    \n    <span class=\"hljs-keyword\">const<\/span> Home = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n      <span class=\"hljs-keyword\">return<\/span>(\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.container}<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Head<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">title<\/span>&gt;<\/span>Live Simulator<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">title<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"description\"<\/span> <span class=\"hljs-attr\">content<\/span>=<span class=\"hljs-string\">\"Live Event Simulator Created by Nextjs\"<\/span> \/&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"icon\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"\/favicon.ico\"<\/span> \/&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Head<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">main<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.main}<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>= <span class=\"hljs-string\">'live-event-container'<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">MemoizedVideoPlayer<\/span>\/&gt;<\/span>\n           <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">main<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n      )\n    }\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> Home;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>With that we have our video player set up.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/media_jams\/s_EEF0CADCB8202E0C4228163C3069F5FC30159D16FE318256EE9DB9AFE46013C9_1633792155820_basic+videoplayer+setup.gif\" alt=\"\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"480\" height=\"258\"\/><\/p>\n<h2>Creating the Live Simulation<\/h2>\n<p>To create a live simulation in our app, we start by importing React and the <code>useState<\/code> hook in our <code>index.js<\/code> file.<\/p>\n<p>The <code>useState<\/code> hook allows our functional component to have states in them.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> React, { useState } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'react'<\/span>;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Next, using the <code>useState<\/code> hook, we create pieces of state to control different properties of our video player, in a <code>Home<\/code> component.<\/p>\n<p>&lt;!\u2014 Can you please mention to place this and the next piece of code within the home constant before return (..) \u2014&gt;<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">const<\/span> Home = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n  <span class=\"hljs-keyword\">const<\/span> &#91;startTime, setStartTime] = useState(<span class=\"hljs-number\">1633538276355<\/span>);\n  <span class=\"hljs-keyword\">const<\/span> &#91;controls, setControls] = useState(<span class=\"hljs-literal\">true<\/span>);\n  <span class=\"hljs-keyword\">const<\/span> &#91;ended, setEnded] = useState(<span class=\"hljs-literal\">false<\/span>);\n  <span class=\"hljs-keyword\">const<\/span> &#91;duration, setDuration] = useState(<span class=\"hljs-literal\">null<\/span>);\n  <span class=\"hljs-keyword\">const<\/span> &#91;playing, setPlaying] = useState(<span class=\"hljs-literal\">true<\/span>);\n\n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.container}<\/span>&gt;<\/span>\n      \n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n  );\n};\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> Home;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<ul>\n<li>\n<code>startTime<\/code> : Set to an initial value of 1630430724714, this is the time in milliseconds we want our \u2018live event\u2019 to start (we shall discuss how to find the time in milliseconds in the functions section of this tutorial below).<\/li>\n<li>\n<code>controls<\/code> : Set to an initial value of true, this property sets the <code>controls<\/code> prop on the <code>ReactPlayer<\/code> component.<\/li>\n<li>\n<code>ended<\/code> : Set to an initial value of false. It would be set to true when the video ends. We will use the <code>ended<\/code> variable to conditionally render our overlay.<\/li>\n<li>\n<code>duration<\/code> : Stores the duration of the video we are playing in seconds.<\/li>\n<li>\n<code>playing<\/code> : Controls when our video starts or stops playing, it will be set to an initial value of <code>true<\/code> as we want our video to be playing when it mounts, unless the video has ended.<\/li>\n<\/ul>\n<p>Next, our control functions.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">let<\/span> date = <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Date<\/span>();\n    <span class=\"hljs-keyword\">let<\/span> currentTime = date.getTime()\n    <span class=\"hljs-keyword\">let<\/span> timePlayed = ( currentTime - startTime ) % <span class=\"hljs-number\">1000<\/span>;\n    \n    <span class=\"hljs-keyword\">const<\/span> endVideo = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n      <span class=\"hljs-keyword\">if<\/span> (controls === <span class=\"hljs-literal\">false<\/span> &amp;&amp; ended === <span class=\"hljs-literal\">true<\/span>) {\n        <span class=\"hljs-keyword\">if<\/span> (playing === <span class=\"hljs-literal\">false<\/span>) {\n          <span class=\"hljs-keyword\">return<\/span>;\n        } <span class=\"hljs-keyword\">else<\/span> {\n          setPlaying(<span class=\"hljs-literal\">false<\/span>);\n        }\n      } <span class=\"hljs-keyword\">else<\/span> {\n        setControls(<span class=\"hljs-literal\">false<\/span>);\n        setEnded(<span class=\"hljs-literal\">true<\/span>);\n        setPlaying(<span class=\"hljs-literal\">false<\/span>);\n      }\n    };\n    \n    <span class=\"hljs-keyword\">const<\/span> videoDuration = <span class=\"hljs-function\"><span class=\"hljs-params\">num<\/span> =&gt;<\/span> {\n        setDuration( num )\n      }\n    \n    <span class=\"hljs-keyword\">if<\/span> (timePlayed &gt; duration){\n        endVideo()\n    }\n    \n     <span class=\"hljs-keyword\">const<\/span> restartLive = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n      <span class=\"hljs-keyword\">let<\/span> newDate = <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Date<\/span>();\n      <span class=\"hljs-keyword\">let<\/span> newStartTime = newDate.getTime();\n      setStartTime(newStartTime);\n      setEnded(<span class=\"hljs-literal\">false<\/span>);\n      setPlaying(<span class=\"hljs-literal\">true<\/span>);\n      setControls(<span class=\"hljs-literal\">true<\/span>);\n    };\n\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<h2>Getting the current time in milliseconds<\/h2>\n<p>The <code>date<\/code> variable in the code block above gets the current date using the JavaScript <code>new Date()<\/code> method. We then get the current time in milliseconds using the JavaScript <code>getTime()<\/code> method, and store it in the <code>currentTime<\/code> variable. The <code>timePlayed<\/code> variable gets the difference between the time our \u2018live event\u2019 started and the current time in seconds, this variable will be used to tell our video player what time in the player we want to seek to.<\/p>\n<p><strong>What happens when our video ends?<\/strong>\nThe <code>endVideo<\/code> function will get called when our video ends, even long after. The <code>endVideo<\/code> function has an <code>if else<\/code> block. This <code>if else<\/code> conditional checks if the <code>controls<\/code> variable is already <code>false<\/code> and the <code>ended<\/code> variable <code>true<\/code>, if they are, we go further to check if the <code>playing<\/code> variable is false, if our code passes all these checks, we want to return from the function.<\/p>\n<p>If, however, our code does not pass all these checks, we want to set<\/p>\n<ul>\n<li>\n<code>playing<\/code> to false to stop playing the video<\/li>\n<li>\n<code>controls<\/code> to false to hide the native player controls.<\/li>\n<\/ul>\n<p>We created a <code>videoDuration<\/code> function that takes in a <code>num<\/code> parameter, this parameter represents the duration of the media. This <code>videoDuration<\/code> function uses the <code>num<\/code> parameter to update the <code>duration<\/code> state variable.<\/p>\n<p>Next, we have an <code>if<\/code> block of code, this checks if the <code>timePlayed<\/code> variable (containing how much time has passed since the start of the live) is greater than the <code>duration<\/code>. If it is, we run the <code>endVideo<\/code> function.<\/p>\n<p><strong>Restarting the video<\/strong><\/p>\n<p>The <code>restartLive<\/code> function is used to restart the live event simulation.\nThe <code>newDate<\/code> variable gets the date the <code>restartLive<\/code> function ran, and the <code>newStartTime<\/code> variable stores the exact time in milliseconds this function ran. We pass in the <code>newStartTime<\/code> to the <code>setStartTime<\/code> function to reset the <code>startTime<\/code> variable.\nFinally, we set our <code>ended<\/code> variable to false, as we just started our simulation over again.<\/p>\n<!-- Fixed 'newStartTime' -->\n<p>Next, we add a button to run this <code>restartLive<\/code> function, with the <code>onClick<\/code> event handler.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\">    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">className<\/span>= <span class=\"hljs-string\">'reset-button'<\/span> <span class=\"hljs-attr\">onClick<\/span> = <span class=\"hljs-string\">{restartLive}<\/span>&gt;<\/span>Restart Live Simulation<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Our <code>index.js<\/code> file should like this.<\/p>\n<p><strong>The module imports and methods<\/strong><\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> Head <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next\/head\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> React, { useState } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { MemoizedVideoPlayer } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/component\/video-player\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> styles <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/styles\/Home.module.css\"<\/span>;\n    \n    <span class=\"hljs-keyword\">const<\/span> Home = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n      <span class=\"hljs-keyword\">const<\/span> &#91;startTime, setStartTime] = useState(<span class=\"hljs-number\">1633538276355<\/span>);\n      <span class=\"hljs-keyword\">const<\/span> &#91;controls, setControls] = useState(<span class=\"hljs-literal\">true<\/span>);\n      <span class=\"hljs-keyword\">const<\/span> &#91;ended, setEnded] = useState(<span class=\"hljs-literal\">false<\/span>);\n      <span class=\"hljs-keyword\">const<\/span> &#91;duration, setDuration] = useState(<span class=\"hljs-literal\">null<\/span>);\n      <span class=\"hljs-keyword\">const<\/span> &#91;playing, setPlaying] = useState(<span class=\"hljs-literal\">true<\/span>);\n    \n      <span class=\"hljs-keyword\">let<\/span> date = <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Date<\/span>();\n      <span class=\"hljs-keyword\">let<\/span> currentTime = date.getTime();\n      <span class=\"hljs-keyword\">let<\/span> timePlayed = (currentTime - startTime) % <span class=\"hljs-number\">1000<\/span>;\n    \n    \n      <span class=\"hljs-keyword\">const<\/span> endVideo = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n        <span class=\"hljs-keyword\">if<\/span> (controls === <span class=\"hljs-literal\">false<\/span> &amp;&amp; ended === <span class=\"hljs-literal\">true<\/span>) {\n          <span class=\"hljs-keyword\">if<\/span> (playing === <span class=\"hljs-literal\">false<\/span>) {\n            <span class=\"hljs-keyword\">return<\/span>;\n          } <span class=\"hljs-keyword\">else<\/span> {\n            setPlaying(<span class=\"hljs-literal\">false<\/span>);\n          }\n        } <span class=\"hljs-keyword\">else<\/span> {\n          setControls(<span class=\"hljs-literal\">false<\/span>);\n          setEnded(<span class=\"hljs-literal\">true<\/span>);\n          setPlaying(<span class=\"hljs-literal\">false<\/span>);\n        }\n      };\n    \n      <span class=\"hljs-keyword\">const<\/span> restartLive = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n        <span class=\"hljs-keyword\">let<\/span> newDate = <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Date<\/span>();\n        <span class=\"hljs-keyword\">let<\/span> newStartTime = newDate.getTime();\n        setStartTime(newStartTime);\n        setEnded(<span class=\"hljs-literal\">false<\/span>);\n        setPlaying(<span class=\"hljs-literal\">true<\/span>);\n        setControls(<span class=\"hljs-literal\">true<\/span>);\n      };\n    \n      <span class=\"hljs-keyword\">const<\/span> videoDuration = <span class=\"hljs-function\">(<span class=\"hljs-params\">num<\/span>) =&gt;<\/span> {\n        setDuration(num);\n      };\n    \n      <span class=\"hljs-keyword\">if<\/span> (timePlayed &gt; duration) {\n        endVideo();\n      }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p><strong>The rendered component<\/strong><\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.container}<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Head<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">title<\/span>&gt;<\/span>Live Simulator<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">title<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span>\n              <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"description\"<\/span>\n              <span class=\"hljs-attr\">content<\/span>=<span class=\"hljs-string\">\"Live Event Simulator Created by Next.js\"<\/span>\n            \/&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"icon\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"\/favicon.ico\"<\/span> \/&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Head<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">main<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.main}<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"live-event-container\"<\/span>&gt;<\/span>\n              {\/* Our VideoPlayer component *\/}\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">MemoizedVideoPlayer<\/span>\n                <span class=\"hljs-attr\">ended<\/span>=<span class=\"hljs-string\">{ended}<\/span>\n                <span class=\"hljs-attr\">timePlayed<\/span>=<span class=\"hljs-string\">{timePlayed}<\/span>\n                <span class=\"hljs-attr\">controls<\/span>=<span class=\"hljs-string\">{controls}<\/span>\n                <span class=\"hljs-attr\">endVideo<\/span>=<span class=\"hljs-string\">{endVideo}<\/span>\n                <span class=\"hljs-attr\">playing<\/span>=<span class=\"hljs-string\">{playing}<\/span>\n                <span class=\"hljs-attr\">videoDuration<\/span>=<span class=\"hljs-string\">{videoDuration}<\/span>\n              \/&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n            {\/* Our Restart button *\/}\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"reset-button\"<\/span> <span class=\"hljs-attr\">onClick<\/span>=<span class=\"hljs-string\">{restartLive}<\/span>&gt;<\/span>\n              Restart Live Simulation\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">main<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n      );\n    };\n    \n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> Home;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>See the complete code block in this Github Gist <a href=\"https:\/\/gist.github.com\/Chuloo\/37e87a3a4ec468e1012d11875c02b32c\">here<\/a>.<\/p>\n<h2>Passing the variables to our React Player<\/h2>\n<p>We pass our <code>timePlayed<\/code> variable, <code>controls<\/code> variables, <code>endVideo<\/code> function and our <code>videoDuration<\/code> function to the <code>MemoizedVideoPlayer<\/code> component housing our <code>ReactPlayer<\/code> component.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml shcb-wrap-lines\">    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">MemoizedVideoPlayer<\/span> <span class=\"hljs-attr\">timePlayed<\/span> =<span class=\"hljs-string\">{timePlayed}<\/span> <span class=\"hljs-attr\">controls<\/span>=<span class=\"hljs-string\">{controls}<\/span> <span class=\"hljs-attr\">endVideo<\/span>=<span class=\"hljs-string\">{endVideo}<\/span> <span class=\"hljs-attr\">playing<\/span>=<span class=\"hljs-string\">{playing}<\/span> <span class=\"hljs-attr\">videoDuration<\/span>=<span class=\"hljs-string\">{videoDuration}<\/span> \/&gt;<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>In our <code>video-player.jsx<\/code> file, we define a <code>player<\/code> variable, we use this variable later to set the ref on our <code>ReactPlayer<\/code>, we do this to reference the component.<\/p>\n<p>Next we pass the variables we received to their respective props, the <code>controls<\/code> variable, to the controls prop and the <code>playing<\/code> variable, to the playing prop.<\/p>\n<p>The <code>ReactPlayer<\/code> component allows us to use an <code>onEnded<\/code> callback prop which runs the function passed into it when the video ends, so we pass in the <code>endVideo<\/code> function.<\/p>\n<p>The <code>onStart<\/code> callback prop takes in a function that runs when the video is mounted and ready to play. We use this, to call the <code>getDuration()<\/code> method on the <code>player<\/code> object we get from the <code>ReactPlayer<\/code> component. This method is used to get the duration of the video in seconds.<\/p>\n<p>Next we write another function using the <code>seekTo()<\/code> method on the <code>player<\/code> object. The <code>seekTo()<\/code> method takes in a time parameter in seconds that indicates where we want to skip to in the video. We then pass the <code>timePlayed<\/code> variable (the difference between the current time and the start time in seconds) as the time parameter into the <code>seekTo()<\/code> method.<\/p>\n<p>Our <code>video-player.jsx<\/code> should look like this.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> React <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> ReactPlayer <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react-player\"<\/span>;\n    <span class=\"hljs-keyword\">let<\/span> player;\n    <span class=\"hljs-keyword\">const<\/span> VideoPlayer = ({\n      endVideo,\n      timePlayed,\n      controls,\n      playing,\n      videoDuration\n    }) =&gt; (\n      <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"video-player\"<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ReactPlayer<\/span>\n          <span class=\"hljs-attr\">ref<\/span>=<span class=\"hljs-string\">{(ref)<\/span> =&gt;<\/span> {\n            player = ref;\n          }}\n          url=\"https:\/\/res.cloudinary.com\/amarachi-2812\/video\/upload\/v1630370229\/videoplayback_1_pr2hzi.mp4\"\n          playing={playing}\n          controls={controls}\n          onStart={() =&gt; {\n            videoDuration(player.getDuration);\n            player.seekTo(timePlayed);\n          }}\n          onEnded={endVideo}\n        \/&gt;\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n    );\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> MemoizedVideoPlayer = React.memo(VideoPlayer);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<!-- The code was not able to run without including [export const MemoizedVideoPlayer = React.memo(VideoPlayer);] -->\n<!--COMMENT- WILLIAM Thanks for pointing that out, i've updated the content and codeblocks to show the memoization. I also managed stuff around chronology, particularly with using the videoOverlay component before it's defined in the article -->\n<h2>Creating the video overlay<\/h2>\n<p>To make our overlay, we create a <code>video-overlay.jsx<\/code> file in the components folder.<\/p>\n<p>For our overlay, we use a <code>div<\/code> element, a header and a <code>p<\/code> tag.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> React <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'react'<\/span>;\n    <span class=\"hljs-keyword\">const<\/span> VideoOverlay = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span> = <span class=\"hljs-string\">'video-overlay'<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h2<\/span>&gt;<\/span>Live Event has finished<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h2<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Click the button below to restart simulation<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n    );\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> VideoOverlay;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>In the <code>styles<\/code> folder, there is a <code>global.css<\/code> stylesheet. In this, we write the styling for our app with the following content:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\">    <span class=\"hljs-selector-class\">.video-overlay<\/span>{\n      <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">640px<\/span>;\n      <span class=\"hljs-attribute\">height<\/span>: <span class=\"hljs-number\">360px<\/span>;\n      <span class=\"hljs-attribute\">position<\/span>: absolute;\n      <span class=\"hljs-attribute\">top<\/span>: <span class=\"hljs-number\">18.5%<\/span>;\n      <span class=\"hljs-attribute\">bottom<\/span>: <span class=\"hljs-number\">0<\/span>;\n      <span class=\"hljs-attribute\">background-color<\/span>: <span class=\"hljs-built_in\">rgba<\/span>(<span class=\"hljs-number\">0<\/span>,<span class=\"hljs-number\">0<\/span>,<span class=\"hljs-number\">0<\/span>, <span class=\"hljs-number\">0.6<\/span>);\n      <span class=\"hljs-attribute\">color<\/span>: <span class=\"hljs-number\">#fff<\/span>;\n      <span class=\"hljs-attribute\">font-family<\/span>: <span class=\"hljs-string\">'Nunito Sans'<\/span>, sans-serif;\n      <span class=\"hljs-attribute\">text-align<\/span>: center;\n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>The video-overlay <code>div<\/code> has a height of 640px and a width of 360px. These are the measurement of the video player. Next, we give the overlay a position property of \u2018absolute\u2019, setting its position relative to its parent.<\/p>\n<p>The <code>top<\/code> and <code>bottom<\/code> properties tell us the distance we want our element to start. This tutorial has our properties <code>top<\/code> to 18.5% and <code>bottom<\/code> set to 0, indicating that we wish our overlay to begin at the top of our video player and end at the bottom.<\/p>\n<p>We give the overlay a <code>background-color<\/code> property <code>background-color: rgba(0, 0, 0, 0.6)<\/code>. This value gives us a light black background. The <code>color<\/code> property indicates what text color we want in our overlay, <code>font-family<\/code> indicates what font we want and the <code>text-align: center<\/code> to move our text to the center of the overlay.<\/p>\n<p>We also style our reset button with:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\">    <span class=\"hljs-selector-class\">.reset-button<\/span>{\n      <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">250px<\/span>;\n      <span class=\"hljs-attribute\">height<\/span>: <span class=\"hljs-number\">30px<\/span>;\n      <span class=\"hljs-attribute\">border-radius<\/span>: <span class=\"hljs-number\">5px<\/span>;\n      <span class=\"hljs-attribute\">background-color<\/span>: <span class=\"hljs-number\">#111<\/span>;\n      <span class=\"hljs-attribute\">outline<\/span>: none;\n      <span class=\"hljs-attribute\">color<\/span>: <span class=\"hljs-number\">#fff<\/span>;\n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<h2>Selectively rendering the overlay<\/h2>\n<p>In the <code>Home<\/code> component we render the <code>VideoOverlay<\/code> component with:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">import<\/span> VideoOverlay <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"..\/component\/video-overlay\"<\/span>;\n<span class=\"hljs-comment\">\/\/ other imports go in here<\/span>\n\n<span class=\"hljs-keyword\">const<\/span> Home = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n  <span class=\"hljs-comment\">\/\/ state and method definitions<\/span>\n\n  <span class=\"hljs-keyword\">return<\/span> (\n    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.container}<\/span>&gt;<\/span>\n      {\/* Head component *\/}\n\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">main<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{styles.main}<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"live-event-container\"<\/span>&gt;<\/span>\n          {\/* Our VideoPlayer component *\/}\n\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">MemoizedVideoPlayer<\/span>\n            <span class=\"hljs-attr\">ended<\/span>=<span class=\"hljs-string\">{ended}<\/span>\n            <span class=\"hljs-attr\">timePlayed<\/span>=<span class=\"hljs-string\">{timePlayed}<\/span>\n            <span class=\"hljs-attr\">controls<\/span>=<span class=\"hljs-string\">{controls}<\/span>\n            <span class=\"hljs-attr\">endVideo<\/span>=<span class=\"hljs-string\">{endVideo}<\/span>\n            <span class=\"hljs-attr\">playing<\/span>=<span class=\"hljs-string\">{playing}<\/span>\n            <span class=\"hljs-attr\">videoDuration<\/span>=<span class=\"hljs-string\">{videoDuration}<\/span>\n          \/&gt;<\/span>\n          {ended ? <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">VideoOverlay<\/span> \/&gt;<\/span> : null}\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n\n        {\/* Our Restart button *\/}\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">main<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n  );\n};\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> Home;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>In the block of code above, we use a ternary operator to render our overlay depending on if the value of the <code>ended<\/code> variable is true.<\/p>\n<p>With that, we have created our Live Event Simulator.<\/p>\n<p>Here was it looks like :<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/media_jams\/s_EEF0CADCB8202E0C4228163C3069F5FC30159D16FE318256EE9DB9AFE46013C9_1633780094851_end+result.gif\" alt=\"\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"480\" height=\"258\"\/><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/media_jams\/s_EEF0CADCB8202E0C4228163C3069F5FC30159D16FE318256EE9DB9AFE46013C9_1633780114165_live-event-ended.PNG\" alt=\"\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1576\" height=\"766\"\/><\/p>\n<h2>Conclusion<\/h2>\n<p>In this article, we created a video player and handled player events with React Player. We specified what should happen when a user starts watching the \u2018live video\u2019 and how to place them at a specific point of the video depending on how much time has passed since the video began.\nTry to modify the video\u2019s start time relative to your current time and see how far into the live video you get.<\/p>\n<!-- Thank you for the awesome build! Left some notes and I had to fix small lettering issues. Really easy to follow, you broke down each section of the procedure very well - thank you! -->\n<h2>Resources<\/h2>\n<p>You may also find these resources helpful.<\/p>\n<ul>\n<li>\n<a href=\"https:\/\/www.npmjs.com\/package\/react-player\">React Player<\/a>\n<\/li>\n<li>\n<a href=\"https:\/\/www.w3schools.com\/js\/js_date_methods.asp\">JavaScript Get Date Methods.<\/a>\n<\/li>\n<li>\n<a href=\"https:\/\/www.w3schools.com\/css\/css_positioning.asp\">CSS Position<\/a>\n<\/li>\n<\/ul>\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":41,"featured_media":28095,"comment_status":"","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[134,212,246,371,303],"class_list":["post-28094","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-guest-post","tag-next-js","tag-react","tag-under-review","tag-video"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.6 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Build a Live Event Simulator with Recorded Video<\/title>\n<meta name=\"description\" content=\"Learn to simulate a live event using recorded video.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Build a Live Event Simulator with Recorded Video\" \/>\n<meta property=\"og:description\" content=\"Learn to simulate a live event using recorded video.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-03-21T18:41:57+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925407\/Web_Assets\/blog\/c4e916a84fc5cc4b386381d71512b2bbc824b641-5355x4016-1_28095547e3\/c4e916a84fc5cc4b386381d71512b2bbc824b641-5355x4016-1_28095547e3.jpg?_i=AA\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"NewsArticle\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Build a Live Event Simulator with Recorded Video\",\"datePublished\":\"2022-03-21T18:41:57+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/\"},\"wordCount\":8,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925407\/Web_Assets\/blog\/c4e916a84fc5cc4b386381d71512b2bbc824b641-5355x4016-1_28095547e3\/c4e916a84fc5cc4b386381d71512b2bbc824b641-5355x4016-1_28095547e3.jpg?_i=AA\",\"keywords\":[\"Guest Post\",\"Next.js\",\"React\",\"Under Review\",\"Video\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2022\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/\",\"url\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/\",\"name\":\"Build a Live Event Simulator with Recorded Video\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925407\/Web_Assets\/blog\/c4e916a84fc5cc4b386381d71512b2bbc824b641-5355x4016-1_28095547e3\/c4e916a84fc5cc4b386381d71512b2bbc824b641-5355x4016-1_28095547e3.jpg?_i=AA\",\"datePublished\":\"2022-03-21T18:41:57+00:00\",\"description\":\"Learn to simulate a live event using recorded video.\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925407\/Web_Assets\/blog\/c4e916a84fc5cc4b386381d71512b2bbc824b641-5355x4016-1_28095547e3\/c4e916a84fc5cc4b386381d71512b2bbc824b641-5355x4016-1_28095547e3.jpg?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925407\/Web_Assets\/blog\/c4e916a84fc5cc4b386381d71512b2bbc824b641-5355x4016-1_28095547e3\/c4e916a84fc5cc4b386381d71512b2bbc824b641-5355x4016-1_28095547e3.jpg?_i=AA\",\"width\":5355,\"height\":4016},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Build a Live Event Simulator with Recorded Video\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"name\":\"Cloudinary Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudinary.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\",\"name\":\"Cloudinary Blog\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"width\":312,\"height\":60,\"caption\":\"Cloudinary Blog\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Build a Live Event Simulator with Recorded Video","description":"Learn to simulate a live event using recorded video.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/","og_locale":"en_US","og_type":"article","og_title":"Build a Live Event Simulator with Recorded Video","og_description":"Learn to simulate a live event using recorded video.","og_url":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/","og_site_name":"Cloudinary Blog","article_published_time":"2022-03-21T18:41:57+00:00","twitter_card":"summary_large_image","twitter_image":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925407\/Web_Assets\/blog\/c4e916a84fc5cc4b386381d71512b2bbc824b641-5355x4016-1_28095547e3\/c4e916a84fc5cc4b386381d71512b2bbc824b641-5355x4016-1_28095547e3.jpg?_i=AA","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/"},"author":{"name":"","@id":""},"headline":"Build a Live Event Simulator with Recorded Video","datePublished":"2022-03-21T18:41:57+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/"},"wordCount":8,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925407\/Web_Assets\/blog\/c4e916a84fc5cc4b386381d71512b2bbc824b641-5355x4016-1_28095547e3\/c4e916a84fc5cc4b386381d71512b2bbc824b641-5355x4016-1_28095547e3.jpg?_i=AA","keywords":["Guest Post","Next.js","React","Under Review","Video"],"inLanguage":"en-US","copyrightYear":"2022","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/","url":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/","name":"Build a Live Event Simulator with Recorded Video","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925407\/Web_Assets\/blog\/c4e916a84fc5cc4b386381d71512b2bbc824b641-5355x4016-1_28095547e3\/c4e916a84fc5cc4b386381d71512b2bbc824b641-5355x4016-1_28095547e3.jpg?_i=AA","datePublished":"2022-03-21T18:41:57+00:00","description":"Learn to simulate a live event using recorded video.","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925407\/Web_Assets\/blog\/c4e916a84fc5cc4b386381d71512b2bbc824b641-5355x4016-1_28095547e3\/c4e916a84fc5cc4b386381d71512b2bbc824b641-5355x4016-1_28095547e3.jpg?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925407\/Web_Assets\/blog\/c4e916a84fc5cc4b386381d71512b2bbc824b641-5355x4016-1_28095547e3\/c4e916a84fc5cc4b386381d71512b2bbc824b641-5355x4016-1_28095547e3.jpg?_i=AA","width":5355,"height":4016},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/build-a-live-event-simulator-with-recorded-video\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Build a Live Event Simulator with Recorded Video"}]},{"@type":"WebSite","@id":"https:\/\/cloudinary.com\/blog\/#website","url":"https:\/\/cloudinary.com\/blog\/","name":"Cloudinary Blog","description":"","publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudinary.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cloudinary.com\/blog\/#organization","name":"Cloudinary Blog","url":"https:\/\/cloudinary.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","width":312,"height":60,"caption":"Cloudinary Blog"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":""}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681925407\/Web_Assets\/blog\/c4e916a84fc5cc4b386381d71512b2bbc824b641-5355x4016-1_28095547e3\/c4e916a84fc5cc4b386381d71512b2bbc824b641-5355x4016-1_28095547e3.jpg?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28094","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=28094"}],"version-history":[{"count":0,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28094\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/28095"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=28094"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=28094"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=28094"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}