使用Tampermonkey / javascript控制Netflix(HTML5)播放

时间:2015-01-13 17:27:32

标签: javascript html5-video greasemonkey tampermonkey netflix

在Netflix网站上观看netflix视频时,我的目标是让用户脚本以编程方式调用播放控件。具体来说,视频的音量,电平,播放/暂停状态和时间位置。

我已经能够操纵html5视频元素本身,但直接控制它并不能向用户提供所需的netflix控制栏反馈。 (即视频已暂停,但控制栏仍显示为正在播放)。

到目前为止,我的方法是尝试找到代表"按钮的元素。您在使用普通控件时单击,并通过用户脚本触发其单击事件。但我似乎无法隔离适当的元素。另外netflix正在使用javascript压缩器/混淆器,这增加了找到代表控制栏上按钮的正确元素的难度。

在这样的网站上,如何识别接收元素点击事件的元素,然后创建用户脚本以通过tampermonkey和/或greasemonkey调用它?

在下面的示例代码中,我在视图中添加了一个按钮以进行测试。

// ==UserScript==
// @name       Jump a minute ahead in netflix
// @version    0.1
// @description  A Test by trying to jump a minute or so ahead into a netflix movie
// @match        *://www.netflix.com/*
// @grant       GM_addStyle
// @require http://code.jquery.com/jquery-latest.js
// ==/UserScript==

var zNode       = document.createElement ('div');
zNode.innerHTML = '<button id="myButton" type="button">Try It</button>';
zNode.setAttribute ('id', 'myContainer');
document.body.appendChild (zNode);

//--- Activate the newly added button.
document.getElementById ("myButton").addEventListener (
    "click", ButtonClickAction, false
);

function ButtonClickAction (zEvent) {
    /*--- For our dummy action, we'll just add a line of text to the top of the screen.*/
    var zNode       = document.createElement ('p');
    var video = $("video:first-of-type");
    var playerSlider = document.getElementsByClassName("player-slider")[0];

    console.log(netflix);
    console.log(playerSlider);
    console.log(netflix.player);
    console.log(netflix.cadmium);
    console.log(netflix.cadmium.ui);
    console.log(netflix.cadmium.ui.playback);

    //video.get(0).pause();
    //video.get(0).currentTime = 2000.0;
    console.log(video.get(0).currentTime);
    console.log(netflix.cadmium.ui.volume);
    zNode.innerHTML = 'The button was clicked.';
    document.getElementById ("myContainer").appendChild (zNode);
}

//--- Style our newly added elements using CSS.
GM_addStyle ( multilineStr ( function () {/*!
    #myContainer {
        position:               absolute;
        top:                    0;
        left:                   0;
        font-size:              20px;
        background:             orange;
        border:                 3px outset black;
        margin:                 5px;
        opacity:                0.9;
        z-index:                222;
        padding:                5px 20px;
    }
    #myButton {
        cursor:                 pointer;
    }
    #myContainer p {
        color:                  red;
        background:             white;
    }
*/} ) );

function multilineStr (dummyFunc) {
    var str = dummyFunc.toString ();
    str     = str.replace (/^[^\/]+\/\*!?/, '') // Strip function () { /*!
    .replace (/\s*\*\/\s*\}\s*$/, '')   // Strip */ }
    .replace (/\/\/.+$/gm, '') // Double-slash comments wreck CSS. Strip them.
    ;
    return str;
}

console.log语句显示了我迄今为止发现的一些内容。但我还没弄明白如何调用它们的功能,或者它们中哪些可能有我想要的东西(我认为很大程度上是由于javascript压缩器让我难以遵循代码)。

3 个答案:

答案 0 :(得分:5)

我认为这是我对这个问题过于刻板的一个例子。一旦我退后一步,我意识到我一直在寻找正确的方向,但没有正确地触发点击事件。

因此,例如,要获得&#34;按钮&#34;控制播放和暂停,您可以使用:document.getElementsByClassName("player-control-button player-play-pause")[0]。然后在tampermonkey中以编程方式单击它,您只需使用以下命令调用click事件:

document.getElementsByClassName("player-control-button player-play-pause")[0].click();

栏中的音量和其他控件类似。播放位置看起来有点棘手,但是一旦我搞清楚,我会再做一些挖掘并添加评论。

答案 1 :(得分:1)

嗯,好消息是你可以通过检测HTML5 VIDEO标签来控制播放

离&#39; S:

https://gist.github.com/rdp/93c761b3524529e591e5286073545362 find_html5_video.js

https://github.com/igrigorik/videospeed

然后调用方法,因为任何普通的HTMLMediaElement对象(静音,暂停等)都可以正常工作。

 video_element.paused = true // pause playback
 video_element.currentTime // get current timestamp

如果您对大多数网站(亚马逊即时视频,youtube)使用此技巧,您可以使用video_element.currentTime = 3进行搜索,它只是有效。

然而,如果你想使用netflix,你会得到&#34;哎呀,出错了......意外错误出现意外错误。请刷新页面,然后再试一次。错误代码:M7375&#34;

我还没有找到解决方法(尽管如果你的搜索只是&#34;快进&#34;有点,你可以减小视频大小,将播放速率设置为超高,当它到达我想要的所需位置时,将其恢复正常。

因此我们需要找到一种不同的方式来发送seek命令。显然,有一个netflix.cadmium.objects.videoPlayer()netflix.player javascript对象可以使用搜索方法,但现在看来它们似乎不存在。

回到原来的问题,似乎可以模仿&#34;点击&#34;在控制位置的滑块上,因此在您尝试时发送搜索消息。

Netflix Party(Chrome扩展程序,以及chrome扩展程序“http://showgoers.tv/”做了类似的事情,解释here

一个尖锐的部分似乎是

var showControls = function() {
  uiEventsHappening += 1;
  var scrubber = $('#scrubber-component');
  var eventOptions = {
    'bubbles': true,
    'button': 0,
    'currentTarget': scrubber[0]
  };
  scrubber[0].dispatchEvent(new MouseEvent('mousemove', eventOptions));
  return delay(10)().then(function() {
    uiEventsHappening -= 1;
  });
};

var seek = function(milliseconds) {
  uiEventsHappening += 1;
  var eventOptions, scrubber;
  return showControls().then(function() {
    // compute the parameters for the mouse events
    scrubber = $('#scrubber-component');
    var factor = milliseconds / getDuration();
    var mouseX = scrubber.offset().left + Math.round(scrubber.width() * factor); // relative to the document
    var mouseY = scrubber.offset().top + scrubber.height() / 2;                  // relative to the document
    eventOptions = {
      'bubbles': true,
      'button': 0,
      'screenX': mouseX - $(window).scrollLeft(),
      'screenY': mouseY - $(window).scrollTop(),
      'clientX': mouseX - $(window).scrollLeft(),
      'clientY': mouseY - $(window).scrollTop(),
      'offsetX': mouseX - scrubber.offset().left,
      'offsetY': mouseY - scrubber.offset().top,
      'pageX': mouseX,
      'pageY': mouseY,
      'currentTarget': scrubber[0]
    };

    // make the "trickplay preview" show up
    scrubber[0].dispatchEvent(new MouseEvent('mouseover', eventOptions));
  }).then(delay(10)).then(function() {
    // simulate a click on the scrubber
    scrubber[0].dispatchEvent(new MouseEvent('mousedown', eventOptions));
    scrubber[0].dispatchEvent(new MouseEvent('mouseup', eventOptions));
    scrubber[0].dispatchEvent(new MouseEvent('mouseout', eventOptions));
  }).then(delay(1)).then(hideControls).then(function() {
    uiEventsHappening -= 1;
  });
};

答案 2 :(得分:1)

我知道这是一个较旧的问题,但我想发布此答案以供未来用户使用。

您现在可以通过执行以下 Javascript(最初由 Dmitry Paloskinthis topic 上贡献)访问其播放器 API 来控制 Netflix 的播放:

const videoPlayer = netflix.appContext.state.playerApp.getAPI().videoPlayer;

// Getting player id
const playerSessionId = videoPlayer.getAllPlayerSessionIds()[0];

const player = videoPlayer.getVideoPlayerBySessionId(playerSessionId);

然后您可以使用 API 在 Netflix 播放器上执行各种命令,例如搜索(使用 player.seek() 和括号中的毫秒数)、播放或暂停视频(使用 {{1 }} 或 player.play()),或控制音量(使用 player.pause() 和括号中的值,1 为 100%,0 为 0%)。

此方法避免了 Netflix 在尝试更改视频元素的 player.setVolume() 属性时崩溃的问题,如上面来自 rogerdpack 的回复所述。