谷歌浏览器中的 Netflix 视频播放器 - 如何快进?

9
我一直无法弄清如何在Chrome中运行的Netflix视频播放器中进行视频搜索(自动转到视频中的某个点)。在Netflix播放器中可以读取currentTime属性,但不能设置,设置后立即触发错误“糟糕!出了些问题。”其他操作,如播放暂停都很好用。例如,您可以尝试以下操作:
  1. 登录Netflix(从Google Chrome)并进入电影 《世界末日》
  2. 电影加载完毕后,如果开始播放,请暂停它。
  3. 打开Chrome开发人员工具面板。 转到Console选项卡。
  4. 将以下片段粘贴到控制台中,然后按<ENTER>

var video = document.evaluate('//*[@id="5670317"]/video',document).iterateNext()

注意:id值是特定于《世界末日》的。 如果您选择不同的电影,则根据该电影URL中的ID更改ID即可。

  1. 输入以下内容,然后按<Enter>video.play()。观察视频恢复播放。

很简单,但如何使视频自动跳转到视频中的特定点?您可能需要参考this doc。显然,您可以通过从左向右拖动视频播放器滑块并释放它来手动查找。您可能希望发现当您这样做时调用哪种方法或事件,并模拟该过程。到目前为止,我还没有成功。

有什么想法吗?

5个回答

30

看起来Netflix更改了播放器API。这是我发现的:

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

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

const player = videoPlayer
  .getVideoPlayerBySessionId(playerSessionId)

现在您可以使用完整的播放器API。例如player.seekplayer.getCurrentTimeplayer.pause等...


2
这正是我一直在寻找的。cadmium对象不再通过netflix API提供。谢谢。 - Fethi Dilmi
2
Dimitry,你介意解释一下你的演绎过程是如何找出答案的吗?几个月前我放弃了,因为我无法破解它。你是怎么去思考找出这个问题的答案的?有用到哪些工具、过程和思路呢?谢谢! - Stephen Cagle
4
没有超自然的力量:) 只是使用Chrome开发工具及其自动完成功能。首先我查找了全局变量(因此我找到了window.netflix)。然后,我仔细阅读了所有属性、方法名称等,并花了很多时间进行实验 :) - DimaOverflow
1
啊,太糟糕了,我本来希望有点魔法的。:) 是啊,你会笑的,但我实际上尝试过摇动鼠标,找到滑块,计算寻找位置,然后生成鼠标事件。那真是太可怕了。;) - Stephen Cagle
你也会笑的,因为我第一次也做了同样的动作,哈哈 :) - DimaOverflow
1
这太棒了!像魔法一样运行! - katspaugh

7

如果您希望在Netflix的控制台日志中使用它,那么它只能在那里工作。如果您想要在Chrome扩展中使用它,则需要将此代码注入到脚本标签中以使其起作用。

const videoPlayer = netflix.appContext.state.playerApp.getAPI().videoPlayer;
const player = videoPlayer.getVideoPlayerBySessionId(videoPlayer.getAllPlayerSessionIds()[0]);

player.seek(1091243) //seek to roughly 18mins

player.getCurrentTime() // will give you the current video time.

enter image description here


3
在Dmitry的回复基础上,向前跳10秒钟: player.seek(player.getCurrentTime() - 10000)

3

最终找到了一个简单的解决方案:

netflix.cadmium.UiEvents.events.resize[1].scope.events.dragend[1].handler(null, {value: 999, pointerEventData: {playing: false}});

您可以通过以下方式进行设置:

  • 使用value属性设置位置
  • 使用pointerEventData.playing属性设置播放状态

这不是完整的解决方案,但可能会有用。

以前版本的Netflix播放器使用全局对象window.netflix.cadmium.objects.videoPlayer。在最新版本中,它为空,但您可以在事件侦听器中访问此对象:

  1. 打开Chrome开发者工具
  2. 选择“body”元素
  3. 选择“事件侦听器”
  4. 打开“框架侦听器”
  5. 选择“keydown”事件,“body”-handler p(e),“[[Scopes]]”,1 [[Closure]]
  6. 您可以使用上下文菜单 - “存储为全局变量”来保存此对象引用
  7. 然后在新的全局变量中,您可以访问temp1.cadmium.objects.videoPlayer

    temp1.cadmium.objects.videoPlayer().getDuration() temp1.cadmium.objects.videoPlayer().seek(2283839); temp1.cadmium.objects.videoPlayer().seek(4283839);

[! [输入图像说明][1]][1]

我不确定是否可以完全自动化。您可以通过以下方式访问这些侦听器:

getEventListeners(document.getElementsByTagName("body")[0]).keydown[0].listener

但我不知道如何访问作用域变量。

看起来很有前途,但请提供所有这些的代码示例。谢谢! - HerrimanCoder
1
kb0,在Chrome Dev Tools(控制台)中,这个方法非常有效,但是当我在Chrome扩展程序中执行相同的代码时,总是会出现相同的错误:netflix is not defined。 我已经使用断点进入了代码,并确认我正在执行与控制台中相同的代码行,与您上面粘贴的代码行相同。 为什么它在控制台中能用,但在Chrome扩展程序中却不能用呢? (在我的扩展程序中,我已经与其他DOM元素进行了交互。例如,这个方法可以正常工作,并获取到视频对象:document.evaluate('//*[@id="60003082"]/video',document).iterateNext()。) - HerrimanCoder
2
@SweatCoder,由于内容脚本(https://developer.chrome.com/extensions/content_scripts)的限制,它在Chrome扩展中无法工作:“但是,内容脚本有一些限制。它们不能使用由网页或其他内容脚本定义的变量或函数...”。您可以尝试在https://dev59.com/_2ct5IYBdhLWcg3wCZIT中使用解决方法。 - kb0
你能指点我一个方向,让我能够在扩展中完成这个吗?既然我可以获取DOM元素的句柄,似乎应该有其他方法来完成这个任务。 - HerrimanCoder
将JS作为脚本对象注入。var elt = document.createElement("script"); elt.innerHTML = "netflix.cadmium.UiEvents..." document.head.appendChild(elt); - kb0
4
截至2017年9月,这个方法已经无效了:Netflix对象中不再提及镉。 - Fethi Dilmi

0

对于那些试图从他们的扩展程序控制Netflix视频播放器的人:我已经找到了一个简单的解决方案。

当前时间和暂停状态:可以轻松地使用以下方法获得

document.querySelector('video').currentTime
document.querySelector('video').paused

(简单地访问此数据不会重定向到错误页面)

恢复/暂停:这里我们有两个选项:

  1. 执行以下代码:

     document.querySelector('video').click();
    

这会暂停/取消暂停视频。您可以使用上面描述的暂停状态获取来确保您不会取消暂停已经暂停的视频。

  • 添加脚本,该脚本本身通过点击事件监听器向文档添加元素:

         const actualCode = `
         const pauseElem = document.createElement('div');
         pauseElem.id = 'my_pause_elem';
         pauseElem.addEventListener('click', () => {
             const videoPlayer = window.netflix.appContext.state.playerApp.getAPI().videoPlayer;
             const player = videoPlayer.getVideoPlayerBySessionId(videoPlayer.getAllPlayerSessionIds()[0]);
             player.pause();
         });
    
         const resumeElem = document.createElement('div');
         resumeElem.id = 'my_resume_elem';
         resumeElem.addEventListener('click', () => {
             const videoPlayer = window.netflix.appContext.state.playerApp.getAPI().videoPlayer;
             const player = videoPlayer.getVideoPlayerBySessionId(videoPlayer.getAllPlayerSessionIds()[0]);
             player.play();
         });
    
    
         document.body.appendChild(pauseElem);
         document.body.appendChild(resumeElem);
         `;
    
         const script = document.createElement('script');
         script.textContent = actualCode;
         (document.head||document.documentElement).appendChild(script);
         script.remove();    
    
  • 现在你需要做的就是:
    document.getElementById('my_pause_elem').click();
    document.getElementById('my_resume_elem').click();
    

    暂停/恢复。

    搜索:这与上面的解决方案相同:添加一个带有事件侦听器的元素,该侦听器使用 Spotify API 进行搜索。特别之处在于我们需要传递一个时间戳。这可以通过将属性值设置为我们的元素来完成:

        const actualCode = `
        const seekElem = document.createElement('div');
        seekElem.id = "my_seek_elem";
        seekElem.addEventListener('click', () => {
            const newTime = Number(document.getElementById('my_seek_elem').getAttribute('timestamp')) * 1000;
            const videoPlayer = window.netflix.appContext.state.playerApp.getAPI().videoPlayer;
            const player = videoPlayer.getVideoPlayerBySessionId(videoPlayer.getAllPlayerSessionIds()[0]);
            player.seek(newTime);
        });
        (document.body).appendChild(seekElem);
        `;
    
     const script = document.createElement('script');
     script.textContent = actualCode;
     (document.head||document.documentElement).appendChild(script);
     script.remove();   
    

    现在我们所需要做的就是在设置时间戳后触发此事件:
    document.getElementById('my_seek_elem').setAttribute('timestamp', '' + timestamp);
    document.getElementById('my_seek_elem').click();
    

    就这样!


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接