【问题标题】:Get flash video state in Youtube site - Chrome extension在 Youtube 网站中获取 Flash 视频状态 - Chrome 扩展
【发布时间】:2015-06-02 10:44:09
【问题描述】:

使用 Chrome 扩展程序,将脚本注入 Youtube 网站本身,并使用 Youtube 播放器 API 监听播放器事件。

注入的脚本代码:
(您可以在 Youtube HTML5 视频页面上的控制台中运行它并查看它是否有效)

var theYTplayer = document.getElementById('movie_player');

theYTplayer.addEventListener('onStateChange', function(){
    console.log('--- player state has been changed');
});

在 HTML5 视频方面,一切都很好,但在 Flash 直播中却不行。
在 Flash 中,由于某种原因,所有 GET 函数都会返回错误,而 SET 函数则运行良好。
获取:getPlayerStateisMutedgetVolume
设置:playVideopauseVideomuteunMutesetVolume

这可能是一个错误,所以我在这里报告了它:issue #7043

例如,您可以在 this live streaming video 上对其进行测试。

如果我做错了什么,请告诉我应该怎么做。
如果这是一个错误,那么让我们考虑另一种方法来检测视频是否正在播放。
我比较了两个 DOM,当状态发生变化或其他任何事情时,没有添加任何类,文件最终匹配。
然后我看到,当视频播放时,Chrome 会在选项卡中添加新的额外图标扬声器,但这只是在有声音的情况下,如果视频静音,则图标不会出现,所以这不好。那么您是否有任何其他想法/解决方法来检测视频是否正在播放或修复我的代码?

【问题讨论】:

  • 确保这不是您的问题:stackoverflow.com/questions/9515704/…
  • @Xan:谢谢,但这不是我的问题,我确实将脚本注入页面并在加载 DOM 后执行此操作,然后尝试在 HTML5 中的控制台中使用它视频和 Youtube 上的 Flash 视频,你会看到我面临的问题。
  • 我也很怀疑,我只是想澄清一下你确实正确地注入了脚本。

标签: javascript google-chrome-extension youtube-api


【解决方案1】:

我在我的代码中发现了问题,以及如何使用 on state change listener。

在 Javascript 中,当您使用 addEventListener 时,您可以设置不带引号的回调函数名称,如下所示:

player.addEventListener('onStateChange', playerStateChange);

但是!
当涉及到 Youtube 播放器 API 时,您必须将函数的名称设置为 字符串,这意味着带引号:

player.addEventListener('onStateChange', 'playerStateChange');

所以...是的,这就是整个问题,虽然它适用于不带引号的 HTML5 播放器,但它不适用于 Flash 播放器。

来自文档:

添加或删除事件监听器

player.addEventListener(event:String, listener:String):Void

为指定事件添加监听函数。活动部分 下面标识了玩家可能触发的不同事件。这 listener 是一个字符串,它指定了将要执行的函数 当指定的事件触发时。

https://developers.google.com/youtube/iframe_api_reference#Adding_event_listener

您可以在文档中清楚地看到它的唯一位置是“订阅事件”部分下的 JS API。

订阅活动
通过向播放器添加事件监听器 参考。例如,当玩家的状态得到通知 更改,为 onStateChange 添加事件侦听器并包含 回调函数。

function onYouTubePlayerReady(playerId) {
    ytplayer = document.getElementById("myytplayer");  
    ytplayer.addEventListener("onStateChange", "onytplayerStateChange");
}

function onytplayerStateChange(newState) {
    alert("Player's new state: " + newState);
}

https://developers.google.com/youtube/js_api_reference#SubscribingEvents

现在这样做之后,您可以在播放器准备好后将监听器添加到播放器,它会正常工作。
要知道播放器何时准备就绪,您需要在manifest 文件中使用run_at 将脚本注入document_start。 然后在您的代码中使用函数名称onYouTubePlayerReady,如下所示:

var theYTplayer;

function onYouTubePlayerReady(){
    theYTplayer = document.getElementById('movie_player');
    theYTplayer.addEventListener('onStateChange', 'playerStateChange');
}

不要使用 iframe API 函数名称 onYouTubeIframeAPIReady,因为它不起作用,只使用 JS API 函数名称 onYouTubePlayerReady

虽然我之前发布的方法有效,但这是正确的。

【讨论】:

    【解决方案2】:

    编辑!
    这是一种可行的解决方法,但它不是正确的答案,您正在寻找的答案是:https://stackoverflow.com/a/29346099/962643


    一种解决方法,
    Flash 播放器完成加载并使其元素 (#movie_player) 成为对象需要一些时间。
    使用setInterval 来检查元素是否为null,并且只有当它不为空时才意味着我们可以将它与GET 函数一起使用,在这种情况下它将使用getPlayerState 函数,使用它在另一个setInterval 中检查状态会给你一个假的“onStateChange”监听器,因为不幸的是,即使播放器已完全加载,添加事件监听器仍然不起作用,但 GET 函数确实有效,所以我们将使用他们代替。

    在我的情况下,我只需要知道在我的扩展程序中打开 pageAction 弹出窗口时的状态,因此只需在弹出窗口加载时调用 getPlayerState 函数对我来说就足够了。

    在注入的脚本中:

    var theYTplayer = document.getElementById('movie_player'),
        theYTplayerState;
    
    var checkYTplayerReady = setInterval(function(){
        theYTplayer = document.getElementById('movie_player');
    
        if(theYTplayer != null){
            clearInterval(checkYTplayerReady);
    
            setTimeout(function(){
                checkYTplayerState();
            },2000);
    
            theYTplayer.addEventListener('onStateChange', checkYTplayerState);
        }
    }, 100);
    
    function checkYTplayerState(event){ 
        theYTplayerState = event;
    
        if(typeof event === 'undefined'){
            theYTplayerState = theYTplayer.getPlayerState();
        }
    
        if(theYTplayerState == 1){
            theYTplayerState = 'playing';
        }else{
            theYTplayerState = 'not playing (unstarted/paused/buffering/ended/video cued)';
        }
    
        return theYTplayerState;
    }
    

    从那里您可以使用消息将其发送到内容脚本,然后发送到弹出窗口或将其用于您需要的任何内容。

    【讨论】:

    • *咳嗽* MutationObserver *咳嗽*
    • @Xan: 哈哈,是的,使用MutationObserver 很棒(你也是,评论这么快!谢谢)我在这个扩展中使用它来做其他事情,但是你如何使用它用于检查元素的类型,如果它是一个对象?或者您是想以其他方式使用它吗?
    • 等等。我很惊讶你的代码完全有效。如果不尝试再次分配theYTplayer,怎么会变成非null
    • 非常感谢!我忘了在这里添加它,编辑了我的代码。现在MutationObserver魔术怎么样了?如果和
    • 你只需要观察所有的插入,直到元素出现在一个内。使用 mutation-summary library 应该非常简单(它可以节省您遍历插入的子树的工作)
    猜你喜欢
    • 2021-04-02
    • 2013-10-21
    • 2016-09-05
    • 2014-08-24
    • 1970-01-01
    • 1970-01-01
    • 2017-03-11
    • 2013-02-08
    • 2019-09-16
    相关资源
    最近更新 更多