2015-01-13 330 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; 
    }); 
};