YouTube iframe API:如何控制 HTML 中已有的 iframe 播放器?
我希望能够控制基于 iframe 的 YouTube 播放器。该播放器已经在 HTML 中,但我想通过 JavaScript API 控制它们。
我一直在阅读iframe API 文档,其中解释了如何向页面添加新视频使用 API,然后使用 YouTube 播放器函数控制它:
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('container', {
height: '390',
width: '640',
videoId: 'u1zgFlCw8Aw',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
该代码创建一个新的播放器对象并将其分配给“player”,然后将其插入 #container div 内。然后我可以对“播放器”进行操作并对其调用 playVideo()
、pauseVideo()
等。
但是我希望能够在页面上已有的 iframe 播放器上进行操作。
我可以使用旧的嵌入方法轻松地完成此操作,例如:
player = getElementById('whateverID');
player.playVideo();
但这不适用于新的嵌入方法iframe。如何分配页面上已有的 iframe 对象,然后在其上使用 API 函数?
I want to be able to control iframe based YouTube players. This players will be already in the HTML, but I want to control them via the JavaScript API.
I've been reading the documentation for the iframe API which explain how to add a new video to the page with the API, and then control it with the YouTube player functions:
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('container', {
height: '390',
width: '640',
videoId: 'u1zgFlCw8Aw',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
That code creates a new player object and assigns it to 'player', then inserts it inside the #container div. Then I can operate on 'player' and call playVideo()
, pauseVideo()
, etc. on it.
But I want to be able to operate on iframe players which are already on the page.
I could do this very easily with the old embed method, with something like:
player = getElementById('whateverID');
player.playVideo();
But this doesn't work with the new iframes. How can I assign a iframe object already on the page and then use the API functions on it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
Fiddle 链接:源代码 - 预览 - 小版本
更新:这个小函数只会在一个方向上执行代码。如果您需要全面支持(例如事件监听器/获取器),请查看 在 jQuery 中监听 Youtube 事件
经过深入的代码分析,我创建了一个函数:
function callPlayer
请求函数调用在任何带框的 YouTube 视频。请参阅 YouTube Api 参考,获取可能的函数调用的完整列表。阅读源代码中的注释以获得解释。2012 年 5 月 17 日,代码大小增加了一倍,以照顾玩家的就绪状态。如果您需要一个不处理玩家就绪状态的紧凑函数,请参阅 http://jsfiddle.net/8R5y6/< /a>.
用法:
可能的问题(和答案):
问:它不起作用!
A:“不起作用”不是一个明确的描述。您收到任何错误消息吗?请出示相关代码。
问:
playVideo
无法播放视频。A:播放需要用户交互,并且 iframe 上存在
allow="autoplay"
。请参阅 https://developers.google.com/web/updates/ 2017/09/autoplay-policy-changes 和 https://developer.mozilla.org/en-US/docs/Web/Media/Autoplay_guide问:我使用
嵌入了 YouTube 视频
但该函数不执行任何函数!A:您必须在网址末尾添加
?enablejsapi=1
:/embed/vid_id?enablejsapi=1
。问:我收到错误消息“指定了无效或非法的字符串”。为什么?
A:API 在本地主机 (
file://
) 上无法正常运行。在线托管您的(测试)页面,或使用 JSFiddle。示例:请参阅此答案顶部的链接。问:你是怎么知道的?
A:我花了一些时间手动解释 API 的源代码。我的结论是我必须使用
postMessage
方法。为了知道要传递哪些参数,我创建了一个拦截消息的 Chrome 扩展。可以在此处下载该扩展的源代码。问:支持哪些浏览器?
A:支持 JSON 和
postMessage
。document.readyState
是在 3.6 中实现的)相关答案/实现:淡入带帧视频使用 jQuery
完整的 API 支持:在 jQuery 中监听 Youtube 事件
官方 API:https://developers.google.com/youtube/iframe_api_reference
修订历史记录
已实现
onYouTubePlayerReady
:callPlayer('frame_id', function() { ... })
。当玩家尚未准备好时,函数会自动排队。
已更新并在支持的浏览器中成功测试(展望未来)。
当函数作为参数传递时,
callPlayer
会强制检查准备情况。这是必需的,因为当在文档准备好时插入 iframe 后立即调用callPlayer
时,它无法确定 iframe 是否已完全准备好。在 Internet Explorer 和 Firefox 中,这种情况导致过早调用postMessage
,该调用被忽略。&origin=*
。&origin=*
的建议。Fiddle Links: Source code - Preview - Small version
Update: This small function will only execute code in a single direction. If you want full support (eg event listeners / getters), have a look at Listening for Youtube Event in jQuery
As a result of a deep code analysis, I've created a function:
function callPlayer
requests a function call on any framed YouTube video. See the YouTube Api reference to get a full list of possible function calls. Read the comments at the source code for an explanation.On 17 may 2012, the code size was doubled in order to take care of the player's ready state. If you need a compact function which does not deal with the player's ready state, see http://jsfiddle.net/8R5y6/.
Usage:
Possible questions (& answers):
Q: It doesn't work!
A: "Doesn't work" is not a clear description. Do you get any error messages? Please show the relevant code.
Q:
playVideo
does not play the video.A: Playback requires user interaction, and the presence of
allow="autoplay"
on the iframe. See https://developers.google.com/web/updates/2017/09/autoplay-policy-changes and https://developer.mozilla.org/en-US/docs/Web/Media/Autoplay_guideQ: I have embedded a YouTube video using
<iframe src="http://www.youtube.com/embed/As2rZGPGKDY" />
but the function doesn't execute any function!A: You have to add
?enablejsapi=1
at the end of your URL:/embed/vid_id?enablejsapi=1
.Q: I get error message "An invalid or illegal string was specified". Why?
A: The API doesn't function properly at a local host (
file://
). Host your (test) page online, or use JSFiddle. Examples: See the links at the top of this answer.Q: How did you know this?
A: I have spent some time to manually interpret the API's source. I concluded that I had to use the
postMessage
method. To know which arguments to pass, I created a Chrome extension which intercepts messages. The source code for the extension can be downloaded here.Q: What browsers are supported?
A: Every browser which supports JSON and
postMessage
.document.readyState
was implemented in 3.6)Related answer / implementation: Fade-in a framed video using jQuery
Full API support: Listening for Youtube Event in jQuery
Official API: https://developers.google.com/youtube/iframe_api_reference
Revision history
Implemented
onYouTubePlayerReady
:callPlayer('frame_id', function() { ... })
.Functions are automatically queued when the player is not ready yet.
Updated and successully tested in the supported browsers (look ahead).
When a function is passed as an argument,
callPlayer
forces a check of readiness. This is needed, because whencallPlayer
is called right after the insertion of the iframe while the document is ready, it can't know for sure that the iframe is fully ready. In Internet Explorer and Firefox, this scenario resulted in a too early invocation ofpostMessage
, which was ignored.&origin=*
in the URL.&origin=*
to the URL.看起来 YouTube 已经更新了他们的 JS API,所以默认情况下可用! 使用现有的 YouTube iframe 的 ID...
您可以在 JS 中
...并且构造函数将使用现有的 iframe,而不是用新的 iframe 替换它。这也意味着您不必向构造函数指定 videoId。
请参阅加载视频播放器
Looks like YouTube has updated their JS API so this is available by default! You can use an existing YouTube iframe's ID...
...in your JS...
...and the constructor will use your existing iframe instead of replacing it with a new one. This also means you don't have to specify the videoId to the constructor.
See Loading a video player
您可以使用更少的代码来完成此操作:
工作示例:
http://jsfiddle.net/kmturley/g6P5H/296/
You can do this with far less code:
Working example:
http://jsfiddle.net/kmturley/g6P5H/296/
我自己的 Kim T 代码版本与上面的一些 jQuery 相结合,并允许针对特定的 iframe。
My own version of Kim T's code above which combines with some jQuery and allows for targeting of specific iframes.
谢谢 Rob W 的回答。
我一直在 Cordova 应用程序中使用它,以避免加载 API,这样我就可以轻松控制动态加载的 iframe。
我一直希望能够从 iframe 中提取信息,例如状态 (getPlayerState) 和时间 (getCurrentTime)。
Rob W 帮助强调了 API 如何使用 postMessage 工作,但当然,这只能向一个方向发送信息,从我们的网页到 iframe。访问 getter 需要我们监听从 iframe 发回给我们的消息。
我花了一些时间才弄清楚如何调整 Rob W 的答案以激活并侦听 iframe 返回的消息。我基本上搜索了 YouTube iframe 中的源代码,直到找到负责发送和接收消息的代码。
关键是将“事件”更改为“监听”,这基本上可以访问所有旨在返回值的方法。
以下是我的解决方案,请注意,仅当请求 getter 时我才切换为“监听”,您可以调整条件以包含额外的方法。
进一步注意,您可以通过将 console.log(e) 添加到 window.onmessage 来查看从 iframe 发送的所有消息。您会注意到,一旦激活收听,您将收到不断的更新,其中包括视频的当前时间。调用诸如 getPlayerState 之类的 getter 将激活这些持续更新,但只会在状态发生更改时发送涉及视频状态的消息。
Thank you Rob W for your answer.
I have been using this within a Cordova application to avoid having to load the API and so that I can easily control iframes which are loaded dynamically.
I always wanted the ability to be able to extract information from the iframe, such as the state (getPlayerState) and the time (getCurrentTime).
Rob W helped highlight how the API works using postMessage, but of course this only sends information in one direction, from our web page into the iframe. Accessing the getters requires us to listen for messages posted back to us from the iframe.
It took me some time to figure out how to tweak Rob W's answer to activate and listen to the messages returned by the iframe. I basically searched through the source code within the YouTube iframe until I found the code responsible for sending and receiving messages.
The key was changing the 'event' to 'listening', this basically gave access to all the methods which were designed to return values.
Below is my solution, please note that I have switched to 'listening' only when getters are requested, you can tweak the condition to include extra methods.
Note further that you can view all messages sent from the iframe by adding a console.log(e) to the window.onmessage. You will notice that once listening is activated you will receive constant updates which include the current time of the video. Calling getters such as getPlayerState will activate these constant updates but will only send a message involving the video state when the state has changed.
我在使用上面的示例时遇到了问题,因此,我只是在源代码中使用带有自动播放功能的 JS 单击时插入了 iframe,它对我来说效果很好。我还可以使用 Vimeo 或 YouTube,所以我需要能够处理这个问题。
这个解决方案并不令人惊奇,可以清理,但这对我有用。我也不喜欢 jQuery,但项目已经在使用它,我只是重构现有代码,随意清理或转换为普通 JS :)
I was having issues with the above examples so instead, I just inserted the iframe on click in with JS with autoplay in the source and it works fine for me. I also had the possibility for Vimeo or YouTube so I needed to be able to handle that.
This solution isn't amazing and could be cleaned up but this worked for me. I also don't like jQuery but the project was already using it and I was just refactoring existing code, feel free to clean up or convert to vanilla JS :)
如果请求不是问题,并且您想要这种行为(例如显示/隐藏视频),一种快速解决方案是删除/添加 iframe,或者清理并填充
源代码
。iframe 将被删除,停止播放,然后立即加载。就我而言,我改进了代码,仅在打开灯箱时再次设置 src,因此仅当用户要求查看视频时才会发生加载。
One quick solution, if requests are not an issue, and you're wanting this behavior for something like a show/hide video, is to remove/add the iframe, or cleaning and filling the
src
.The iframe will be removed, stop to play and will be loaded right after that. In my case I've improved the code to only set the src again on lightbox open, so the load will only happen if user demands to see the video.