Como pausar um player do YouTube ao ocultar o iframe?

86

Eu tenho um div oculto contendo um vídeo do YouTube em um <iframe>. Quando o usuário clica em um link, este div se torna visível, o usuário deve então ser capaz de reproduzir o vídeo.

Quando o usuário fecha o painel, a reprodução do vídeo deve ser interrompida. Como posso conseguir isso?

Código:

<!-- link to open popupVid -->
<p><a href="javascript:;" onClick="document.getElementById('popupVid').style.display='';">Click here</a> to see my presenting showreel, to give you an idea of my style - usually described as authoritative, affable and and engaging.</p>

<!-- popup and contents -->
<div id="popupVid" style="position:absolute;left:0px;top:87px;width:500px;background-color:#D05F27;height:auto;display:none;z-index:200;">

  <iframe width="500" height="315" src="http://www.youtube.com/embed/T39hYJAwR40" frameborder="0" allowfullscreen></iframe>

  <br /><br /> 
  <a href="javascript:;" onClick="document.getElementById('popupVid').style.display='none';">
  close
  </a>
</div><!--end of popupVid -->
0161-Jon
fonte
Não tenho certeza, mas talvez você tenha que encontrar uma maneira de interromper o vídeo ou removê-lo do div e não apenas ocultá-lo.
aniri
você deve aceitar a resposta.
snymkpr

Respostas:

188

A maneira mais fácil de implementar esse comportamento é chamar os métodos pauseVideoe playVideo, quando necessário. Inspirado pelo resultado da minha resposta anterior , escrevi uma função sem plug-in para atingir o comportamento desejado.

Os únicos ajustes:

  • Eu adicionei uma função, toggleVideo
  • Eu adicionei ?enablejsapi=1ao URL do YouTube, para habilitar o recurso

Demo: http://jsfiddle.net/ZcMkt/
Código:

<script>
function toggleVideo(state) {
    // if state == 'hide', hide. Else: show video
    var div = document.getElementById("popupVid");
    var iframe = div.getElementsByTagName("iframe")[0].contentWindow;
    div.style.display = state == 'hide' ? 'none' : '';
    func = state == 'hide' ? 'pauseVideo' : 'playVideo';
    iframe.postMessage('{"event":"command","func":"' + func + '","args":""}', '*');
}
</script>

<p><a href="javascript:;" onClick="toggleVideo();">Click here</a> to see my presenting showreel, to give you an idea of my style - usually described as authoritative, affable and and engaging.</p>

<!-- popup and contents -->
<div id="popupVid" style="position:absolute;left:0px;top:87px;width:500px;background-color:#D05F27;height:auto;display:none;z-index:200;">
   <iframe width="500" height="315" src="http://www.youtube.com/embed/T39hYJAwR40?enablejsapi=1" frameborder="0" allowfullscreen></iframe>
   <br /><br />
   <a href="javascript:;" onClick="toggleVideo('hide');">close</a>
Rob W
fonte
1
Sim, definitivamente precisa da caixa de seleção verde se isso funcionou. Estou pegando essa solução também - ótimo material, tenho esses quadros de vídeo em um jQueryUI Accordion, então preciso anexá-los a cada evento de gatilho.
jeffkee de
Só queria salientar que, infelizmente, a API do YouTube faz com que você use aspas duplas para a mensagem enviada por meio de postMessage. Você não pode alternar para aspas duplas externas e aspas simples internas, por exemplo.
Jordan
1
@Jordan Isso faz sentido porque se espera que a mensagem seja JSON. JSON, por definição, usa aspas duplas para citar chaves e valores.
Rob W
2
Se alguém estiver interessado, atualizei o código para interromper a reprodução do vídeo quando você clica no botão "Fechar" em um modal bootstrap 3. $ ("# MyModal-close") .click (function () {var div = document.getElementById ("MyModal-videoWrapper"); var iframe = div.getElementsByTagName ("iframe") [0] .contentWindow; iframe.postMessage ('{"evento": "comando", "função": "' + 'pauseVideo' + '", "args": ""}', '*');});
Ryan Walton
10
Observe que você deve adicionar o ?enablejsapi=1ao URL de incorporação do iframe desta forma: <iframe class="embed-responsive-item" src="//www.youtube.com/embed/WIZUeIDFALw?html5=1&enablejsapi=1" allowfullscreen></iframe>ou não funcionará :)
dineth 01 de
23

Aqui está uma abordagem do jQuery sobre a resposta de RobW para usar como ocultar / pausar um iframe em uma janela modal:

    function toggleVideo(state) {
        if(state == 'hide'){
            $('#video-div').modal('hide');
            document.getElementById('video-iframe'+id).contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}', '*');
        }
        else {
            $('#video-div').modal('show');
            document.getElementById('video-iframe'+id).contentWindow.postMessage('{"event":"command","func":"playVideo","args":""}', '*');
        }
    }

Os elementos html referidos são o próprio div modal (# video-div) chamando os métodos mostrar / ocultar e o iframe (# video-iframe) que tem o URL do vídeo como src = "" e tem o sufixo enablejsapi = 1 ? que permite o controle programático do player (por exemplo,

Para mais informações sobre o html, consulte a resposta de RobW.

DrewT
fonte
5
Qual legibilidade aprimorada estava mudando o? condicional a if / else, mas obrigado por me iniciar nisso. Eu apenas senti que tinha algo a acrescentar, só isso.
DrewT
15

Aqui está um snippet jQuery simples para pausar todos os vídeos na página com base nas respostas de RobW e DrewT:

jQuery("iframe").each(function() {
  jQuery(this)[0].contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}', '*')
});
quartarian
fonte
se você não quiser usar jQuery, o código dentro de 'cada' função é o mesmo depois de remover a referência do objeto jQuery. ou seja, node.contentWindow. ...
mattdlockyer
Como faço para reverter isso para reproduzir novamente quando o vídeo é mostrado novamente?
Carl Papworth
Basta substituir "pauseVideo" por "playVideo". Exemplo: jsfiddle.net/ora2kqzq/1
quartarian
Que já não está funcionando ... mesmo quando eu tento {"event":"command","func":"playVideo","args":[],"id":1,"channel":"widget"}depois {"event":"listening","id":1,"channel":"widget"}que é o que YT.Player iframe api está postando para o YouTube incorporar.
NoBugs de
9

Ei, uma maneira fácil é simplesmente definir o src do vídeo para nada, de modo que o vídeo desapareça enquanto estiver oculto e, em seguida, defina o src de volta para o vídeo que você deseja quando clicar no link que abre o vídeo .. fazer que simplesmente define um id para o iframe do youtube e chama a função src usando esse id como este:

<script type="text/javascript">
function deleteVideo()
{
document.getElementById('VideoPlayer').src='';
}

function LoadVideo()
{
document.getElementById('VideoPlayer').src='http://www.youtube.com/embed/WHAT,EVER,YOUTUBE,VIDEO,YOU,WHANT';
}
</script>

<body>

<p onclick="LoadVideo()">LOAD VIDEO</P>
<p onclick="deleteVideo()">CLOSE</P>

<iframe id="VideoPlayer" width="853" height="480" src="http://www.youtube.com/WHAT,EVER,YOUTUBE,VIDEO,YOU,HAVE" frameborder="0" allowfullscreen></iframe>

</boby>
Paula
fonte
4
Aviso: Modificações para o iframe's srccom javascript inadvertidamente empurrar para window.history, causando problemas de botão Voltar.
Jordan Arseno
Obrigado Jordan! Eu mesmo comecei a usar essa resposta e não estava ciente desse comportamento. Melhor saber agora do que mais tarde :)
MMachinegun
Aviso justo para qualquer um que tentar este método: pode causar um atraso extremamente perceptível se você estiver usando isso para alternar entre divs que contêm incorporações de iframe para o YouTube. Seja cuidadoso.
Muhammad Abdul-Rahim
6

Já que você precisa definir ?enablejsapi=trueo src do iframe antes de usar os comandos playVideo/ pauseVideomencionados em outras respostas , pode ser útil adicionar isso programaticamente via Javascript (especialmente se, por exemplo, você deseja que este comportamento se aplique a vídeos incorporados por outros usuários que acabaram de recortar e colar um código de incorporação do YouTube). Nesse caso, algo assim pode ser útil:

function initVideos() {

  // Find all video iframes on the page:
  var iframes = $(".video").find("iframe");

  // For each of them:
  for (var i = 0; i < iframes.length; i++) {
    // If "enablejsapi" is not set on the iframe's src, set it:
    if (iframes[i].src.indexOf("enablejsapi") === -1) {
      // ...check whether there is already a query string or not:
      // (ie. whether to prefix "enablejsapi" with a "?" or an "&")
      var prefix = (iframes[i].src.indexOf("?") === -1) ? "?" : "&amp;";
      iframes[i].src += prefix + "enablejsapi=true";
    }
  }
}

... se você chamar isso document.ready, todos os iframes em um div com uma classe de "vídeo" serão enablejsapi=trueadicionados à sua fonte, o que permite que os comandos playVideo / pauseVideo funcionem neles.

(nb. este exemplo usa jQuery para aquela linha que define var iframes, mas a abordagem geral deve funcionar tão bem com Javascript puro se você não estiver usando jQuery).

Nick F
fonte
5

Você pode parar o vídeo chamando o stopVideo()método na instância do player do YouTube antes de ocultar o div, por exemplo

player.stopVideo()

Para obter mais detalhes, consulte aqui: http://code.google.com/apis/youtube/js_api_reference.html#Playback_controls

david
fonte
qual é o objeto jogador e como você o acessa? Eu recebo o player indefinido e o vídeo ainda é reproduzido
Claudiu Creanga
Ele está disponível quando você o instanciou usando a API JS.
David
4

O método de RobW funcionou muito bem para mim. Para quem usa jQuery, aqui está uma versão simplificada que acabei usando:

var iframe = $(video_player_div).find('iframe');

var src = $(iframe).attr('src');      

$(iframe).attr('src', '').attr('src', src);

Neste exemplo, "video_player" é um div pai contendo o iframe.

skribbz14
fonte
4

Eu queria compartilhar uma solução que encontrei usando jQuery que funcione se você tiver vários vídeos do YouTube incorporados em uma única página. No meu caso, defini um pop-up modal para cada vídeo da seguinte maneira:

<div id="videoModalXX">
...
    <button onclick="stopVideo(videoID);" type="button" class="close"></button>
    ...
    <iframe width="90%" height="400" src="//www.youtube-nocookie.com/embed/video_id?rel=0&enablejsapi=1&version=3" frameborder="0" allowfullscreen></iframe>
...
</div>

Nesse caso, videoModalXX representa um id único para o vídeo. Então, a seguinte função interrompe o vídeo:

function stopVideo(id)
{
    $("#videoModal" + id + " iframe")[0].contentWindow.postMessage('{"event":"command","func":"pauseVideo","args":""}', '*');
}

Gosto dessa abordagem porque mantém o vídeo pausado de onde você parou, caso queira voltar e continuar assistindo mais tarde. Funciona bem para mim porque está procurando o iframe dentro do modal de vídeo com um id específico. Nenhum ID de elemento especial do YouTube é necessário. Esperançosamente, alguém achará isso útil também.

Poldon
fonte
Isso funcionou muito bem sem uma tonelada de código. Tenho vários vídeos do YT na página e apenas mostrando um polegar do YT e precisava de uma solução de parar / pausar. E alterando pauseVideo para playVideo, fui capaz de iniciar o vídeo quando ele se expandiu para a largura total da coluna
WebDude0482
2

apenas remova o src do iframe

$('button.close').click(function(){
    $('iframe').attr('src','');;
});
Rakesh Kejriwal
fonte
Mas ele pode querer continuar a jogar quando os usuários clicarem no botão aberto.
Coda Chang
brother, onclick novamente adiciona src via jquery, vai funcionar
rakesh kejriwal
1

A resposta de Rob W me ajudou a descobrir como pausar um vídeo sobre iframe quando um controle deslizante está oculto. Ainda assim, eu precisava de algumas modificações antes de fazê-lo funcionar. Aqui está um trecho do meu html:

<div class="flexslider" style="height: 330px;">
  <ul class="slides">
    <li class="post-64"><img src="http://localhost/.../Banner_image.jpg"></li>
    <li class="post-65><img  src="http://localhost/..../banner_image_2.jpg "></li>
    <li class="post-67 ">
        <div class="fluid-width-video-wrapper ">
            <iframe frameborder="0 " allowfullscreen=" " src="//www.youtube.com/embed/video-ID?enablejsapi=1 " id="fitvid831673 "></iframe>
        </div>
    </li>
  </ul>
</div>

Observe que isso funciona em locaishosts e também como Rob W mencionou " enablejsapi = 1 " foi adicionado ao final da URL do vídeo.

A seguir está meu arquivo JS:

jQuery(document).ready(function($){
    jQuery(".flexslider").click(function (e) {
        setTimeout(checkiframe, 1000); //Checking the DOM if iframe is hidden. Timer is used to wait for 1 second before checking the DOM if its updated

    });
});

function checkiframe(){
    var iframe_flag =jQuery("iframe").is(":visible"); //Flagging if iFrame is Visible
    console.log(iframe_flag);
    var tooglePlay=0;
    if (iframe_flag) {                                //If Visible then AutoPlaying the Video
        tooglePlay=1;
        setTimeout(toogleVideo, 1000);                //Also using timeout here
    }
    if (!iframe_flag) {     
        tooglePlay =0;
        setTimeout(toogleVideo('hide'), 1000);  
    }   
}

function toogleVideo(state) {
    var div = document.getElementsByTagName("iframe")[0].contentWindow;
    func = state == 'hide' ? 'pauseVideo' : 'playVideo';
    div.postMessage('{"event":"command","func":"' + func + '","args":""}', '*');
}; 

Além disso, como um exemplo mais simples, verifique isso no JSFiddle

Fahim Hossain
fonte
1

Essa abordagem requer jQuery. Primeiro, selecione seu iframe:

var yourIframe = $('iframe#yourId');
//yourId or something to select your iframe.

Agora você seleciona o botão reproduzir / pausar deste iframe e clica nele

$('button.ytp-play-button.ytp-button', yourIframe).click();

Espero que ajude você.

hong4rc
fonte
0

As respostas de RobW aqui e em outros lugares foram muito úteis, mas descobri que minhas necessidades eram muito mais simples. Já respondi em outro lugar , mas talvez seja útil aqui também.

Eu tenho um método onde formo uma string HTML para ser carregada em um UIWebView:

NSString *urlString = [NSString stringWithFormat:@"https://www.youtube.com/embed/%@",videoID];

preparedHTML = [NSString stringWithFormat:@"<html><body style='background:none; text-align:center;'><script type='text/javascript' src='http://www.youtube.com/iframe_api'></script><script type='text/javascript'>var player; function onYouTubeIframeAPIReady(){player=new YT.Player('player')}</script><iframe id='player' class='youtube-player' type='text/html' width='%f' height='%f' src='%@?rel=0&showinfo=0&enablejsapi=1' style='text-align:center; border: 6px solid; border-radius:5px; background-color:transparent;' rel=nofollow allowfullscreen></iframe></body></html>", 628.0f, 352.0f, urlString];

Você pode ignorar as coisas de estilo na sequência de HTML preparado. Os aspectos importantes são:

  • Usando a API para criar o objeto "YT.player". Em um ponto, eu só tinha o vídeo na tag iFrame e isso me impediu de fazer referência ao objeto "player" posteriormente com JS.
  • Eu vi alguns exemplos na web onde a primeira tag de script (aquela com a tag iframe_api src) é omitida, mas eu definitivamente precisava disso para fazer isso funcionar.
  • Criação da variável "player" no início do script da API. Também vi alguns exemplos que omitiram essa linha.
  • Adicionando uma tag id ao iframe para ser referenciado no script API. Quase esqueci essa parte.
  • Adicionando "enablejsapi = 1" ao final da tag src do iFrame. Isso me deixou paralisado por um tempo, pois inicialmente eu o tinha como um atributo da tag iFrame, que não funciona / não funcionou comigo.

Quando preciso pausar o vídeo, acabo de executar o seguinte:

[webView stringByEvaluatingJavaScriptFromString:@"player.pauseVideo();"];

Espero que ajude!

Brian
fonte
Caso você esteja se perguntando por que não houve votos positivos, é porque isso não é javascript e, portanto, não é útil para o caso de uso do OP, que é um iframe referenciando uma url incorporada do youtube, não um aplicativo iOS.
Vroo
@Vroo Sim, eu entendo. Só queria deixar esta resposta aqui, caso outra pessoa iOS viesse aqui e encontrasse essa pergunta como eu.
Brian
0

Isso está funcionando bem para mim com o jogador YT

 createPlayer(): void {
  return new window['YT'].Player(this.youtube.playerId, {
  height: this.youtube.playerHeight,
  width: this.youtube.playerWidth,
  playerVars: {
    rel: 0,
    showinfo: 0
  }
});
}

this.youtube.player.pauseVideo ();

HuyLe
fonte
0

Uma resposta mais concisa, elegante e segura: adicione “? Enablejsapi = 1” ao final do URL do vídeo e, a seguir, construa e crie um string para um objeto comum que representa o comando pause:

const YouTube_pause_video_command_JSON = JSON.stringify(Object.create(null, {
    "event": {
        "value": "command",
        "enumerable": true
    },
    "func": {
        "value": "pauseVideo",
        "enumerable": true
    }
}));

Use o Window.postMessagemétodo para enviar a string JSON resultante para o documento de vídeo incorporado:

// |iframe_element| is defined elsewhere.
const video_URL = iframe_element.getAttributeNS(null, "src");
iframe_element.contentWindow.postMessage(YouTube_pause_video_command_JSON, video_URL);

Certifique-se de especificar o URL do vídeo para o argumento Window.postMessagedo método targetOriginpara garantir que suas mensagens não sejam enviadas a nenhum destinatário indesejado.

Patrick Dark
fonte