heisenberg
heisenberg

Reputation: 1954

Unable to load youtube video using <video> tag where youtube url is inputted in textfield

I'm working on a modal window which allows user to either 1.) paste a video url or 2.) select a file from local drive then get a preview using html5's <video>tag.

Option 2.) Selecting a video file locally work perfectly. However, when I paste a youtube video url on input text field, the video player shows a loading indicator then stops. You can't play the video and doesn't seem to load successfully.

I checked Google Chrome's inspector and get this message

Cross-Origin Read Blocking (CORB) blocked cross-origin response https://www.youtube.com/... with MIME type text/html.

I suspect the problem is in this line.

$('#modalInput_pasteURL').on('input',function(e){
    var videoUrl = $('#modalInput_pasteURL').val().trim();
    $(".video").attr("src", videoUrl);
});

I read while doing research that <iframe> must be used to contain or play a youtube video from a url. In this case, I'd like to use just <video> tag so that I only have one video container.

What am I missing? Any suggestions?

Below is are the code snippets.

HTML file

<label>Paste Url here</label>
<input type="text" class="modal_inputbox" id="modalInput_pasteURL"/><br>

<label>Select Video</label>
<input type="file" class="modalbtn_browseFiles" id="modalBtn_choose_video_file"  value="Browse Video" accept="video/*"/><br>

<label>Video Preview</label>
<div class="modalContainer_filePreview" id="modalContainer_videoPreview">
<video controls class="video" width="510" height="200">
</video >
</div>

JS file

$('#modalInput_pasteURL').on('input',function(e){
    var videoUrl = $('#modalInput_pasteURL').val().trim();
    $(".video").attr("src", videoUrl);
});

$("#modalBtn_choose_video_file").on('change',function(event){
    var fileInput = document.getElementById('modalBtn_choose_video_file');
    var fileUrl = window.URL.createObjectURL(fileInput.files[0]);
    $(".video").attr("src", fileUrl);
});

Thank you.

Upvotes: 1

Views: 10442

Answers (3)

zer00ne
zer00ne

Reputation: 44078

YouTube videos can be embedded into a webpage by either using a <div> or an <iframe> tag and loading YouTube IFrame Player API. The following Demo is a modification of the OP code. It can play either a standard video or a YT video. The Stack Snippet cannot play YouTube videos on SO site, so to properly test it, you either copy and paste the entire code elsewhere or go to this Plunker.

Note: There is some code commented out that is included should you want to load the YT API in order to control the YT player programmatically.


Plunker

Demo

Details commented in Demo

The YouTube video will not play on SO due to sandbox, go to Plunker for a fully functional Demo


/* If you want programattic control over the YT Player uncomment
|| the following block and the block after the next block
*/
/*/ Load YouTube IFrame Player API
var tag = document.createElement('script');
tag.src = 'https://www.youtube.com/iframe_api';
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
*/

// Reference video tag
var vid = document.getElementById('vid');

/*/ Declare YT Player
var ytv;
// Define YT Player 
function onYouTubeIframeAPIReady() {
  ytv = new YT.Player('ytv');
}
*/

// Seup switch behavior
$('.switchBtn').on('click', function(e) {
  $('.switchBtn').removeClass('act');
  $(e.target).addClass('act');
});

// Delegate input event to #pasteURL
$('#pasteURL').on('input', function(e) {

  // Get the url string
  var videoUrl = $('#pasteURL').val().trim();
  // if the "Standard Video" switch is active...
  if ($('.v').is('.act')) {
    // ...enable controls on vid...
    vid.controls = true;
    // ...set src to url string...
    vid.src = videoUrl;
    // ...reset vid so it cues new url
    vid.load();
    // ...otherwise...
  } else {
    // ...pause vid...
    vid.pause();
    // ...reset vid...
    vid.currentTime = 0;
    // ...remove vid controls...
    vid.controls = false;
    // ...set ytv src to new url
    $('#ytv').attr('src', videoUrl);
  }
});

$("#file").on('change', function(event) {
  var fileInput = $('#file')[0];
  var fileUrl = window.URL.createObjectURL(fileInput.files[0]);
  $("#vid").attr("src", fileUrl).prop("controls", true);
});
input,
label {
  display: inline-block;
  font: inherit;
  margin: 10px 0 0 0;
}

input[type=text] {
  width: 350px;
}

.group {
  pointer-events: none;
  opacity: 0.4;
}

.switchBtn {
  width: 110px;
  height: 18px;
  margin: 15px -2px 10px -2px;
  border: 3px outset grey;
  padding: 2px 3px 0;
  cursor: pointer;
}

.switchBtn.act {
  background: tomato;
  color: #fff
}

.switchBtn.act~.group {
  pointer-events: auto;
  opacity: 1;
}

.switchBtn.v {
  border-top-left-radius: 12px;
  border-bottom-left-radius: 12px;
  text-align: right;
}

.switchBtn.y {
  border-top-right-radius: 12px;
  border-bottom-right-radius: 12px;
}

.switch {
  display: none
}

.switch:checked+* {
  height: 405px;
  transition: 1s;
}
<!DOCTYPE html>
<html>

<head>
  <!--<link rel="stylesheet" href="style.css">-->

</head>

<body>

  <label for='vidURL' class='switchBtn v'>Standard Video</label>

  <label for='ytvURL' class='switchBtn y'>You Tube Video</label>
  <br>
  <fieldset class='group'>

    <label>Test Std URL: </label>
    <input type='text' readonly value='https://ia800209.us.archive.org/24/items/WildlifeSampleVideo/Wildlife.mp4'>
    <br>
    <label>Test YT URL: </label>
    <input type='text' readonly value='https://www.youtube.com/embed/Ch5MEJk5ZCQ?enablejsapi=1'>
    <br>

    <label>Paste Url here </label>
    <input type="text" id="pasteURL" />

  </fieldset>

  <label>Select Video </label>
  <input type="file" id="file" value="Browse Video" accept="video/*" />
  <br>

  <label>Video Preview</label>
  <figure class="filePreview">

    <input id='vidURL' type='radio' name='switch' class='switch'>

    <video id="vid" width="100%" height="0"></video>

    <input id='ytvURL' type='radio' name='switch' class='switch'>

    <iframe id="ytv" type="text/html" width="100%" height="0" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>

  </figure>



  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

  <!--<script src="script.js"></script>-->
</body>

</html>

Upvotes: 2

heisenberg
heisenberg

Reputation: 1954

After doing some research and also taking the comment of zer00ne and Adam McGurk into consideration, I realized that the best way to load the youtube video url is through <iframe> then the problem of isolating or obtaining the youtube video's id came up.

Then, I ended up finding a related resource and answer here in SO which solved my problem.

function getYoutubeVideoId(url) {
    var regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/;
    var match = url.match(regExp);
    if (match && match[2].length == 11) {
        return match[2];
    } else {
        return 'error';
    }
}

$('#modalInput_pasteURL').on('input',function(e){
    var videoUrl = $('#modalInput_pasteURL').val().trim();
    var videoId = getYoutubeVideoId(videoUrl);
    $('#modalContainer_videoPreview').html('<iframe width="510" height="200" src="//www.youtube.com/embed/' + videoId + '" frameborder="0" allowfullscreen></iframe>');
});

This should serve as reference to others who are trying to accomplish the same effect when pasting a youtube url in a text field and loading it to a container such as an <iframe> which works best.

Upvotes: 2

Adam McGurk
Adam McGurk

Reputation: 476

There are a couple of problems here, and it doesn't even necessarily have to do with your code. I didn't even look at your code here, because it's unimportant.

You will not be able to take a YouTube URL and paste it into the src attribute of the video tag and have it play. That just isn't how YouTube works.

  1. YouTube doesn't serve it's videos by plain URLs. Imagine if they did that, anybody could get into the inspect tool and download the video straight from YouTube.

So how do they serve their videos? Through BLOBs:

  1. Here's a pretty good explanation of what a BLOB is: https://developer.mozilla.org/en-US/docs/Web/API/Blob

So you won't be able to just take the URL, it's just not how YouTube works. And so the way I would frame your code would be to have a control statement that detects if there is an iframe tag or not, and if there is, insert just the iFrame, but if there is not, insert your video URL.

Obviously there are many security holes there, but that is out of the scope of this answer. If you want to go more of the route that I outlined a little bit, do some research, ask another question, and we'd be glad to help you out!

Upvotes: 0

Related Questions