Initializing an empty player with Youtube Javascript API - youtube-api

I have made a component for my web app that initializes a YouTube player on the page. This player will be used to an un-demand video on to the page. However, when initializing the player, I have to pass a video for it to initialize:
//javascript
swfobject.embedSWF( makeUrl( 'http://www.youtube.com/v/NINOxRxze9k', {
version : 3,//youtube api version
autoplay : 0,//automatically start playing
color : 'white',//color for the 'viewed' part of the video
autohide : 0,//automatically hide the controls
controls : 0,//don't show the controls
disablekb : 1,//disable keyboard shortcuts
enablejsapi : 1,//enable javascript api
fs : 0,//disable full-screen
playerapiid : id,//player api id that is used for javascript api
//playlist : videoIds.join( ',' ),//the list of video ids to play (it can be only one item)
showinfo : 0,//don't show video information like title
rel : 0,//don't show related videos after playback is finished
theme : 'light',//use the light theme (the other one is 'dark')
showsearch : 0, //don't show the search bar (it's disabled when 'rel' is 0)
origin : window.location.hostname//it is a security thing necessary for enabling javascript api
}), id, '300', '200', '8', null, null, params, atts);
(notice the 'NINOxRxze9k' part on the first line).
The question is: how can I initialize a YouTube player without initializing it for a specific video? I don't want it to show a snapshot of the video ready to be played. I want it to be blank before I start playing anything on it.
Sitenote: as you can see from Google's documentation, the VIDEO_ID is passed to embedSWF(). I tried removing it but it stopped working.

I think that this is the answer to the same question, but if you use the Player IFrame API:
Init YouTube iframe player without video ID

Not sure if this will help but here it is anyway.
I have played with YT-api for a while in flash and web for different projects and found it to be a LARG system that takes a lot of reading.
The only time I have found it to have a blank player loaded was in a flash app. Also it needed to be chromeles.
I did an "amature" tutorial with download for people here.
http://www.youtubetutsite.com/player.php?videoID=kO_WVIYdLDc
Only sugesting as you are using the SWF player in your app.

Related

How can I activate subtitles by default in the Dailymotion embedded player for any language

Dailymotion embed URLs can activate subtitles by default:
https://www.dailymotion.com/embed/video/x7n59nb?subtitles-default=en
But the embed player needs to know the language for that.
It would be nice to be able to activate subtitles regardless of language for the
video software I am using, as I don't want to store the language for every video.
Is there a way to activate just any subtitle eg:
https://www.dailymotion.com/embed/video/x7n59nb?subtitles-default=any (or first)
Or to give the player a list of possible subtitles:
https://www.dailymotion.com/embed/video/x7n59nb?subtitles-default=de,en
It's not possible to directly activate subtitles with a random value.
With an API call you can retrieve the list of available subtitles for a specific video by using the endpoint: https://api.dailymotion.com/video/{id_of_video}/subtitles Documentation
If you are in a browser, you can maybe use the navigator.language to set the value of the subtitles.
With the dailymotion-sdk-js (Documentation), you can use the events to set your subtitle randomly:
var player = DM.player(document.getElementById("player"), {
video: "x7n59nb"
});
player.addEventListener('playback_ready', function (e)
{
if(e.target.subtitles.length > 0){
var random = Math.floor(Math.random() * Math.floor(e.target.subtitles.length));
playlists.setSubtitle(e.target.subtitles[random])
}
});

Turbolinks and autoplay HTML5 video

I just started a Rails 5 project, and on the homepage I'm supposed to have a video banner, muted, in loop autoplay. I'm using Turbolinks 5 and I don't know if I can keep it.
When I load the home page for the first time, everything works fine. But when I go to any other page, the sound of the home page video starts to play. And If I go back to the home, the sound start again, over the sound previously started.
And so I have multiple instance of the sound of the muted video playing at the same time.
Fun at first, nightmare after 5 seconds.
I've seen this issue: https://github.com/turbolinks/turbolinks/issues/177 , which is still open and have no practical solution in the comments.
Apparently it's not new, this post https://www.ruby-forum.com/topic/6803782 seems to talk about the same problem in 2015. The guy talks about disabling Turbolinks for the link that lead to that page. I can't do it, since my problem is on the home page.
This is due to Turbolinks caching a copy of the homepage DOM. Even though the video is not visible it still exists in the cache and so will play. (However, I'm not sure why it's not muted—this could be a browser bug :/)
I think Turbolinks could handle this by default, but in the meantime, here are a couple of options:
Solution 1: Disable Caching on the Homepage
To prevent Turbolinks from caching a copy of the homepage, you could disable caching for that page. For example, you could include the following in your layout's <head>:
<% if #turbolinks_cache_control %>
<meta name="turbolinks-cache-control" content="<%= #turbolinks_cache_control %>">
<% end %>
Then in your homepage view:
<% #turbolinks_cache_control = 'no-cache' %>
The downside is that you miss out on the performance benefits when the visitor revisits the homepage.
Solution 2: Track autoplay elements
Alternatively, you could track autoplay elements, remove the autoplay attribute before the page is cached, then re-add it before it's rendered. Similar to Persisting Elements Across Page Loads, this solution requires that autoplay elements have a unique ID.
Include the following in your application JavaScript:
;(function () {
var each = Array.prototype.forEach
var autoplayIds = []
document.addEventListener('turbolinks:before-cache', function () {
var autoplayElements = document.querySelectorAll('[autoplay]')
each.call(autoplayElements, function (element) {
if (!element.id) throw 'autoplay elements need an ID attribute'
autoplayIds.push(element.id)
element.removeAttribute('autoplay')
})
})
document.addEventListener('turbolinks:before-render', function (event) {
autoplayIds = autoplayIds.reduce(function (ids, id) {
var autoplay = event.data.newBody.querySelector('#' + id)
if (autoplay) autoplay.setAttribute('autoplay', true)
else ids.push(id)
return ids
}, [])
})
})()
This script gets all the autoplay elements before the page is cached, stores each ID in autoplayIds, then removes the autoplay attribute. When a page is about to be rendered, it iterates over the stored IDs, and checks if the new body contains an element with a matching ID. If it does, then it re-adds the autoplay attribute, otherwise it pushes the ID to the new autoplayIds array. This ensures that autoplayIds only includes IDs that have not been re-rendered.

Failed to execute 'postMessage' on 'DOMWindow': target/origin mismatch http vs https

I apologize up front as I'm very confused by my problem. I'm really in a bind because this is causing a problem on my production site.
I have a javascript player on my site which plays through song lists which can be hosted on youtube, soundcloud or vimeo. Yesterday I noticed this error which generally arises anytime you try to load a new song through "skipping" with the player buttons. This error just started in the last day or two. I am not seeing anything new in the youtube api release notes and this error occurs using Chrome, Firefox and Safari, so it is most likely not related to a change in the browser. Something that I am using has changed though, as I have not pushed new code in 18 days.
An example playlist is here: http://www.muusical.com/playlists/programming-music
I think I have isolated the way to reproduce the error, here are the steps:
Play a youtube hosted song.
Skip to any other song in the list (whether by pressing the skip buttons or directly pressing the play button on the song's row item).
*Note, that if the first song in the playlist is a youtube song, simply skipping to another song even without playing the initially loaded youtube song will produce the error.
Essentially, the error seems to occur once you have loaded and/or played a youtube song and attempt to skip to another song.
Let me know if you find an exception to this behavior.
I see this error in the console:
Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('https://www.muusical.com') does not match the recipient window's origin ('http://www.muusical.com').
I load the player with using the youtube javascript api:
new YT.Player('playlist-player', {
playerVars: { 'autoplay': 1, 'fs': 0 },
videoId: "gJ6APKIjFQY",
events: {
'onReady': #initPlayerControls,
'onStateChange': #onPlayerStateChange
}
})
Which produces this iframe:
<iframe id="playlist-player" frameborder="0" allowfullscreen="1" title="YouTube video player" width="640" height="360" src="https://www.youtube.com/embed/gJ6APKIjFQY?autoplay=1&enablejsapi=1&origin=http%3A%2F%2Fwww.muusical.com"></iframe>
After hitting skip from the above youtube song, this is what I see loaded in the iframe:
<iframe id="playlist-player" frameborder="0" allowfullscreen="1" title="YouTube video player" width="640" height="360" src=""></iframe>
I support youtube, soundcloud and vimeo songs. It seems like once a youtube song is loaded the "origin" changes from http to https. I don't think it is necessary to include the embedding methods for the other hosts as this error occurs even if the entire playlist is only youtube and it does not occur in a playlist which consists of only songs from soundcloud and vimeo.
Also, this is how I am loading the youtube javascript:
// 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);
Please let me know if you need me to clarify anything and thanks in advance for taking a look.
I have read a bit about this, some SO posts here and there and this link too : https://code.google.com/p/gdata-issues/issues/detail?id=5788
I was about to add a comment to your question, saying I was getting crazy over this ... but when I started to describe my setup, I found a way to avoid the issue ^^.
I start with an empty div element, and use the Youtube Iframe API to turn it into an iframe with all the necessary options.
I have multiple divs like this one, and usually use the same JS variable to store all those players, but one at a time (one replaces the other, and so on ... - it could be better, I know).
To fix the issue, I had the idea to destroy the player with youtubePlayer.destroy(); before building a new one from another element. No more JS errors bleeding in my Chrome console :).
Hope it helps, all the litterature I could read about http and https did not apply to my case, because I am not setting the iframe URL myself, and my website happens to be not https ...
I did restore an async call instead of a static script tag in my HTML but I do not think this was necessary.
EDIT : this error message is quite misleading in fact, it only vaguely means : you are not using the youtube API the proper way :)
#sodawillow's answer is partially correct but I'd like to give the details to the solution and what caused my code to stop calling the .destroy() method to remove the youtube player.
My site has a player which swaps out songs from various sites, one of them being Youtube. There can be different methods for removing a player depending on the type it is. My code checks for the existence of a youtube player and if passes the check then it uses the .destroy() method which only the youtube player has. The problem is that YouTube changed the names of some of the static variables on their player object. For example, if I created a player via:
var player = new YT.Player('playlist-player', {
playerVars: { 'autoplay': 1, 'fs': 0 },
videoId: "gJ6APKIjFQY",
events: {
}
})
then there would be a variable player.L which held the string "player". So to check if the current player was a YouTube player and remove it I did this:
if (player.L == "player") {
player.destroy();
} else {
//handle the removal of the Soundcloud or Vimeo player.
}
Sometime recently Youtube changed the location of the string "player" to now reside at player.M. I could change the above code to check player.M instead of player.L and that would work but to try to avoid this issue in the future I instead have implemented:
if (player.destroy) {
player.destroy();
} else {
//handle the removal of the Soundcloud or Vimeo player.
}
As long as Youtube does not remove the .destroy() method unannounced this will not cause any issues.
So in summary, the issue was as #sodawillow guessed, I was not using the .destroy() method to remove the Youtube player. The reason was because Youtube made some unannounced changes to their api, changing the location of some of the static variables.
This error belongs to the Google Youtube API.
Inside "https://www.youtube.com/iframe_api":
if (!window['YT']) {
var YT = {loading: 0, loaded: 0};
}
if (!window['YTConfig']) {
var YTConfig = {'host': 'http://www.youtube.com'};
}
They use http instead of https.
We need to override the 'host' option and 'widget_referrer' same as 'origin'.
player = new YT.Player('player', {
host: 'https://www.youtube.com',
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE'
...
origin: "https://www.enziin.com",
widget_referrer: "https://www.enziin.com"
}
Goodluck.
My solution is to write all the Youtube player logic in a separate page (as blank as posible) , and that page be referenced in an IFRAME tag.
<iframe src="/youtube_frame/?data=SOME_DATA -%>" height="400px" width="100%" frameborder="0" border="0" scrolling="no"></iframe>
Then, your youtube_frame.html will be something like this:
<!DOCTYPE html>
<html>
<body>
<!-- 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: 'M7lc1UVf-VE',
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) {
console.log("OnplayerStateChange");
if (event.data == YT.PlayerState.PLAYING && !done) {
console.log("OnplayerStateChange - If statement");
setTimeout(stopVideo, 6000);
done = true;
}
}
function stopVideo() {
player.stopVideo();
}
</script>
</body>
</html>
(As a marginal note: my context is that Prototype.js interferes with the event 'OnStateChange', and we cannot remove this dependency.
Using a jsfiddle would not be useful to reproduce the issue, as it has few dependencies.
My app here is built in Rails, and using this plugin for showing a Video playlist: https://github.com/Giorgio003/Youtube-TV/)

Photoswipe Custom Hashtag Immediately Closes Slideshow

Testing on the desktop with JQM doesn't produce this issue, so it's difficult to pinpoint.
Backstory: I have created server side code (php) to accept a query string and open a gallery straight to a picture. But if a user wants to share a link while surfing a gallery on a mobile device, and in particular a certain photo; most Mobile Browsers share the core link and not the actual photo. It's easy in the events when swiping to create a URL hashtag modifier for the URL with the photo id ( For example #photoID=987), but only if the gallery is originally started with no hashtags. It's then easy to share with a Phone's Native methods.
(function(window, $, PhotoSwipe){
$(document).ready(function(){
//More Code is here but not needed fro this question
$(photoSwipeInstance).bind(PhotoSwipe.EventTypes.onDisplayImage, function(e){
var pid = codeThatGetsPhotoIDFromDisplayedIMGURL();
window.location.hash = '&pid='+pid[0];
});
if(getUrlVars()["pid"]!=null || getUrlVars()["pid"]!=undefined)
{
console.log(getUrlVars()["pid"]);
var photopid= getPhoto(getUrlVars()["pid"]);
photoSwipeInstance.show(photopid);
}
});//End Documentstrong text
}(window, window.jQuery, window.Code.PhotoSwipe));
function getUrlVars()
{
var vars = [], hash;
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
for(var i = 0; i < hashes.length; i++)
{
hash = hashes[i].split('=');
vars.push(hash[0]);
vars[hash[0]] = hash[1];
}
return vars;
}
Issue: If a gallery is loaded with a hashtag the gallery will pop up the proper image but then immediately closes the slide show. And every photo past this point performs in the same manner, slideshow opens then closes.
I have turned off all AJAX, and hashtag anchor functions JQM utilizes. This hashtag url functions works as intended when using a Desktop browser but not when using any Mobile browser.
Has someone else tried this functionality?
I probably made this much more confusing then it is in my description.
Answer: JQM's hashtag handlers did not need to be turned off instead. Photoswipe needed this handler added to the options: backButtonHideEnabled: false
JQM's hashtag handlers did not need to be turned off instead. Photoswipe needed this handler added to the options: backButtonHideEnabled: false

Prevent YouTube auto-play with Fancybox?

If I Fancybox the youtube link (as opposed to embedding the code as normally w/o fancybox) how can I avoid autoplay on pageload?
I want to be able to click the image for it to start playing.
http://www.estherwarda.com/wci/homepage/
If you're using the latest version of Fancybox (2+), YouTube and Vimeo are now recognized and handled quite well.
However, it took some digging around to find this out since most documentation is on Fancybox 1.
Fancybox strips your YouTube URL and adds some default parameters:
autoplay=1 (videos will autoplay)
autohide=1 (control will hide once video is playing)
fs=1 (fullscreen is enabled)
rel=0 (related videos are hidden)
hd=1 (HD playback is enabled)
wmode=opaque (fixes z-index with YouTube and lightboxes)
enablejsapi=1 (enables Javascript API)
What this means that normally you could pass those parameters in your URL and have them apply, but Fancybox 2 ignores those and falls back on the preset values.
Don't dismay! You can override those in your script. Several ways.
Normal media embed:
$(".fancybox").fancybox({
helpers : {
media: true
}
});
Custom URL parameters method 1:
$(".fancybox").fancybox({
helpers : {
media: {
youtube : {
params : {
autoplay : 0
}
}
}
}
});
Custom URL parameters method 2:
$(".fancybox").fancybox({,
helpers : {
media: true
},
youtube : {
autoplay: 0
}
});
Look in the helpers > jquery.fancybox-media.js file for more details (check the comments). Fancybox 2 also supports a variety of URL formats so you don't need to worry about which URL version you should be using (i.e. youtube.com/watch?v=### vs. youtu.be/###).
It's about your embed code. Youtube's old default embed code looks like that: http://www.youtube.com/v/bla?version=3. It can be take autoplay parameter that controls the playing on loading. You can push back &autoplay=0 to http://www.youtube.com/v/bla
http://www.youtube.com/v/bla?version=3&autoplay=0

Resources