1

I have a page with multiple videos embeds (iframes). Embed sources are diverse: youtube videos, facebook post including videos, facebook only video embed, instagram with video, twitter with video...

I would like via javascript or jquery to pause one video when another one is started, that is to say prevent 2 videos from playing at the same time.

I tried but can't use the tactic consisitng in pausing the video that is not inside the viewport as i might have cases where multiple videos are in the same viewport.

I failed to access events inside iframes.

Here are the jsfiddle of my page

HTML

<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet" data-lang="fr"><p lang="en" dir="ltr">And best sip goes to…   <a href="https://twitter.com/CocaCola/status/836010516493529088/video/1">pic.twitter.com/vDcpmcYFMJ</a></p>&mdash; Coca-Cola (@CocaCola) <a href="https://twitter.com/CocaCola/status/836010516493529088">27 février 2017</a></blockquote>

<iframe class="instagram-media instagram-media-rendered" id="instagram-embed-0" src="https://www.instagram.com/p/BPodiIYgG3K/embed/captioned/?cr=1&amp;v=7" allowtransparency="true" frameborder="0" height="776" data-instgrm-payload-id="instagram-media-payload-0" scrolling="no" style="background: rgb(255, 255, 255); border: 1px solid rgb(219, 219, 219); margin: 1px 1px 12px; max-width: 320px; width: calc(100% - 2px); border-radius: 4px; box-shadow: none; display: block; padding: 0px;"></iframe>
<script async="" defer="" src="//platform.instagram.com/en_US/embeds.js"></script>

<iframe src="https://www.facebook.com/plugins/video.php?href=https%3A%2F%2Fwww.facebook.com%2FGoProinFrance%2Fvideos%2F1956721507884735%2F&show_text=1&width=560" width="560" height="420" style="border:none;overflow:hidden" scrolling="no" frameborder="0" allowTransparency="true"></iframe>

<iframe src="https://www.facebook.com/plugins/video.php?href=https%3A%2F%2Fwww.facebook.com%2FGoProinFrance%2Fvideos%2F1955803827976503%2F&show_text=0&width=560" width="560" height="315" style="border:none;overflow:hidden" scrolling="no" frameborder="0" allowTransparency="true" allowFullScreen="true"></iframe>

<iframe width="560" height="315" src="https://www.youtube.com/embed/EDwb9jOVRtU" frameborder="0" allowfullscreen></iframe>

How to achieve this?

Mathieu
  • 4,587
  • 11
  • 57
  • 112

2 Answers2

2

If iframe's origin is different from current page's, it's impossible to access its contentDocument, not to mention listening/triggering events inside it. This is due to security concern. The access operation will case SecurityError

However, there is a workaround. You can make a "forward" route in your own backend (/iframeAddr for example), and use this route for all iframe src URL, passing the real video page URL as parameter. In server side, when HTTP request comes to /iframeAddr, the video page URL will be extracted and corresponding page content will be retrieved by server-side-programming. Finally, the video page content is sent back to browser. As /iframeAddr has the same origin with your JavaScript on page, you can access its contentDocument and listen playing video event, or trigger pause operation.

Community
  • 1
  • 1
shaochuancs
  • 15,342
  • 3
  • 54
  • 62
1

Normally you should use iframe API for YouTube and JavaScript SDK for Facebook to control iframed videos. But of course, there is a workaround ;) you can simply use:

iframe.contentWindow.postMessage(message, origin);

to send message to iframeWindow (from parentWindow). Those messages can include "playVideo", "pauseVideo", "stopVideo", "muteVideo" etc.. (whatever the video provider supports)

Unfortunately, only Youtube, Vimeo and Dailymotion (maybe some others) support this feature out of the box.

For the Facebook videos, there is an another work around though. You should reload the iframe when the video is outside the viewPort, or when an another iframe is clicked. This also raises an another question: "How am i supposed to capture the click event for iframe, this wasn't possible with simple click eventListener, right?"... Well, yes!. You can attach a click eventListener to an iframe element. Because it has a different scope, and you can't access its scope from parent window. But there is a work around for that too ;)

Check out my research about this area:

https://codepen.io/mcakir/pen/JpQpwm

and take a look at the JS codes. You will find your answers :))

  • Cheers
Must Ckr
  • 310
  • 2
  • 5
  • 1
    Could you edit part of the codepen example into the answer? – LW001 Mar 09 '18 at 14:21
  • Thanks you very much for your work. I am checking your code now very very impressive. i'm now all over iframe and co, access to iframe content, control of videos embed... and your work / research is very insightful! – Mathieu Mar 09 '18 at 14:23
  • by the way, out of curiosity, as I have trouble understanding sometimes, just with the chrome dev tools, when you pause the video, as you manage to when the video gets out of sight: does the video stops "streaming"=downloading remaining of the video stream data? or is it just "visual"= you pause the vidoe but behind the scene, the vidoe continues to download bytes of the remaining video data ? – Mathieu Mar 09 '18 at 14:45
  • @Mathieu for Youtube; when you pause the video, it also stops streaming, because YouTube won't stream unless you watch it. I suppose there is a 15 seconds or 30 seconds threshold (depends on the full length of the video) – Must Ckr Mar 12 '18 at 06:31
  • @MustafaCakir I'm all inside studying FB embed video. Have you found you can use for Facebook video embed a function to start playing video to access their iframe using contentWindow.postMessage ? I am failing to do it – Mathieu Mar 26 '18 at 09:44
  • @MustafaCakir I'm all inside studying FB embed video. Have you found you can use for a Facebook video inside their iframe using contentWindow.postMessage ? I am failing to do it – Mathieu Mar 26 '18 at 09:50
  • Are you able to achieve this with twitter. The code at [link](https://codepen.io/mcakir/pen/JpQpwm) do not work for twitter. – mjmicro Aug 27 '23 at 10:02