I am new to CS and currently working on personal projects. I am creating a web app where a user can copy and paste a YouTube URL to a video in a search box and then have the ability to watch the video on the same web page after clicking watch. To get the video ID, I have used a regex:
function getId(url) {
const regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/;
const match = url.match(regExp);
return (match && match[2].length === 11)
? match[2]
: null;
}
And this is how I am getting the user input:
var inputVal = document.getElementById("userInput").value;
To get the video ID, I am calling getId on the inputVal from the user:
var newVideoId = getId(inputVal)
Below is the YouTube API used to play a video on my page. However, I am finding it difficult to passing in the newVideoId variable to the API under the player object.
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: 'newVideoId', //the problem lies here
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.playVideo();
}
// 5. The API calls this function when the player's state changes.
// The function indicates that when playing a video (state=1),
// the player should play for six seconds and then stop.
var done = false;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
function stopVideo() {
player.stopVideo();
}
}
The problem is that, nothing shows on my screen after clicking the button. I am able to console.log the ID; that means I am getting the correct ID from the regex equation.
I would appreciate any help on how to use a dynamic ID gotten from user in the API! Thanks
To play a video with the iframe api providing a video Id you can use this function:
loadVideoById({'videoId': 'bHQqvYy5KYo',
'startSeconds': 5,
'endSeconds': 60,
'suggestedQuality': 'large'});
From IFrame Player API:
This function loads and plays the specified video.
The required videoId parameter specifies the YouTube Video ID of the
video to be played. In the YouTube Data API, a video resource's id
property specifies the ID. The optional startSeconds parameter accepts
a float/integer. If it is specified, then the video will start from
the closest keyframe to the specified time. The optional endSeconds
parameter accepts a float/integer. If it is specified, then the video
will stop playing at the specified time.
This should do the trick.
Related
I am dealing with this code written by somebody else and it is to load an image and a YouTube Video. My understanding his that I can change the priority of the script. Right now, it seems that when someone goes on this website with an iPhone and they hit the play button in front of the image, the video does not play, because the script is not finished loading. How do I alter the code below so that if the page or this script is not finished loading, the end user cannot see a play button?
By the way, this problem does not happen on an Android device, so I am not sure if that piece of information will serve as a clue.
I hope this makes sense because I am still trying to wrap my head around it.
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "//www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player1;
var player2;
function onYouTubeIframeAPIReady() {
player1 = new YT.Player('player', {
height: '390',
width: '640',
playerVars: {
'controls': 0,
'rel': 0
},
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
jQuery('.video-overlay').click(function() {
event.target.setVolume(100);
event.target.setPlaybackQuality('hd1080');
setTimeout(function() {
jQuery('.video-overlay').css('transform', 'scale(0)');
jQuery('.homepage-tagline').hide();
}, 300);
event.target.playVideo();
});
}
// 5. The API calls this function when the player's state changes.
// The function indicates that when playing a video (state=1),
// the player should play for six seconds and then stop.
var done = false;
function onPlayerStateChange(event) {
jQuery('.video-overlay').click(function() {
event.target.setPlaybackQuality('hd1080');
jQuery('.video-overlay').hide();
jQuery('.slider-overlay').hide();
event.target.playVideo();
});
}
function stopVideo() {
player.stopVideo();
}
I tried adding this piece of code:
jQuery('.video-overlay').css('opacity', 0);
but it didn't do much.
It would be best to set the pointer-events to none and when onPlayerReady is fired, set the target.style.pointerEvents = "all"
I am trying to get a "pause" event with the YouTube API on a YouTube video created by AMP (Accelerated Mobile Pages) with this basic example: https://ampbyexample.com/components/amp-youtube/
The code works and I get a video showing. The next thing I wanted to do was do something when the video is paused. I've had a look on how to do this and I've got the current code:
//The iframe generated from AMP does not give an ID so I have added one
$('#AMP_1 iframe').attr('id', 'yt_player');
//Load API code
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('yt_player', {
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady() {
console.log("READY");
}
function onPlayerStateChange() {
console.log("STATE CHANGE");
}
When I run this I am not getting console errors and none of the console.log calls are displaying anything. The player variable stays undefined.
The iframe produced by AMP does have "enablejsapi=1" in the URL.
Do I need to do anything/am I missing something, to get the pause event on the video?
You need to have a parameter on function onPlayerStateChange to get the event data.
function onPlayerStateChange(event) {
switch(event.data){
case 2:
console.log("PAUSE!")
break;
}
}
other event.data list
-1 (unstarted)
0 (ended)
1 (playing)
2 (paused)
3 (buffering)
5 (video cued).
I'm adding a custom player to my website and I have two issues.
My playlist on YouTube has 391 songs and the API player only loads 200.
I have problems shuffling the list using the API commands.
Here's the code that I'm using to call to the player:
<div class="videoplayer" id="ytplayer"></div>
<script>
var getRandom = function(min, max) {
return Math.random() * (max - min) + min;
};
// Load the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// Replace the 'ytplayer' element with an <iframe> and
// YouTube player after the API code downloads.
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('ytplayer', {
height: '50',
width: '400',
events: {
'onReady': onPlayerReady
},
playerVars:{
list:'PLH30k6CwlcgK8C-LET6_ZrAWwYGLqT8R-',
index:parseInt(0),
suggestedQuality:'small',
controls:0,
autoplay:1
}
});
}
function onPlayerReady(event) {
event.target.setShuffle();
event.target.setLoop();
}
</script>
I tried to workaround the shuffle thing using:
function onPlayerReady(event) {
var num = parseInt(getRandom(1,391));
event.target.playVideoAt(num);
}
But it doesn't work like I want, so I want retrieve the ID's of all the videos in the playlist into an array, mix them and pass all the array to load each video. I was trying to use some examples from previous questions but those examples are not working anymore, if some of you guys has examples with the v3 of the YouTube API or actually working examples I will appreciate it.
Regards.
First, you have to use iframe API
because, javascript API is outdated and deprecated
Look for youtube API documentation (list of deprecated api's on left side menu)
https://developers.google.com/youtube/iframe_api_reference?hl=fr
replacing
tag.src = "https://www.youtube.com/player_api";
// by
tag.src = "https://www.youtube.com/iframe_api";
and
function onYouTubePlayerAPIReady()
// by
function onYouTubeIframeAPIReady()
0 To fix shuffling, try to randomize at each end state
by using onPlayerStateChange event listener, and YT.PlayerState.ENDED
state.
1 You need to CUE the playlist to get whole video's ids
before the randomization.
and get them with proper method : getPlaylist()
var player;
var videoList, videoCount;
function onYouTubeIframeAPIReady()
{
player = new YT.Player('ytplayer',
{
height: '50',
width: '400',
events:
{
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
},
playerVars:
{
controls:0,
autoplay:0
}
});
}
function onPlayerReady(event)
{
// cue the playlist, to get the video's ids
event.target.cuePlaylist
({
listType: 'playlist',
list: 'PLH30k6CwlcgK8C-LET6_ZrAWwYGLqT8R-',
suggestedQuality:'small',
autoplay: 1,
index:0,
});
event.target.setLoop();
}
function onPlayerStateChange(event)
{
if(event.data == YT.PlayerState.CUED)
{
videoList = event.target.getPlaylist();
// to prevent adding new video and for the randomize
videoCount = videoList.length;
// get the ids before randomize playlist, send it
sendIds(videoList);
// starting the player (like autoplay)
event.target.playVideo();
}
// randomize at each video ending
if(event.data == YT.PlayerState.ENDED)
{
var num = getRandom(1,videoCount);
event.target.playVideoAt(num);
}
}
function sendIds(ids)
{
console.log(ids);
// make what you want to do with them... ajax call to your php
}
I am adding a youtube video using YouTube Player API , based on the example provided from Getting Started.
Black borders(top and bottom) are my problem. And on YouTube Player Parameters I didn't find a parameter which can solve my problem.
Is there a way to hide the black borders, without CSS?
This is the code that I use(I only added playerVars in new YT.Player):
<!--1.The <iframe> (and video player)will replace this <div> tag.-->
<div id = "player"> < div>
<script>
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height : '390',
width : '640',
videoId : 'St_dIV8NIoc',
//
// here is where youtube player parameters are placed
//
playerVars : {
controls : 0,
cc_load_policy : 0,
loop : 1,
autoplay: 1,
modestbranding: 0,
rel: 0,
showinfo: 0
},
events : {
'onReady' : onPlayerReady,
'onStateChange' : onPlayerStateChange
}
});
}
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.playVideo();
}
// 5. The API calls this function when the player's state changes.
// The function indicates that when playing a video (state=1),
// the player should play for six seconds and then stop.
var done = false;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
function stopVideo() {
player.stopVideo();
}
</script>
The example adds 30px to the standard-height(for the controls).
When you don't show the controls use the standard-size(640x360)
The standard-sizes are listed at https://developers.google.com/youtube/iframe_api_reference#Playback_quality
I was trying the following code from the samples given on developers.google.com/*
<script>
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: 'yZxrao3zou4',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.playVideo();
}
// 5. The API calls this function when the player's state changes.
// The function indicates that when playing a video (state=1),
// the player should play for six seconds and then stop.
var done = false;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
function stopVideo() {
player.stopVideo();
}
</script>
The code works perfectly when I have nothing else on my web page, but when I try to merge it with my project it doesn't seem to work.
I am guessing the problem is with the following lines:
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
Can someone tell me what does the above two lines do, especially the [0] part?
My code is pretty much the same except that instead of the script tag I have the code inside a function, which takes in a argument for the videoId.
EDIT:
My code is as follows:
<script>
// I have a input area, where the user can enter the movie name. When the user submits the movie name, I capture the val and pass it to the youtube().
function youtube(movie_name) {
var videoId;
$.ajax({
url:"https://www.googleapis.com/youtube/v3/search?part=snippet&q="+movie_name+"&type=video&key=my_key",
success: function (response) {
videoId = response.items[0].id.videoId;
findMovieById(videoId);
}
});
}
function findMovieById(videoID) {
$("#player").css('display', 'inline-block');
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: ""+videoID,
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
alert('Player Ready');
event.target.playVideo();
}
// 5. The API calls this function when the player's state changes.
// The function indicates that when playing a video (state=1),
// the player should play for six seconds and then stop.
var done = false;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
setTimeout(stopVideo, 6000);
done = true;
}
}
function stopVideo() {
player.stopVideo();
}
}
</script>
The idea behind the sample code is that it is much more consistent when you load the YouTube iFrame library code after the rest of the page has loaded; hence the sample code demonstrates that you put an inline at the bottom of the page, and within that, you traverse the DOM, find a place where you can insert another tag, and do so dynamically (the [0] just says 'the first entry in the array of all elements of name in the document).
The logic here is that, when the iFrame library loads, it will call the function onYouTubeIframeAPIReady. But since the library loads asynchronously, it's best to load it this way to ensure that anything else that your API hooks might depend on (the element in the DOM you're binding to, for example) already exists.
Also note that, because the loaded library will always call the onYouTubeIframeAPIReady function, it MUST be defined outside any other function. Otherwise it isn't callable. That could be why nesting it inside your code somewhere isn't working.
Feel free to post some of your merged code for more detailed help.