天道酬勤,学无止境

YouTube API - Firefox/IE return error “X is not a function” for any 'player.' request

I've been pulling my hair out trying to get a fairly simple YouTube api integration working in FF/IE and have had no luck so far.

It sounds like either a scope issue or a call being made before the player is initialized but everything I've tried suggests it's not one of those two things. Also of note, everything works perfectly in (only) Chrome.

// Async api load per YT documentation...
var tag = document.createElement('script');
tag.src = "//www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

// Declare player and set basic functions...
var player

playVideo = function() { player.playVideo(); }
stopVideo = function() { player.stopVideo(); }

// YT Api ready function...
function onYouTubeIframeAPIReady() {
  player = new YT.Player('player', {
    videoId: "TkJcg4bmAYs",
    events: {
      'onStateChange': onPlayerStateChange
    }
  });

  // After player object created, bind popup function to page anchors...
  var popup = $('#video-popup')
  ,   popupFrame = $(popup).children('.center')
  ;

  $('a[data-vid]').click(function(e){
    e.preventDefault ? e.preventDefault() : e.returnValue = false;

    var clicked = $(e.target).closest('a')
    ,   videoID = $(clicked).attr('data-vid')
    ;

    if (!$(popup).hasClass('working')){
      // If popup isn't already working, cue video and animate popup in... 
      player.cueVideoById({videoId:videoID});

      $(popup).addClass('working');
      $(popup).css('display','block').animate({
        opacity: '1'
      }, 200, function(){
        playVideo();
        $(popup).removeClass('working');
      });
    }
  });
}

Link to test page with the api and popup code, working in Chrome but not in other browsers. http://www.crackin.com/dev/regions/pathBuild/

评论

After imbedding half of my keyboard keys into my forehead, I finally stumbled across the frustratingly simple root of the problem... It's nothing but a visibility issue! ARRGG!!! Apparently, FireFox and IE do not have access to the player object if it is initialized while set to display:none;, but Chrome is smart enough to still initialize and target it even hidden.

The fix, in my particular case, was to load the popup as display:block with opacity:0, THEN initialize the api, THEN set the popup to display:none inside the YT api init function. Something like this:

First, CSS...

#video-popup { display: block; opacity: 0; }

.. then javascript...

var player
,   popup = $('#video-popup')
;

function onYouTubeIframeAPIReady() {
    player = new YT.Player('player', {
        videoId: "TkJcg4bmAYs"
    });
    $(popup).css('display','none');
}

Now I need to go get drunk.


ADDITIONAL STUFF: After finally figuring out the root of the problem, I was able to isolate some additional IE browser problems and work out solutions. These are just in case somebody else is having a similar issue, they may be able to carve out their own solution from this. My solution might be a bit situation-specific, but if anybody else is putting youtube videos in popups and needs IE support, this might help.

The fix above (setting display:none in the YT ready function) didn't seem to work perfectly for IE8, but was quickly fixed by wrapping it in a brief timeout:

function onYouTubeIframeAPIReady() {
    player = new YT.Player('player', {
        videoId: "TkJcg4bmAYs"
    });
    setTimeout(function(){
        $(popup).css('display','none');
    }, 500);
}

IE7 was a bit trickier, as it seems that if the player is EVER hidden using display:none, it immediately becomes unavailable regardless of whether it's been initialized or not.

Using conditional comments to apply classes to the tag, you can add some IE specific css to keep the popup "visible" but hide it offscreen instead.

#video-popup { position: fixed; top: 0; left: 0; width: 100%; height: 100%; display: none; opacity: 0; }
.ie7Detect #video-popup { display: block; left: -101% }
#video-popup.open { left:0 !important; }

There is also an issue where in both IE7 and 8 the youtube player is still visible even when the parent container is set to opacity 0 (which happens while page is still loading). I tried adding rules to further target the contents of the popup and set their opacity also, but didn't work and wasn't super clean either. What I settled on was using a loading class.

So the popup has a loading class:

<div id="video-popup" class="loading">
    <!-- bunch of stuff in here -->
</div>

And function is updated...

function onYouTubeIframeAPIReady() {
    player = new YT.Player('player', {
        videoId: "TkJcg4bmAYs",
    });
    setTimeout(function(){
        $(popup).removeClass('loading');
    }, 500);
}

CSS looks something like this...

#video-popup { position: fixed; top: 0; left: 0; width: 100%; height: 100%; display: none; opacity: 0; }
.ie7Detect #video-popup, #video-popup.loading { display: block; left: -100% }
#video-popup.open { left:0 !important; }

The last piece of the puzzle would be to incorporate a classname 'open' for your popup function when it's actually suppose to be visible.

Hope that helps somebody avoid some potential headaches in the future. On the downside, you may not be QUITE as enthusiastic to get drunk after addressing these issues as you might have otherwise been.

Peace, yo.

First off, thanks for figuring this out. Like you, I think I tried every solution I could find to no avail.

Second, I'm writing because although my issue was very similar in nature, I was trying to load a video via the bxSlider jQuery plugin and I wanted to post my solution in hopes it could save someone else some time.

I simply just called a function on the onSliderLoad method. Here's what the function looks like:

function()
{
  if ($('.slideshow-item-video').length > 0) {

    $('.slideshow-item-video').each(function()
    {
      $(this).css('display', 'block');

      setTimeout(function()
      {
        $(this).css('display', 'none');
      }, 500);
    });
  }
}

I'm simply giving slides that contain a video a specific class and making them visible so the API can access the element, then setting a timeout to hide the element again.

This solution works in Firefox and IE8+. I have not figured out a solution for IE7, but, it's IE7.

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 嵌入式YouTube视频不会重播(Embedded YouTube videos won't replay)
    问题 奇怪的一个:嵌入式YouTube视频一旦播放(通过单击“播放”或在页面加载时自动播放),将无法再次播放。 我使用的是直接从YouTube复制的标准iFrame嵌入。 在几个不同的简短视频中,以及在我测试过的所有浏览器/操作系统组合中(Windows / Mac上的Chrome / Safari / Firefox / IE),都会发生这种情况。 这是代码: <iframe width="420" height="315" src="//www.youtube.com/embed/OuSdU8tbcHY" frameborder="0" allowfullscreen></iframe> 您可以在这个小提琴中看到它的实际效果。 回答1 因此,问题似乎与视频时长无关; Flash播放器有问题。 如果加载了Flash Player,并且根本没有用户与控件的交互,则当Flash Player结束时,它不会重新加载iframe(尽管事实是它引发了“视频结束”事件...当您尝试执行以下操作时:重新加载,它将不会发出正确的调用来重新加载视频,因此永远无法重新开始播放)。 您也可以测试更长的视频; 如果您开始观看它们并且不使用滚动条,它们将表现出相同的行为。 同样,在非常短的视频上,如果您开始播放然后稍稍擦一下(甚至是时间倒退),则会触发iframe重新加载(类似于
  • Youtube Embed Iframe - Events Not Firing In Local
    I've just noticed that the Youtube events (onReady, onStateChange) are no longer firing when I am testing in my local, but works when I upload the code to JsFiddle. I've decided to copy and paste the code from Youtube Player API where I am able to verify that it indeed is not working. Is anyone else having this issue? This issue occurs on Chrome, Firefox, IE, Safari, and Opera. EDIT - When I console.log(player); in my local, I see that it is missing a lot of Youtube functions such as seekTo(), setVolume(), showVideoInfo() which are present in JsFiddle. I am unsure why this is happening, but I
  • YouTube嵌入iframe-事件未在本地触发(Youtube Embed Iframe - Events Not Firing In Local)
    问题 我刚刚注意到,当我在本地进行测试时,不再触发Youtube事件(onReady,onStateChange),但是当我将代码上传到JsFiddle时,该事件才起作用。 我决定从Youtube Player API复制并粘贴代码,在此我可以验证它确实不起作用。 还有其他人遇到这个问题吗? 此问题在Chrome,Firefox,IE,Safari和Opera上发生。 编辑-当我console.log(player); 在我的本地环境中,我发现它缺少许多Youtube函数,例如seekTo() , setVolume() , showVideoInfo() 。 我不确定为什么会这样,但是我相信这可能是我问题的根源。 有任何想法吗? http://jsfiddle.net/8ZmKx/ <!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
  • Problems with Youtube Iframe Api to start playing video on Chrome
    I have following starting setup: var player; function onYouTubeIframeAPIReady() { player = new YT.Player('player', { events: { 'onReady': onPlayerReady, 'onStateChange': onPlayerStateChange } }); } Then in onPlayerReady handler I added event listener to button which is outside iframe: function onPlayerReady(event) { button.addEventListener('click', () => event.target.playVideo()); } In onPlayerStateChange I'm just logging what is happening: function onPlayerStateChange(event) { console.log(event.data); } After hitting that button in Chrome (v.72.0.3626.119) there are 3 entries in console: -1
  • Bootstrap模式关闭时,Youtube视频仍在播放(Youtube Video Still Playing When Bootstrap Modal Closes)
    问题 我正在创建一个带有引导程序的网站,可以在这里找到-http://www.branchingouteurope.com/digital-spark-testing/ 如果您选择视频图像,则会看到一个模态窗口,打开youtube视频。 我的问题是,当关闭模态窗口时,视频将继续播放。 我希望该视频在模式窗口关闭时停止播放。 我在网上看过并阅读了许多解决方案,但是似乎都没有用。 这是标记... <span class="main_video"> <div data-toggle="modal" data-target="#myModal" style="cursor:pointer"> <img src="img/master/video.fw.png" height="81%" width="60%" alt="Digital Spark Video"/> </div> </span> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> </div> <div class="modal-body">
  • How to avoid Security Errors when using the Youtube AS3 Player API
    I'm using the Youtube AS3 Player API to load video's in a Flash Project. I get this really annoying Error when loading the Player swf: SecurityError: Error #2047: Security sandbox violation: parent: http://www.degoudenglimlach.be/main.swf cannot access http://www.youtube.com/[[IMPORT]]/s.ytimg.com/yt/swf/watch_as3-vflbgr4dW.swf. I tried adding the following to my code before loading the swf but it doesn't make any difference: Security.allowDomain("*"); Security.allowDomain("www.youtube.com"); Security.allowDomain("youtube.com"); Security.allowDomain("s.ytimg.com"); Security.allowDomain("i
  • Youtube API-提取视频ID(Youtube API - Extract video ID)
    问题 我正在编写一种功能,允许用户输入Youtube视频URL。 我想从这些网址中提取视频ID。 Youtube API是否支持某种函数,我可以通过该函数传递链接,它会返回视频ID。 还是我必须自己解析字符串? 我正在使用PHP ...在此方面,我将不胜感激任何指针/代码示例。 谢谢 回答1 这是一个使用正则表达式从URL提取youtube ID的示例函数: /** * get youtube video ID from URL * * @param string $url * @return string Youtube video id or FALSE if none found. */ function youtube_id_from_url($url) { $pattern = '%^# Match any youtube URL (?:https?://)? # Optional scheme. Either http or https (?:www\.)? # Optional www subdomain (?: # Group host alternatives youtu\.be/ # Either youtu.be, | youtube\.com # or youtube.com (?: # Group path alternatives /embed/ #
  • 使用youtube api加载多个视频播放器(loading multiple video players with youtube api)
    问题 我需要使用YouTube的API加载多个视频。 这是我第一次使用它,所以我不确定自己在做什么错,但这是我正在尝试的事情: var player; var player2; function onYouTubePlayerAPIReady() { player = new YT.Player('player', { videoId: 'hdy78ehsjdi' }); player2 = new YT.Player('player', { videoId: '81hdjskilct' }); } 回答1 由于应该仅使用以下方法才调用onYouTubeIframeAPIReady函数: 初始化并将视频播放器信息( ControlId,width,height,VideoId )保存在数组中调用onYouTubeIframeAPIReady函数来创建所有视频​​播放器 例子 var playerInfoList = [{id:'player',height:'390',width:'640',videoId:'M7lc1UVf-VE'},{id:'player1',height:'390',width:'640',videoId:'M7lc1UVf-VE'}]; function onYouTubeIframeAPIReady() { if(typeof
  • YouTube iframe API:如何控制HTML中已经存在的iframe播放器?(YouTube iframe API: how do I control an iframe player that's already in the HTML?)
    问题 我希望能够控制基于iframe的YouTube播放器。 该播放器已经存在于HTML中,但是我想通过JavaScript API对其进行控制。 我一直在阅读iframe API的文档,其中解释了如何使用API​​将新视频添加到页面,然后使用YouTube播放器功能对其进行控制: var player; function onYouTubePlayerAPIReady() { player = new YT.Player('container', { height: '390', width: '640', videoId: 'u1zgFlCw8Aw', events: { 'onReady': onPlayerReady, 'onStateChange': onPlayerStateChange } }); } 该代码创建了一个新的播放器对象,并将其分配给“ player”,然后将其插入#container div中。 然后,我可以在'player'上进行操作,并在其上调用playVideo() , pauseVideo()等。 但我希望能够在页面上已经存在的iframe播放器上进行操作。 使用旧的embed方法,我可以很容易地做到这一点,例如: player = getElementById('whateverID'); player.playVideo()
  • YouTube Api for android exception “service_missing”
    I want to play you tube video in my android application I got exception while youtube initialization like "service_missing". I write following code, package com.example.youtubedemo; import android.os.Bundle; import android.view.Menu; import android.widget.Toast; import com.google.android.youtube.player.*; import com.google.android.youtube.player.YouTubePlayer.OnInitializedListener; import com.google.android.youtube.player.YouTubePlayer.Provider; public class MainActivity extends YouTubeBaseActivity implements OnInitializedListener{ static private final String DEVELOPER_KEY = "MY API KEY"
  • 带有 jQ​​uery 的 Youtube iframe 播放器 JS API - 播放器对象没有方法“getPlayerState”(Youtube iframe player JS API with jQuery - player object has no method 'getPlayerState')
    问题 我有以下代码,假设在发生鼠标悬停事件时暂停 Slidedeck 的自动滚动。 对于 mouseout 事件,除非 Slidedeck 中的 youtobe 视频当前正在播放或缓冲,否则自动滚动应该继续工作。 如果没有 Youtube 视频的条件,我就可以正常工作。 我认为对象播放器的范围存在问题,但无法解决,如何解决此问题。 我在 mouseout 控制台中得到的错误是: 未捕获的类型错误:对象 #<T> 没有方法“getPlayerState” 欢迎任何建议。 这是指向 YT 播放器 iframe JS API 函数参考的链接:https://developers.google.com/youtube/iframe_api_reference#Functions 这是我的代码: // remap jQuery to $ jQuery(function ($) { /* trigger when page is ready */ $(document).ready(function (){ // Control for the video in Slidedeck // Find slidedeck $( "dl.slidedeck" ) // On mouseenter stop the Slidedeck autoplay .mouseenter( function()
  • Youtube iframe player JS API with jQuery - player object has no method 'getPlayerState'
    I've got following code, that is suppose to pause Slidedeck's autoscroll whenever there is a mouseover event. For mouseout event, the autoscroll should resume working unless the youtobe video in the Slidedeck is currently playing or buffering. I got it working fine if there wasn't the condition for the Youtube video. I believe there's a problem with the scope for the object player, but can't work it out, how to fix this problem. The error I get in console on mouseout is: Uncaught TypeError: Object #<T> has no method 'getPlayerState' Any advice welcome. Here's link to YT player iframe JS API
  • 将YouTube数据API添加到Android Studio(Add YouTube Data API to Android Studio)
    问题 因此,我目前在闲暇时间玩弄android编程,并且我将android studio用作我的选择。 我目前正在尝试使用youtube api制作一个非常简单的应用。 我的问题是我无法弄清楚如何将api真正放入我的应用程序中。 我已经使用file> project结构将东西添加到我的应用程序中,但是它本身无法正常工作。 它不再对语法错误对我大吼大叫,但在编译时却出现了错误。 我对此进行了一些研究,发现我需要添加一些内容到build.gradle或settings.gradle(或两者)中,但是我还没有找到确切的答案。 到目前为止,我尝试过的所有方法都没有起作用。 所以,如果有人可以向我解释我该怎么做,或者将我链接到一个可以解释我该怎么做的地方,那将是很好的 - 编辑 - 我现在很困惑。 我开始了一个新项目。 我添加了库,它仍然可以编译。 然后,我添加了导入,并引发了错误。 然后我将它们添加到build.gradle中,它能够完美地编译 compile fileTree(dir: 'libs/youtube', include: '*.jar') compile fileTree(dir: 'libs/youtube/libs', include: '*.jar') 但是当我添加需要库的代码时 /** Global instance of the HTTP transport. *
  • YouTube iframe API未触发onYouTubeIframeAPIReady(Youtube iframe api not triggering onYouTubeIframeAPIReady)
    问题 我已经和youtube iframe api斗争了很长时间。 不知何故,并不总是触发onYouTubeIframeAPIReady上的方法。 从症状看来,这是一个加载问题。 检查器中未显示任何错误。 这是我的代码: 的HTML <div id="player"></div> <script> videoId = 'someVideoId'; var tag = document.createElement('script'); tag.src = "//www.youtube.com/iframe_api"; var firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); </script> JS (在页面结尾处调用。我尝试将代码放在上述脚本之后,并且结果相同。) var isReady = false , player , poster , video; $(function () { $('.js-play').click(function (e) { e.preventDefault(); interval = setInterval(videoLoaded, 100); }); })
  • Youtube Javascript API-禁用相关视频(Youtube Javascript API - disable related videos)
    问题 是的,这似乎没有很好地记录在文档中,或者我在文档中看不到它。 我基本上不希望使用JavaScript API的相关视频( ?rel=0 )。 $players[$vidIdPlaceholderRef] = new YT.Player('player_' + $vidIdPlaceholderRef, { height: '550', width: '840', videoId: $vidId }); 是我所拥有的。 我也尝试过: $players[$vidIdPlaceholderRef] = new YT.Player('player_' + $vidIdPlaceholderRef, { height: '550', width: '840', videoId: $vidId + '?rel=0', rel : 0 }); 没有运气。 是否有人知道可以添加的选项( rel : 0 ,没有运气) 回答1 “ rel”是播放器参数,如下所示: https://developers.google.com/youtube/player_parameters#rel 要将播放器参数添加到iframe播放器,您需要指定第二个构造函数参数的playerVars属性(在编写本文时以及在IFrame API文档页面上都对此进行了说明) 例如 new YT.Player('playerid
  • YouTube Player API:如何在不播放的情况下获得已加载/提示的视频的持续时间?(YouTube Player API: How to get duration of a loaded/cued video without playing it?)
    问题 我无法通过YouTube Player API的getDuration()方法获得正确的视频时长/长度(以秒为单位),以已加载/提示的视频为准; 但是,一旦视频开始播放,相同的方法将返回有效值! 想知道YouTube如何显示已加载/提示的视频的有效时长。 当我用15秒的视频剪辑加载此HTML页面时,得到以下调试输出: 状态= 5持续时间= -0.000025 当我点击“播放”按钮时,我得到以下调试输出: 状态= 3持续时间= 15 将不胜感激的解决方案或解决方法。 加载,立即播放和暂停播放器不是我最喜欢的方法。 <html> <head> <script type="text/javascript"> var videoId; videoId = 'http://www.youtube.com/v/4TSJhIZmL0A'; // bbc // videoId = 'http://www.youtube.com/v/ezwyHNs_W_A'; // physics function $(id) { return document.getElementById(id); } </script> <script src="http://www.google.com/jsapi"></script> <script> google.load("swfobject", "2.1")
  • youtube API playVideo、pauseVideo 和 stopVideo 不起作用(youtube API playVideo, pauseVideo and stopVideo not working)
    问题 我正在尝试使用 YouTube API 来控制幻灯片中的一组播放器。 我希望能够根据幻灯片所在的帧停止和播放视频。 所以我根据帧的 id 将玩家推入一个数组。 当名气发生变化时,我会停止当前的名声并开始新的名声。 但是,即使在最基本的情况下,我也会收到此错误: Uncaught TypeError: Object #<S> has no method 'playVideo' 这是简单测试的代码 <!-- WIDGET YOUTUBE VIDEO --> <div class="widget_youtube_video" id="wyv_1-5"> <iframe id="ytplayer_1-5" width="560" height="315" src="//www.youtube.com/embed/CxW8TLtUMfM?autoplay=0&enablejsapi=1&origin=http://mmgi.localhost/" frameborder="0" allowfullscreen></iframe> <script type="text/javascript"> var tag = document.createElement('script'); tag.src = "//www.youtube.com/iframe_api"; var
  • Error: YouTubeService has leaked IntentReceiver … Are you missing a call to unregisterReceiver()?
    I uses YoutubeServie API to play youtube video in my Android application. However when I exit my activity, I found the below crash log showing, even my App still works. 02-28 15:54:02.081 20374-20374/? E/ActivityThread: Service com.google.android.youtube.api.service.YouTubeService has leaked IntentReceiver com.google.android.libraries.youtube.player.audiofocus.HeadsetPlugReceiver@a843e7c that was originally registered here. Are you missing a call to unregisterReceiver()? android.app.IntentReceiverLeaked: Service com.google.android.youtube.api.service.YouTubeService has leaked IntentReceiver
  • Android:YouTube播放器已发布(Android : youtube player has been released)
    问题 我收到此错误Fatal Exception: java.lang.IllegalStateException This YouTubePlayer has been released ,但未明确调用release()是发生崩溃的代码段: if(youtubePlayer != null){ time = youtubePlayer.getCurrentTimeMillis();//exception may occur } 是否可以检查youtubePlayer已released ? 有回叫吗? 谢谢。 回答1 Youtube SDK中的大多数代码都被混淆了,这使得调试真的很困难。 而且,没有任何直接方法可以检查YoutubePlayer是否已发布这一事实也无济于事。 话虽这么说,我认为将YoutubePlayer设置为null(在onStop()中)似乎对我来说是一种hack,而不是一种适当的解决方案。 您应该在onDestroy()中释放YoutubePlayer,并且不要在任何地方手动将其分配为null。 检查YoutubePlayer是否已释放的一种简单方法是将您的调用(例如youtubePlayer.loadVideo(),cueVideo(),getCurrentTimeMillis()等)放在try
  • AngularJS Youtube player embed very big playlist
    I'm currently building an AngularJS app (I know it's kinda outdated but I'm confident with it so..). My app need to embed a youtube player that contain a very big playlist (about 1500 items) but I can't code it so that it can embed more than 200 item actually. I search all over the net and for month to fix that issue but none of what I read seems to work, I litteraly tried everthing I could think of. Oh by the way I use angular-youtube-embed to make youtube api work with AngularJS. Here is my code in the controller on how I build up the player const home = this; var inter = false; var