Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Vidyard embedded player inside of React

I've been tasked with inserting an embedded "Vidyard" video into a React project.

The embed code looks something like this.

<script type="text/javascript" async 
  src="https://play.vidyard.com/embed/v4.js">
</script>
<img
  style="width: 100%; margin: auto; display: block;"
  class="vidyard-player-embed"
  src="xxxx"
  data-uuid="xxxx"
  data-v="4"
  data-type="inline"
/>

This does not work 100% of the time. When I insert this into a plain .html file, the video shows up.

On the plain .html file, the image loads and I believe the script then finds the image and drops the embedded video player on the DOM from there.

What I believe is happening is that there is a conflict between React/Vidyard as far as manipulating the DOM.

I've attempted to drop this directly into a component with no luck. I've also added the script call directly to the <head>. I've followed Script load in react and attempted to manually call the script file, I also stuck the manual script load in both the componentWillMount and componentDidMount. I've also inserted the code into dangerouslySetInnerHTML.

The behavior remains the same.

Ideally if this was to work the image would append to the page. The embed/v4.js script would then append a embedded video player on the image. Currently, the image appears and does not get switched out to a video. If i refresh/hard refresh the page, sometimes the image will swap out for the embedded video player.

like image 946
dosebot Avatar asked Aug 30 '25 18:08

dosebot


2 Answers

Here's my solution for those who prefer hooks/functional components:

import React from "react"
import ScriptLoader from "react-script-loader-hoc"

const VIDYARD_EMBED_JS_URL = "https://play.vidyard.com/embed/v4.js"

function VidyardPlayer(props: {
  scriptsLoadedSuccessfully: boolean
  maxWidth: string
  maxHeight: string
  type: string
  uuid: string
  aspect?: "4:3" | "16:9" | "16:10"
  onLoadCallback?: (player: any, embedApi: any) => void
}) {
  const {
    scriptsLoadedSuccessfully,
    maxWidth,
    maxHeight,
    type,
    uuid,
    aspect,
    onLoadCallback,
  } = props
  const containerRef = React.useRef<any>()

  React.useEffect(() => {
    if (scriptsLoadedSuccessfully) {
      window.VidyardV4.api
        .renderPlayer({
          aspect,
          container: containerRef.current,
          height: maxHeight,
          type,
          uuid,
          width: maxWidth,
        })
        .then((player: any) => {
          if (onLoadCallback) {
            onLoadCallback(player, window.VidyardV4.api)
          }
        })
        .catch((e: any) => {
          // eslint-disable-next-line no-console
          console.error(e.message)
        })
    }
  }, [scriptsLoadedSuccessfully])

  return <div ref={containerRef} />
}

export default ScriptLoader(VIDYARD_EMBED_JS_URL)(VidyardPlayer)
like image 62
Alfonso M. García Astorga Avatar answered Sep 02 '25 07:09

Alfonso M. García Astorga


I finally found a solution for the same problem. Here's the player component that you can import and just pass the video id.

/* eslint-disable */
import * as React from 'react';

let vidyardEmbed = {};
if (typeof window !== 'undefined') {
  vidyardEmbed = require('../../../utils/vidyard');
}

export default class VidyardEmbed extends React.Component {
  constructor() {
    super(...arguments);
    this.state = { hasError: false };
    this.handleContainerRef = ref => {
      if (ref) {
        this.container = ref;
      }
    };
  }

  componentDidMount() {
    if (!this.container) {
      return;
    }
    if (this.props.playbackUrl) {
      vidyardEmbed._debug.setPlaybackURL(this.props.playbackUrl);
    }
    vidyardEmbed.api
      .renderPlayer(
        Object.assign(
          {
            aspect: this.props.aspect,
            container: this.container,
            height: this.props.maxHeight,
            type: this.props.type,
            uuid: this.props.uuid,
            width: this.props.maxWidth
          },
          this.props.params
        )
      )
      .then(player => {
        this.player = player;
        if (typeof this.props.api === 'function') {
          this.props.api(player, vidyardEmbed.api);
        }
      })
      .catch(e => {
        this.setState({ hasError: true });
        console.warn(e.message);
      });
  }

  componentWillUnmount() {
    if (this.player) {
      vidyardEmbed.api.destroyPlayer(this.player);
    }
  }

  render() {
    return <div ref={this.handleContainerRef} />;
  }
}

The imported vidyard file is the script that they offer but I imported it locally. That way I was able to get it working within React without any issues.

like image 39
jP_ Avatar answered Sep 02 '25 07:09

jP_