diff --git a/bigbluebutton-html5/imports/api/external-videos/server/methods/startWatchingExternalVideo.js b/bigbluebutton-html5/imports/api/external-videos/server/methods/startWatchingExternalVideo.js
index b5d6b8550acca0b6cad435325419b9b4ea0fdaa5..407d8a2b0903f037979c9528eca0f70f24ed42a0 100644
--- a/bigbluebutton-html5/imports/api/external-videos/server/methods/startWatchingExternalVideo.js
+++ b/bigbluebutton-html5/imports/api/external-videos/server/methods/startWatchingExternalVideo.js
@@ -20,7 +20,7 @@ export default function startWatchingExternalVideo(credentials, options) {
 
   const payload = { externalVideoUrl };
 
-  Logger.info(`User id=${requesterUserId} sharing a youtube video: ${externalVideoUrl} for meeting ${meetingId}`);
+  Logger.info(`User id=${requesterUserId} sharing an external video: ${externalVideoUrl} for meeting ${meetingId}`);
 
   return RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, requesterUserId, payload);
 }
diff --git a/bigbluebutton-html5/imports/api/external-videos/server/methods/stopWatchingExternalVideo.js b/bigbluebutton-html5/imports/api/external-videos/server/methods/stopWatchingExternalVideo.js
index 8b0496232da1126a4c38d97749f6c1bf47a455db..04a009c59fa558592dd9b524f515cc57923a1bad 100644
--- a/bigbluebutton-html5/imports/api/external-videos/server/methods/stopWatchingExternalVideo.js
+++ b/bigbluebutton-html5/imports/api/external-videos/server/methods/stopWatchingExternalVideo.js
@@ -17,7 +17,7 @@ export default function stopWatchingExternalVideo(credentials) {
   Meetings.update({ meetingId }, { $set: { externalVideoUrl: null } });
   const payload = {};
 
-  Logger.info(`User id=${requesterUserId} stopped sharing a youtube video for meeting=${meetingId}`);
+  Logger.info(`User id=${requesterUserId} stopped sharing an external video for meeting=${meetingId}`);
 
   RedisPubSub.publishUserMessage(CHANNEL, EVENT_NAME, meetingId, requesterUserId, payload);
 }
diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/service.js b/bigbluebutton-html5/imports/ui/components/actions-bar/service.js
index bde56d3e16dd3ed2226fd3ac3ca00d9431265cfc..20960bf10cf39ce9ed2e1cfb657d942ebce0f455 100755
--- a/bigbluebutton-html5/imports/ui/components/actions-bar/service.js
+++ b/bigbluebutton-html5/imports/ui/components/actions-bar/service.js
@@ -3,7 +3,7 @@ import Users from '/imports/api/users';
 import { makeCall } from '/imports/ui/services/api';
 import Meetings from '/imports/api/meetings';
 import Breakouts from '/imports/api/breakouts';
-import { getVideoId } from '/imports/ui/components/external-video-player/service';
+import { getVideoUrl } from '/imports/ui/components/external-video-player/service';
 
 const USER_CONFIG = Meteor.settings.public.user;
 const ROLE_MODERATOR = USER_CONFIG.role_moderator;
@@ -45,5 +45,5 @@ export default {
   getBreakouts,
   getUsersNotAssigned,
   takePresenterRole,
-  isSharingVideo: () => getVideoId(),
+  isSharingVideo: () => getVideoUrl(),
 };
diff --git a/bigbluebutton-html5/imports/ui/components/external-video-player/component.jsx b/bigbluebutton-html5/imports/ui/components/external-video-player/component.jsx
index 50edb7e48536178092f521f5020314369aaf9536..20b5eee6386fe492f7dbed4f35e12a9dd77f5af0 100644
--- a/bigbluebutton-html5/imports/ui/components/external-video-player/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/external-video-player/component.jsx
@@ -1,42 +1,52 @@
 import React, { Component } from 'react';
 import injectWbResizeEvent from '/imports/ui/components/presentation/resize-wrapper/component';
-import YouTube from 'react-youtube';
 import { sendMessage, onMessage } from './service';
 import logger from '/imports/startup/client/logger';
 
-const { PlayerState } = YouTube;
+import ArcPlayer from './custom-players/arc-player';
+
+import ReactPlayer from 'react-player';
+
+import { styles } from './styles';
 
 const SYNC_INTERVAL_SECONDS = 2;
 
+ReactPlayer.addCustomPlayer(ArcPlayer);
+
 class VideoPlayer extends Component {
   constructor(props) {
     super(props);
 
+    const isPresenter = { props };
+
     this.player = null;
     this.syncInterval = null;
-    this.playerState = PlayerState.UNSTARTED;
-    this.presenterCommand = false;
-    this.preventStateChange = false;
     this.state = {
       mutedByEchoTest: false,
+      playing: false,
+      playbackRate: 1,
     };
 
     this.opts = {
-      playerVars: {
-        width: '100%',
-        height: '100%',
-        autoplay: 1,
-        modestbranding: true,
-        rel: 0,
-        ecver: 2,
+      controls: isPresenter,
+      youtube: {
+        playerVars: {
+          autoplay: 1,
+          modestbranding: 1,
+          autohide: 1,
+          rel: 0,
+          ecver: 2,
+          controls: this.props.isPresenter ? 1 : 2,
+        },
       },
+      preload: true,
     };
 
     this.keepSync = this.keepSync.bind(this);
     this.handleResize = this.handleResize.bind(this);
     this.handleOnReady = this.handleOnReady.bind(this);
-    this.handleStateChange = this.handleStateChange.bind(this);
-    this.changeState = this.changeState.bind(this);
+    this.handleOnPlay = this.handleOnPlay.bind(this);
+    this.handleOnPause = this.handleOnPause.bind(this);
     this.resizeListener = () => {
       setTimeout(this.handleResize, 0);
     };
@@ -44,6 +54,9 @@ class VideoPlayer extends Component {
 
   componentDidMount() {
     window.addEventListener('resize', this.resizeListener);
+
+    clearInterval(this.syncInterval);
+    this.keepSync();
   }
 
   componentDidUpdate(prevProps) {
@@ -53,17 +66,11 @@ class VideoPlayer extends Component {
     } = this.state;
 
     if (inEchoTest && !this.player.isMuted() && !mutedByEchoTest) {
-      this.player.mute();
-      this.changeState(true);
+      this.setState({ mutedByEchoTest: true });
     }
 
     if (!inEchoTest && prevProps.inEchoTest && mutedByEchoTest) {
-      this.player.unMute();
-      this.changeState(false);
-    }
-
-    if (!prevProps.videoId) {
-      clearInterval(this.syncInterval);
+      this.setState({ mutedByEchoTest: false });
     }
   }
 
@@ -72,29 +79,36 @@ class VideoPlayer extends Component {
 
     clearInterval(this.syncInterval);
     this.player = null;
-    this.refPlayer = null;
-  }
-
-  changeState(booleanValue) {
-    this.setState({ mutedByEchoTest: booleanValue });
   }
 
   handleResize() {
-    if (!this.player || !this.refPlayer) {
+    if (!this.player || !this.playerParent) {
       return;
     }
 
-    const el = this.refPlayer;
-    const parent = el.parentElement;
-    const w = parent.clientWidth;
-    const h = parent.clientHeight;
+    const par = this.playerParent.parentElement;
+    const w = par.clientWidth;
+    const h = par.clientHeight;
     const idealW = h * 16 / 9;
 
+    let style = {}
     if (idealW > w) {
-      this.player.setSize(w, w * 9 / 16);
+      style.width = w;
+      style.height = w * 9 / 16;
     } else {
-      this.player.setSize(idealW, h);
+      style.width = idealW;
+      style.height = h;
     }
+
+    var styleStr = `width: ${style.width}px; height: ${style.height}px;`;
+    this.player.wrapper.style = styleStr;
+    this.playerParent.style = styleStr;
+  }
+
+  getCurrentPlaybackRate() {
+    const intPlayer = this.player.getInternalPlayer();
+
+    return (intPlayer.getPlaybackRate && intPlayer.getPlaybackRate()) || 1;
   }
 
   keepSync() {
@@ -103,38 +117,41 @@ class VideoPlayer extends Component {
     if (isPresenter) {
       this.syncInterval = setInterval(() => {
         const curTime = this.player.getCurrentTime();
-        const rate = this.player.getPlaybackRate();
-        sendMessage('playerUpdate', { rate, time: curTime, state: this.playerState });
+        const rate = this.getCurrentPlaybackRate();
+
+        sendMessage('playerUpdate', { rate, time: curTime, state: this.state.playing });
       }, SYNC_INTERVAL_SECONDS * 1000);
     } else {
+
       onMessage('play', ({ time }) => {
-        this.presenterCommand = true;
-        if (this.player) {
-          this.player.seekTo(time, true);
-          this.playerState = PlayerState.PLAYING;
-          this.player.playVideo();
+        if (!this.player) {
+          return;
         }
+
+        this.player.seekTo(time);
+        this.setState({playing: true});
+
         logger.debug({ logCode: 'external_video_client_play' }, 'Play external video');
       });
 
       onMessage('stop', ({ time }) => {
-        this.presenterCommand = true;
-
-        if (this.player) {
-          this.playerState = PlayerState.PAUSED;
-          this.player.seekTo(time, true);
-          this.player.pauseVideo();
+        if (!this.player) {
+          return;
         }
+        this.player.seekTo(time);
+        this.setState({playing: false});
+
         logger.debug({ logCode: 'external_video_client_stop' }, 'Stop external video');
       });
 
       onMessage('playerUpdate', (data) => {
+
         if (!this.player) {
           return;
         }
 
-        if (data.rate !== this.player.getPlaybackRate()) {
-          this.player.setPlaybackRate(data.rate);
+        if (data.rate !== this.player.props.playbackRate) {
+          this.setState({playbackRate: data.rate});
           logger.debug({
             logCode: 'external_video_client_update_rate',
             extraInfo: {
@@ -153,16 +170,8 @@ class VideoPlayer extends Component {
           }, 'Seek external video to:');
         }
 
-        if (this.playerState !== data.state) {
-          this.presenterCommand = true;
-          this.playerState = data.state;
-          if (this.playerState === PlayerState.PLAYING) {
-            this.player.playVideo();
-            logger.debug({ logCode: 'external_video_client_prevent_pause' }, 'Prevent pause external video');
-          } else {
-            this.player.pauseVideo();
-            logger.debug({ logCode: 'external_video_client_prevent_play' }, 'Prevent play external video');
-          }
+        if (this.state.playing !== data.state) {
+          this.setState({playing: data.state});
         }
       });
     }
@@ -171,75 +180,55 @@ class VideoPlayer extends Component {
   handleOnReady(event) {
     const { isPresenter } = this.props;
 
-    this.player = event.target;
-    this.player.pauseVideo();
-
-    this.keepSync();
-
     if (!isPresenter) {
       sendMessage('viewerJoined');
-    } else {
-      this.player.playVideo();
     }
 
     this.handleResize();
   }
 
-  handleStateChange(event) {
+  handleOnPlay() {
     const { isPresenter } = this.props;
     const curTime = this.player.getCurrentTime();
 
-    if (this.preventStateChange && [PlayerState.PLAYING, PlayerState.PAUSED].includes(event.data)) {
-      this.preventStateChange = false;
-      return;
+    if (isPresenter) {
+      sendMessage('play', { time: curTime });
     }
+    this.setState({playing: true});
+  }
 
-    if (this.playerState === event.data) {
-      return;
-    }
+  handleOnPause() {
+    const { isPresenter } = this.props;
+    const curTime = this.player.getCurrentTime();
 
-    if (event.data === PlayerState.PLAYING) {
-      if (isPresenter) {
-        sendMessage('play', { time: curTime });
-        this.playerState = event.data;
-      } else if (!this.presenterCommand) {
-        this.player.seekTo(curTime, true);
-        this.preventStateChange = true;
-        this.player.pauseVideo();
-      } else {
-        this.playerState = event.data;
-        this.presenterCommand = false;
-      }
-    } else if (event.data === PlayerState.PAUSED) {
-      if (isPresenter) {
-        sendMessage('stop', { time: curTime });
-        this.playerState = event.data;
-      } else if (!this.presenterCommand) {
-        this.player.seekTo(curTime);
-        this.preventStateChange = true;
-        this.player.playVideo();
-      } else {
-        this.playerState = event.data;
-        this.presenterCommand = false;
-      }
+    if (isPresenter) {
+      sendMessage('stop', { time: curTime });
     }
+    this.setState({playing: false});
   }
 
   render() {
-    const { videoId } = this.props;
-    const { opts, handleOnReady, handleStateChange } = this;
+    const { videoUrl } = this.props;
+    const { playing, playbackRate, mutedByEchoTest } = this.state;
+    const { opts, commonOpts, handleOnReady, handleStateChange } = this;
 
     return (
       <div
-        id="youtube-video-player"
+        id="video-player"
         data-test="videoPlayer"
-        ref={(ref) => { this.refPlayer = ref; }}
+        ref={(ref) => { this.playerParent = ref; }}
       >
-        <YouTube
-          videoId={videoId}
-          opts={opts}
-          onReady={handleOnReady}
-          onStateChange={handleStateChange}
+        <ReactPlayer
+          className={styles.videoPlayer}
+          url={videoUrl}
+          config={this.opts}
+          muted={mutedByEchoTest}
+          playing={playing}
+          playbackRate={playbackRate}
+          onReady={this.handleOnReady}
+          onPlay={this.handleOnPlay}
+          onPause={this.handleOnPause}
+          ref={(ref) => { this.player = ref; }}
         />
       </div>
     );
diff --git a/bigbluebutton-html5/imports/ui/components/external-video-player/container.jsx b/bigbluebutton-html5/imports/ui/components/external-video-player/container.jsx
index aca54887bf628b7b778478cb63199ebba75739c5..e00da62abbd156b1a76bbb879542aaba4f295e5f 100644
--- a/bigbluebutton-html5/imports/ui/components/external-video-player/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/external-video-player/container.jsx
@@ -2,6 +2,7 @@ import React from 'react';
 import { defineMessages, injectIntl } from 'react-intl';
 import { withTracker } from 'meteor/react-meteor-data';
 import { Session } from 'meteor/session';
+import Service from './service';
 import ExternalVideo from './component';
 
 const intlMessages = defineMessages({
@@ -12,7 +13,7 @@ const intlMessages = defineMessages({
 });
 
 const ExternalVideoContainer = props => (
-  <ExternalVideo {...props}>
+  <ExternalVideo {...{...props, videoUrl: Service.getVideoUrl() } }>
     {props.children}
   </ExternalVideo>
 );
diff --git a/bigbluebutton-html5/imports/ui/components/external-video-player/custom-players/arc-player.jsx b/bigbluebutton-html5/imports/ui/components/external-video-player/custom-players/arc-player.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..4528fea16f4df86f8ea7a21cd8249f2121e25015
--- /dev/null
+++ b/bigbluebutton-html5/imports/ui/components/external-video-player/custom-players/arc-player.jsx
@@ -0,0 +1,193 @@
+import loadScript from 'load-script';
+import React, { Component } from 'react'
+
+const MATCH_URL = new RegExp("https?:\/\/(\\w+)\.(instructuremedia.com)(\/embed)?\/([-abcdef0-9]+)");
+
+const SDK_URL = 'https://files.instructuremedia.com/instructure-media-script/instructure-media-1.1.0.js';
+
+const EMBED_PATH = "/embed/";
+
+// Util function to load an external SDK or return the SDK if it is already loaded
+// From https://github.com/CookPete/react-player/blob/master/src/utils.js
+const resolves = {}
+export function getSDK (url, sdkGlobal, sdkReady = null, isLoaded = () => true, fetchScript = loadScript) {
+  if (window[sdkGlobal] && isLoaded(window[sdkGlobal])) {
+    return Promise.resolve(window[sdkGlobal])
+  }
+  return new Promise((resolve, reject) => {
+    // If we are already loading the SDK, add the resolve
+    // function to the existing array of resolve functions
+    if (resolves[url]) {
+      resolves[url].push(resolve)
+      return
+    }
+    resolves[url] = [resolve]
+    const onLoaded = sdk => {
+      // When loaded, resolve all pending promises
+      resolves[url].forEach(resolve => resolve(sdk))
+    }
+    if (sdkReady) {
+      const previousOnReady = window[sdkReady]
+      window[sdkReady] = function () {
+        if (previousOnReady) previousOnReady()
+        onLoaded(window[sdkGlobal])
+      }
+    }
+    fetchScript(url, err => {
+      if (err) {
+        reject(err);
+      }
+      window[sdkGlobal] = url;
+      if (!sdkReady) {
+        onLoaded(window[sdkGlobal])
+      }
+    })
+  })
+}
+
+export class ArcPlayer extends Component {
+  static displayName = 'ArcPlayer'
+
+  static canPlay = url => {
+    return MATCH_URL.test(url)
+  }
+
+  constructor(props) {
+    super(props);
+
+    this.currentTime = 0;
+    this.updateCurrentTime = this.updateCurrentTime.bind(this);
+    this.getCurrentTime = this.getCurrentTime.bind(this);
+    this.getEmbedUrl = this.getEmbedUrl.bind(this);
+    this.onStateChange = this.onStateChange.bind(this);
+  }
+
+  load() {
+    new Promise((resolve, reject) => {
+      this.render();
+      resolve();
+    })
+    .then(() => { return getSDK(SDK_URL, 'ArcPlayer') })
+    .then(() => {
+      this.player = new InstructureMedia.Player('arcPlayerContainer', {
+        height: '100%',
+        width: '100%',
+        embedUrl: this.getEmbedUrl(),
+        events: {
+          onStateChange: this.onStateChange,
+        }
+      });
+      this.player.playVideo();
+    });
+  }
+
+  onStateChange(event) {
+    console.log('js_api index.development.html onStateChange', event);
+    this.player.getCurrentTime().then((t) => {
+      this.updateCurrentTime(t.data);
+    });
+
+    if (event.data === "CUED") {
+      this.props.onReady();
+    } else if (event.data === "PLAYING") {
+      this.props.onPlay && this.props.onPlay();
+    } else if (event.data === "PAUSED") {
+      this.props.onPause && this.props.onPause();
+    } else if (event.data === "SEEKED") {
+      // TODO
+    } else if (event.data === "SEEKING") {
+      // TODO
+    }
+  }
+
+  updateCurrentTime(e) {
+    this.currentTime = e;
+  }
+
+  getVideoId() {
+    const { url } = this.props;
+    const m = url.match(MATCH_URL);
+    return m && m[4];
+  }
+
+  getHostUrl() {
+    const { url } = this.props;
+    const m = url.match(MATCH_URL);
+    return m && 'https://' + m[1] + '.' + m[2];
+  }
+
+  getEmbedUrl() {
+    let url = this.getHostUrl() + EMBED_PATH + this.getVideoId();
+    return url;
+  }
+
+  play() {
+    this.player.playVideo();
+  }
+
+  pause() {
+    this.player.pauseVideo();
+  }
+
+  stop() {
+    // TODO: STOP
+  }
+
+  seekTo(seconds) {
+    this.player.seekTo(seconds);
+  }
+
+  setVolume(fraction) {
+    // console.log("SET VOLUME");
+  }
+
+  setLoop(loop) {
+    // console.log("SET LOOP");
+  }
+
+  mute() {
+    // console.log("SET MUTE");
+  }
+
+  unmute() {
+    // console.log("SET UNMUTE");
+  }
+
+  getDuration() {
+    //console.log("GET DURATION");
+  }
+
+  getCurrentTime () {
+    this.player.getCurrentTime().then((t) => {
+      this.updateCurrentTime(t.data);
+    });
+
+    return this.currentTime;
+  }
+
+  getSecondsLoaded () {
+  }
+
+  render () {
+    const style = {
+      width: '100%',
+      height: '100%',
+      overflow: 'hidden',
+      backgroundColor: 'black'
+    }
+    return (
+      <div
+        key={this.props.url}
+        style={style}
+        id={"arcPlayerContainer"}
+        ref={(container) => {
+          this.container = container;
+        }}
+      >
+      </div>
+    )
+  }
+}
+
+export default ArcPlayer;
+
diff --git a/bigbluebutton-html5/imports/ui/components/external-video-player/modal/component.jsx b/bigbluebutton-html5/imports/ui/components/external-video-player/modal/component.jsx
index f6524395c2130d75b044b8f6ea8a6732f8be0b53..3601f3f9ccfb2e02a30cb9cfda0d29c7a0ed601c 100644
--- a/bigbluebutton-html5/imports/ui/components/external-video-player/modal/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/external-video-player/modal/component.jsx
@@ -4,14 +4,14 @@ import Modal from '/imports/ui/components/modal/simple/component';
 import Button from '/imports/ui/components/button/component';
 
 import { defineMessages, injectIntl } from 'react-intl';
-import { isUrlValid, getUrlFromVideoId } from '../service';
+import { isUrlValid } from '../service';
 
 import { styles } from './styles';
 
 const intlMessages = defineMessages({
   start: {
     id: 'app.externalVideo.start',
-    description: 'Share youtube video',
+    description: 'Share external video',
   },
   urlError: {
     id: 'app.externalVideo.urlError',
@@ -35,7 +35,7 @@ const intlMessages = defineMessages({
   },
   note: {
     id: 'app.externalVideo.noteLabel',
-    description: 'provides hint about Shared YouTube videos',
+    description: 'provides hint about Shared External videos',
   },
 });
 
@@ -43,11 +43,11 @@ class ExternalVideoModal extends Component {
   constructor(props) {
     super(props);
 
-    const { videoId } = props;
+    const { videoUrl } = props;
 
     this.state = {
-      url: getUrlFromVideoId(videoId),
-      sharing: videoId,
+      url: videoUrl,
+      sharing: videoUrl,
     };
 
     this.startWatchingHandler = this.startWatchingHandler.bind(this);
@@ -93,10 +93,10 @@ class ExternalVideoModal extends Component {
   }
 
   render() {
-    const { intl, videoId, closeModal } = this.props;
+    const { intl, videoUrl, closeModal } = this.props;
     const { url, sharing } = this.state;
 
-    const startDisabled = !isUrlValid(url) || (getUrlFromVideoId(videoId) === url);
+    const startDisabled = !isUrlValid(url);
 
     return (
       <Modal
@@ -118,13 +118,12 @@ class ExternalVideoModal extends Component {
                 id="video-modal-input"
                 onChange={this.updateVideoUrlHandler}
                 name="video-modal-input"
-                value={url}
                 placeholder={intl.formatMessage(intlMessages.urlInput)}
                 disabled={sharing}
-                aria-describedby="youtube-note"
+                aria-describedby="exernal-video-note"
               />
             </label>
-            <div className={styles.youtubeNote} id="youtube-note">
+            <div className={styles.externalVideoNote} id="external-video-note">
               {intl.formatMessage(intlMessages.note)}
             </div>
           </div>
diff --git a/bigbluebutton-html5/imports/ui/components/external-video-player/modal/container.jsx b/bigbluebutton-html5/imports/ui/components/external-video-player/modal/container.jsx
index 6a91801ccbc75d82035aab942d9998708aaf2809..6d53925557393181102f30c6008670aed277d97c 100644
--- a/bigbluebutton-html5/imports/ui/components/external-video-player/modal/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/external-video-player/modal/container.jsx
@@ -2,7 +2,7 @@ import React from 'react';
 import { withTracker } from 'meteor/react-meteor-data';
 import { withModalMounter } from '/imports/ui/components/modal/service';
 import ExternalVideoModal from './component';
-import { startWatching, getVideoId } from '../service';
+import { startWatching, getVideoUrl } from '../service';
 import mediaService from '/imports/ui/components/media/service';
 
 const ExternalVideoModalContainer = props => <ExternalVideoModal {...props} />;
@@ -12,7 +12,7 @@ export default withModalMounter(withTracker(({ mountModal }) => ({
     mountModal(null);
   },
   startWatching,
-  videoId: getVideoId(),
+  videoUrl: getVideoUrl(),
   toggleLayout: mediaService.toggleSwapLayout,
   isSwapped: mediaService.getSwapLayout(),
 }))(ExternalVideoModalContainer));
diff --git a/bigbluebutton-html5/imports/ui/components/external-video-player/modal/styles.scss b/bigbluebutton-html5/imports/ui/components/external-video-player/modal/styles.scss
index e5fe49bf34d778be1eaeb14b2cae1ec61866d8ec..e4d8dbe2731817dbe5f8fc40b0552734073df7d0 100755
--- a/bigbluebutton-html5/imports/ui/components/external-video-player/modal/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/external-video-player/modal/styles.scss
@@ -139,7 +139,7 @@
   }
 }
 
-.youtubeNote {
+.externalVideoNote {
   color: var(--color-gray);
   font-size: var(--font-size-small);
   font-style: italic;
diff --git a/bigbluebutton-html5/imports/ui/components/external-video-player/service.js b/bigbluebutton-html5/imports/ui/components/external-video-player/service.js
index db2fd93b795a0f20e2cb4e2ab6c2ad8fbe4abc65..b3a530435d13992edf26f30fea2d6db81401f3c2 100644
--- a/bigbluebutton-html5/imports/ui/components/external-video-player/service.js
+++ b/bigbluebutton-html5/imports/ui/components/external-video-player/service.js
@@ -4,22 +4,13 @@ import ExternalVideoStreamer from '/imports/api/external-videos';
 
 import { makeCall } from '/imports/ui/services/api';
 
-const YOUTUBE_PREFIX = 'https://youtube.com/watch?v=';
-const YOUTUBE_REGEX = /(?:youtube\.com\/\S*(?:(?:\/e(?:mbed))?\/|watch\/?\?(?:\S*?&?v\=))|youtu\.be\/)([a-zA-Z0-9_-]{6,11})/g;
+import ReactPlayer from 'react-player';
 
 const isUrlEmpty = url => !url || url.length === 0;
-
-const isUrlValid = url => !isUrlEmpty(url) && url.match(YOUTUBE_REGEX);
-
-const getUrlFromVideoId = id => (id ? `${YOUTUBE_PREFIX}${id}` : '');
-
-const videoIdFromUrl = (url) => {
-  const match = YOUTUBE_REGEX.exec(url);
-  return match ? match[1] : false;
-};
+const isUrlValid = url => ReactPlayer.canPlay(url);
 
 const startWatching = (url) => {
-  const externalVideoUrl = videoIdFromUrl(url);
+  const externalVideoUrl = url;
   makeCall('startWatchingExternalVideo', { externalVideoUrl });
 };
 
@@ -39,7 +30,7 @@ const onMessage = (message, func) => {
   ExternalVideoStreamer.on(message, func);
 };
 
-const getVideoId = () => {
+const getVideoUrl = () => {
   const meetingId = Auth.meetingID;
   const meeting = Meetings.findOne({ meetingId });
 
@@ -49,8 +40,7 @@ const getVideoId = () => {
 export {
   sendMessage,
   onMessage,
-  getVideoId,
-  getUrlFromVideoId,
+  getVideoUrl,
   isUrlValid,
   startWatching,
   stopWatching,
diff --git a/bigbluebutton-html5/imports/ui/components/external-video-player/styles.scss b/bigbluebutton-html5/imports/ui/components/external-video-player/styles.scss
index 5bb369f6e5cf3772faba2e0595a05f75f2a579ae..2af8c737bdd6d061cfcc34860d43861b5831129a 100644
--- a/bigbluebutton-html5/imports/ui/components/external-video-player/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/external-video-player/styles.scss
@@ -1,49 +1,7 @@
 @import "/imports/ui/stylesheets/mixins/focus";
 @import "/imports/ui/stylesheets/variables/_all";
 
-$icon-offset: -.4em;
-
-.note {
-  background-color: #fff;
-  padding-top: var(--md-padding-x);
-  display: flex;
-  flex-grow: 1;
-  flex-direction: column;
-  justify-content: space-around;
-  overflow: hidden;
-}
-
-.header {
-  display: flex;
-  flex-direction: row;
-  align-items: left;
-  flex-shrink: 0;
-  padding-left: var(--md-padding-x);
-  padding-right: var(--md-padding-x);
-
-  a {
-    @include elementFocus(var(--color-primary));
-    padding: 0 0 var(--sm-padding-y) var(--sm-padding-y);
-    text-decoration: none;
-    display: block;
-
-    [dir="rtl"] & {
-      padding: 0 var(--sm-padding-y) var(--sm-padding-y) 0;
-    }
-  }
-
-  [class^="icon-bbb-"],
-  [class*=" icon-bbb-"] {
-    font-size: 85%;
-  }
-}
-
-.title {
-  @extend %text-elipsis;
-  flex: 1;
-}
-
-iframe {
+.videoPlayer iframe {
   display: flex;
   flex-flow: column;
   flex-grow: 1;
@@ -52,4 +10,5 @@ iframe {
   overflow-x: hidden;
   overflow-y: auto;
   border-style: none;
+  border-bottom: none;
 }
diff --git a/bigbluebutton-html5/imports/ui/components/media/container.jsx b/bigbluebutton-html5/imports/ui/components/media/container.jsx
index dbaababf71897f1493b50a8e884a252e7657eadb..a049c4d6e469ae5f35e81433670af0248c7179d1 100755
--- a/bigbluebutton-html5/imports/ui/components/media/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/media/container.jsx
@@ -14,7 +14,6 @@ import PresentationPodsContainer from '../presentation-pod/container';
 import ScreenshareContainer from '../screenshare/container';
 import DefaultContent from '../presentation/default-content/component';
 import ExternalVideoContainer from '../external-video-player/container';
-import { getVideoId } from '../external-video-player/service';
 
 const LAYOUT_CONFIG = Meteor.settings.public.layout;
 const KURENTO_CONFIG = Meteor.settings.public.kurento;
@@ -143,7 +142,6 @@ export default withModalMounter(withTracker(() => {
     data.children = (
       <ExternalVideoContainer
         isPresenter={MediaService.isUserPresenter()}
-        videoId={getVideoId()}
       />
     );
   }
diff --git a/bigbluebutton-html5/imports/ui/components/media/service.js b/bigbluebutton-html5/imports/ui/components/media/service.js
index a2f121773c4f63136cbc6d5bfa66cecd97c82c6c..1e03deafcafe009937fc39b7809e4668bfdf7cd6 100755
--- a/bigbluebutton-html5/imports/ui/components/media/service.js
+++ b/bigbluebutton-html5/imports/ui/components/media/service.js
@@ -1,6 +1,6 @@
 import Presentations from '/imports/api/presentations';
 import { isVideoBroadcasting } from '/imports/ui/components/screenshare/service';
-import { getVideoId } from '/imports/ui/components/external-video-player/service';
+import { getVideoUrl } from '/imports/ui/components/external-video-player/service';
 import Auth from '/imports/ui/services/auth';
 import Users from '/imports/api/users';
 import Settings from '/imports/ui/services/settings';
@@ -36,7 +36,7 @@ function shouldShowScreenshare() {
 
 function shouldShowExternalVideo() {
   const { enabled: enableExternalVideo } = Meteor.settings.public.externalVideoPlayer;
-  return enableExternalVideo && getVideoId();
+  return enableExternalVideo && getVideoUrl();
 }
 
 function shouldShowOverlay() {
diff --git a/bigbluebutton-html5/package-lock.json b/bigbluebutton-html5/package-lock.json
index 6700180d031aa0420b1bf42563e82de027c09a03..5dcc97c0bf63bd1fc05e25ab16af077fb84ce14a 100644
--- a/bigbluebutton-html5/package-lock.json
+++ b/bigbluebutton-html5/package-lock.json
@@ -5601,6 +5601,23 @@
         "warning": "^3.0.0"
       }
     },
+    "react-player": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/react-player/-/react-player-1.11.1.tgz",
+      "integrity": "sha512-bS4qls4eICdwklCm/jqjSvYZt1dl07biT8aAiXG9dMZ2s789cZtCDiHdwKP2FH82jHYk5oFfHXy7EL9lMjUfxA==",
+      "requires": {
+        "deepmerge": "^3.0.0",
+        "load-script": "^1.0.0",
+        "prop-types": "^15.5.6"
+      },
+      "dependencies": {
+        "deepmerge": {
+          "version": "3.3.0",
+          "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-3.3.0.tgz",
+          "integrity": "sha512-GRQOafGHwMHpjPx9iCvTgpu9NojZ49q794EEL94JVEw6VaeA8XTUyBKvAkOOjBX9oJNiV6G3P+T+tihFjo2TqA=="
+        }
+      }
+    },
     "react-render-in-browser": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/react-render-in-browser/-/react-render-in-browser-1.1.1.tgz",
@@ -5660,16 +5677,6 @@
         }
       }
     },
-    "react-youtube": {
-      "version": "7.9.0",
-      "resolved": "https://registry.npmjs.org/react-youtube/-/react-youtube-7.9.0.tgz",
-      "integrity": "sha512-2+nBF4qP8nStYEILIO1/SylKOCnnJUxuZm+qCeWA0eeZxnWZIIixfAeAqbzblwx5L1n/26ACocy3epm9Glox8w==",
-      "requires": {
-        "fast-deep-equal": "^2.0.1",
-        "prop-types": "^15.5.3",
-        "youtube-player": "^5.5.1"
-      }
-    },
     "reactcss": {
       "version": "1.2.3",
       "resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz",
@@ -6201,11 +6208,6 @@
         }
       }
     },
-    "sister": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/sister/-/sister-3.0.1.tgz",
-      "integrity": "sha512-aG41gNRHRRxPq52MpX4vtm9tapnr6ENmHUx8LMAJWCOplEMwXzh/dp5WIo52Wl8Zlc/VUyHLJ2snX0ck+Nma9g=="
-    },
     "slash": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
@@ -7522,16 +7524,6 @@
         }
       }
     },
-    "youtube-player": {
-      "version": "5.5.2",
-      "resolved": "https://registry.npmjs.org/youtube-player/-/youtube-player-5.5.2.tgz",
-      "integrity": "sha512-ZGtsemSpXnDky2AUYWgxjaopgB+shFHgXVpiJFeNB5nWEugpW1KWYDaHKuLqh2b67r24GtP6HoSW5swvf0fFIQ==",
-      "requires": {
-        "debug": "^2.6.6",
-        "load-script": "^1.0.0",
-        "sister": "^3.0.0"
-      }
-    },
     "yup": {
       "version": "0.26.10",
       "resolved": "https://registry.npmjs.org/yup/-/yup-0.26.10.tgz",
diff --git a/bigbluebutton-html5/package.json b/bigbluebutton-html5/package.json
index e59f7f51e7a0e57340f6655610de4620630ac139..e1e0e3e9a7a04e36a21c88cd260617fd369b1001 100755
--- a/bigbluebutton-html5/package.json
+++ b/bigbluebutton-html5/package.json
@@ -62,12 +62,12 @@
     "react-dropzone": "^7.0.1",
     "react-intl": "~2.7.2",
     "react-modal": "~3.6.1",
+    "react-player": "^1.11.1",
     "react-render-in-browser": "^1.1.1",
     "react-tabs": "^2.3.1",
     "react-toastify": "^4.5.2",
     "react-toggle": "~4.0.2",
     "react-transition-group": "^2.9.0",
-    "react-youtube": "^7.9.0",
     "reconnecting-websocket": "~v4.1.10",
     "redis": "~2.8.0",
     "sdp-transform": "2.7.0",
diff --git a/bigbluebutton-html5/private/locales/en.json b/bigbluebutton-html5/private/locales/en.json
index 652d4b0005bfe5b4d2fda3bd0c99af196c09c66c..61b75fad23ef6e2ed799eadd7123a92c1445ea1d 100755
--- a/bigbluebutton-html5/private/locales/en.json
+++ b/bigbluebutton-html5/private/locales/en.json
@@ -644,16 +644,16 @@
     "app.createBreakoutRoom.roomTime": "{0} minutes",
     "app.createBreakoutRoom.numberOfRoomsError": "The number of rooms is invalid.",
     "app.externalVideo.start": "Share a new video",
-    "app.externalVideo.title": "Share a YouTube video",
-    "app.externalVideo.input": "YouTube video URL",
-    "app.externalVideo.urlInput": "Add YouTube URL",
-    "app.externalVideo.urlError": "This URL isn't a valid YouTube video",
+    "app.externalVideo.title": "Share an external video",
+    "app.externalVideo.input": "External Video URL",
+    "app.externalVideo.urlInput": "Add Video URL",
+    "app.externalVideo.urlError": "This video URL isn't supported",
     "app.externalVideo.close": "Close",
     "app.network.connection.effective.slow": "We're noticing connectivity issues.",
     "app.network.connection.effective.slow.help": "More information",
-    "app.externalVideo.noteLabel": "Note: Shared YouTube videos will not appear in the recording",
-    "app.actionsBar.actionsDropdown.shareExternalVideo": "Share YouTube video",
-    "app.actionsBar.actionsDropdown.stopShareExternalVideo": "Stop sharing YouTube video",
+    "app.externalVideo.noteLabel": "Note: Shared external videos will not appear in the recording",
+    "app.actionsBar.actionsDropdown.shareExternalVideo": "Share an external video",
+    "app.actionsBar.actionsDropdown.stopShareExternalVideo": "Stop sharing external video",
     "app.iOSWarning.label": "Please upgrade to iOS 12.2 or higher",
     "app.legacy.unsupportedBrowser": "It looks like you're using a browser that is not supported. Please use either {0} or {1} for full support.",
     "app.legacy.upgradeBrowser": "It looks like you're using an older version of a supported browser. Please upgrade your browser for full support.",