YT.Player 不使用 playVideo() 返回实例

问题描述 投票:0回答:3

当我创建

YT.Player(HTMLIFrameElement, { options })
的实例时,我得到一个具有以下内容的对象:

  • 摧毁
  • 设置大小
  • 获取Iframe
  • 添加事件监听器
  • 获取视频嵌入代码
  • 获取选项
  • 获取选项

但不是

文档
中描述的
playVideo
pauseVideo等。

我在这里有一个演示:http://siesta-annotations.surge.sh/Siesta_webviewer_test/?page=3

我正在通过

trait.playable.youtube.js
中的 DOM 创建 iframe,并将 iframe 添加到
documentFragment
,最终将添加到 div 中:

const element = document.createElement('iframe')
element.src = `https://www.youtube.com/embed/${id}?rel=0;&autoplay=${this.options.autostart ? 1 : 0};&enablejsapi=1;&origin=${location.hostname};`
element.style = this.inlineStyle

然后我创建一个 YT.Player 实例:

// nasty initialization because we're outside webpack and this is a demo
if (global.YT.loaded) {
  this.player = new global.YT.Player(element, {
    events: {
      'onStateChange': this.stateHandler,
      'onReady': onPlayerReady
    }
  })
} else {
  const oldHandler = global.onYouTubeIframeAPIReady
  global.onYouTubeIframeAPIReady = () => {
    if (oldHandler) oldHandler()

    this.player = new global.YT.Player(element, {
      events: {
        'onStateChange': this.stateHandler,
        'onReady': onPlayerReady
      }
    })
  }
}

YT.Player 的实例看起来像这样:

看起来缩小过程出错了。我做错了什么 - 我应该如何为我的用例初始化 YT.Player?

javascript youtube-api youtube-iframe-api
3个回答
0
投票

这是我的第二篇文章,希望能解决您的问题。

我不是 100% 确定你的代码是如何工作的,但我怀疑......

看起来像是

YT.Player
对象的双重实例化,这会导致
YT.Player
对象不稳定。

我自己也挣扎了很久(ps:我是业余程序员😅)

作为示例,以下代码片段是从 Youtube Iframe API 网站修改的,以及第二个实例化如何破坏播放器对象的示例 尝试一下! JS 斌:

<!DOCTYPE html>
<html>

<body>
    <!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
    <div id="player"></div>
    </br>
    <button onclick="instantiateOneMore()">
        Call
        <pre>new YT.Player('player')</pre>
    </button>
    <button onclick="pauseVideo()">
      pauseVideo();
    </button>
    <script>
        // 2. This code loads the IFrame Player API code asynchronously.
        var tag = document.createElement('script');

        tag.src = "https://www.youtube.com/iframe_api";
        var firstScriptTag = document.getElementsByTagName('script')[0];
        firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

        // 3. This function creates an <iframe> (and YouTube player)
        //    after the API code downloads.
        var player;

        function onYouTubeIframeAPIReady() {
            player = new YT.Player('player', {
                height: '390',
                width: '640',
                videoId: 'M7lc1UVf-VE',
                events: {
                    'onReady': onPlayerReady,
                    'onStateChange': onPlayerStateChange
                }
            });

        }


        let callTime = 0;
        // 4. The API will call this function when the video player is ready.
        function onPlayerReady(event) {
            event.target.playVideo();
            callTime ++;
            console.log(callTime);
            //document.querySelector('#dd').innerHTML = player.pauseVideo;
        }
      function pauseVideo(){
        player.pauseVideo();
      }
        instantiateOneMore = () => {
            player = new YT.Player('player', {
                height: '390',
                width: '640',
                videoId: 'M7lc1UVf-VE',
                events: {
                    'onReady': onPlayerReady,
                    'onStateChange': onPlayerStateChange
                }
            });
            //document.querySelector('#dd').innerHTML = player.pauseVideo;
        }

        // 5. The API calls this function when the player's state changes.
        //    The function indicates that when playing a video (state=1),
        //    the player should play for six seconds and then stop.
        var done = false;

        function onPlayerStateChange(event) {
            if (event.data == YT.PlayerState.PLAYING && !done) {
                /* setTimeout(stopVideo, 6000) */
                ;
                done = true;
            }
        }
        /* 
              function stopVideo() {
                player.stopVideo();
              } */
    </script>
</body>

</html>

此外,第二个

onPlayerReady()
甚至不会被调用。因此,如果您打算放置一些计数器来查看
new YT.Player(...)
被调用了多少次,您会怀疑它只被调用了一次。这使得效果幽灵远离调试。


0
投票

奇怪的是,直到在构造函数播放器选项对象中调用

'onReady'
之前,您无法访问 YTPlayer API。 https://developers.google.com/youtube/iframe_api_reference#Loading_a_Video_Player

function onYouTubeIframeAPIReady() {
  new YT.Player('player', {
    height: '390',
    width: '640',
    videoId: 'M7lc1UVf-VE',
    events: {
      'onReady': function (event) {
        onPlayerReady(event.target)
      },
      'onStateChange': onPlayerStateChange
    }
  });
}

function onPlayerReady(player) {
  player.playVideo();
}

这当然仅适用于一名玩家,因此如果您想处理多名玩家,则需要推出自己的 YouTube 播放器管理器。 (我知道 API 很疯狂)

如果您有带有 YouTube 视频的 iframe,则可以采用以下快速解决方案(未经测试):

const YTManager = {
  videos: [],
  youtubeApiReady = false,
  initialize () {
    const matchId = /[^/]+$/

    this.youtubeApiReady = true
    
    document.querySelectorAll('iframe[src*="youtube"]')
      .forEach(iframe => this.videos.push({
         dom: iframe,
         player: null,
         videoId: iframe.src.exec(matchId) || iframe.src.exec(matchId)[0]
       }))
  },
  createPlayers () {
    if (this.youtubeApiReady === false) return

    this.videos.forEach(v => {
      new YT.Player(v.dom.id, {
        videoId: v.videoId,
        events: {
          'onReady': function (event) {
            v.player = event.target
          }
        }
      })
    })
  },
  find (id) {
    return this.videos.find(v => v.id === id)
  },
  play (id) {
    const video = this.find(id)
    if (this.youtubeApiReady && video && video.player) {
      video.playVideo()
    }
  },
  pause (id) {
    const video = this.find(id)
    if (this.youtubeApiReady && video && video.player) {
      video.pauseVideo()
    }
  },
}

window.onYouTubeIframeAPIReady = function onYouTubeIframeAPIReady() {
  // YouTube client side script has been loaded
  YTManager.youtubeApiReady = true
  YTManager.createPlayers()
}

document.addEventListener("DOMContentLoaded", function() {
  // all iframes has been parsed by the browser
  YTManager.initialize()
});

当然,如果没有 ID,您就无法调用

YTManager.play
YTManager.pause
,并等待 YouTube 脚本加载,然后视频初始化完成。总而言之,真是一团糟。我相信你能想出一个更好的经理。我在工作中编写了一个更好的程序,但也适用于完全不同的对象和要求,因此它不太适合通用的 YouTube 视频管理器。但上面的是我现在的玩家的要点。

我建议从一开始就使用 iframe - 如果您的脚本出现任何问题,视频仍然可以播放,只是您无法控制它们。

Iframed youtube 视频看起来像这样:

<iframe
  id="uniqueDOMElementID1"
  width="560"
  height="315"
  src="https://www.youtube.com/embed/bHQqvYy5KYo"
  frameborder="0"
  allow="autoplay; encrypted-media"
  allowfullscreen></iframe>

0
投票

这是一个很老的问题,但我今天偶然发现了这个问题并自己解决了,尽管花了我几个小时。

就我而言,罪魁祸首是错误的视频 ID。

假设正确的 ID 是

videoId:"M7lc1UVf-VE"
,但我最初输入的是
videoId:"M7lc1UVf-VE?si=5rdPpwWtXnTEFHd_
。不知何故,它部分起作用,电影实际上正在播放,但其他功能从未起作用。

所以,我建议检查一下视频id上是否有不必要的参数。

© www.soinside.com 2019 - 2024. All rights reserved.