2015-01-13 331 views
4

在Netflix网站上观看Netflix视频时,我的目标是让用户脚本以编程方式调用播放控件。具体来说,视频的音量,级别,播放/暂停状态和时间位置。使用Tampermonkey控制Netflix(HTML5)播放/ javascript

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

到目前为止,我的方法是尝试找到代表使用常规控件时单击的“按钮”的元素,并通过userscript触发其点击事件。但我似乎无法孤立适当的元素。此外,netflix正在使用JavaScript压缩器/混淆器,这增加了查找代表控制栏上按钮的适当元素的难度。

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

在下面的示例代码中,为了测试目的,我在视图上添加了一个按钮。

// ==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压缩器使我难以遵循代码)。

+0

的Silverlight播放器控制,请参阅http://stackoverflow.com/q/6086205/32453 – rogerdpack

+0

截至9月2017年。这是唯一可行的答案。 https://stackoverflow.com/questions/42105028/netflix-video-player-in-chrome-how-to-seek/46816934#46816934 –

回答

5

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

因此,例如,要获得控制播放和暂停的“按钮”,您可以使用:document.getElementsByClassName("player-control-button player-play-pause")[0]。然后点击它编程在tampermonkey,您只需使用调用单击事件:

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

音量等控制在酒吧是相似的。回放的位置看起来有点棘手,但我会做一些更深入的挖掘,并在解决这个问题时给这个答案添加评论。

+2

我标记为答案,因为它确实解决了原来的问题。但是,我发现在netflix中操纵视频播放的更好方法是引用videoPlayer对象本身。例如: 'var vp = netflix.cadmium.objects.videoPlayer(); vp.seek(60500);' 您还可以使用此对象获取暂停,音量,获取位置和持续时间等功能。 –

+0

你有没有用这个建立任何东西? –

+1

@ChadMichael看起来'netflix.cadmium'对象最近被删除了,不幸的是[?] – rogerdpack

1

好了,好消息是,你可以在一定程度通过检测HTML5视频标签

前的控制播放:

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,就会得到“Whoop,出错了......意外错误出现意外错误,请重新加载页面并重试。错误代码:M7375“

我还没有想出一个解决方法呢(尽管如果您的搜索只是”快进“一点,您可以减小视频大小,将播放速率设置为超高,然后当它到达想要的位置时,将它恢复到正常状态)

因此,我们需要找到一种不同的方式来发送seek命令,显然有一个netflix.cadmium.objects.videoPlayer()netflix.player JavaScript对象可用于但是它们现在似乎不存在了

回到原来的问题,看起来似乎可以模仿控制位置的滑块上的“单击”从而发送寻求信息,就像你试图的那样。

Netflix Party(扩展名为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; 
    }); 
};