1

I'm using youtube iframe api to detect when video starts playing, sometimes it can happen that state changes to buffering and then again to playing, so myFunction gets executed more than once per session, how do I make it run only once?

if (event.data == YT.PlayerState.PLAYING) {
    playing = true;
    player.mute();
    player.setPlaybackQuality('small');

    function myFunction() {
        setTimeout(function(){
            var videoData = player.getVideoData();
            var video_id = videoData['video_id'];
            const Http = new XMLHttpRequest();
            const url='https://url?viewcounter=' + video_id;
            Http.open("GET", url);
            Http.send();
        }, 3000);
    }
}
1
  • This would be easier to answer properly if you also included the code wherever myFunction is invoked, in addition to the definition. Commented Sep 26, 2019 at 17:01

5 Answers 5

3

Use a Boolean flag

var alreadyRun = false;
if (event.data == YT.PlayerState.PLAYING && !alreadyRun) {
            playing = true;
            alreadyRun = true;
            player.mute();
            player.setPlaybackQuality('small');
    function myFunction() {
      setTimeout(function(){
        var videoData = player.getVideoData();
        var video_id = videoData['video_id'];
        const Http = new XMLHttpRequest();
        const url='https://url?viewcounter=' + video_id;
        Http.open("GET", url);
        Http.send();
      }, 3000);
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

It looks like the playing variable may already exist for that purpose, in which case OP could just add that to the conditional instead of creating another flag.
0

I haven't tested this, but you could use a variable in your if statement, i.e:

var isplaying = false;

if (event.data == YT.PlayerState.PLAYING && isplaying === false) {
    isplaying = true;
    playing = true;
    player.mute();
    player.setPlaybackQuality('small');
    function myFunction() {
        setTimeout(function(){
            var videoData = player.getVideoData();
            var video_id = videoData['video_id'];
            const Http = new XMLHttpRequest();
            const url='https://url?viewcounter=' + video_id;
            Http.open("GET", url);
            Http.send();
        }, 3000);
    }
}

Comments

0

I would check also for if video is buffering so yt returns YT.PlayerState.BUFFERING

if (event.data === YT.PlayerState.PLAYING && event.data !== YT.PlayerState.BUFFERING)  {
    playing = true;
    player.mute();
    player.setPlaybackQuality('small');

    function myFunction() {
        setTimeout(function(){
            var videoData = player.getVideoData();
            var video_id = videoData['video_id'];
            const Http = new XMLHttpRequest();
            const url='https://url?viewcounter=' + video_id;
            Http.open("GET", url);
            Http.send();
        }, 3000);
    }
}

Comments

0

Use a global variable to run only 1 time.

var sw_myFunction = false;

if (event.data == YT.PlayerState.PLAYING) {
    playing = true;
    player.mute();
    player.setPlaybackQuality('small');

    function myFunction() {
        if(sw_myFunction) return;
        setTimeout(function(){
            var videoData = player.getVideoData();
            var video_id = videoData['video_id'];
            const Http = new XMLHttpRequest();
            const url='https://url?viewcounter=' + video_id;
            Http.open("GET", url);
            Http.send();
        }, 3000);
        sw_myFunction = true;
    }
}

Comments

0

Somethin is wrong, http request isn't called after 30 secs. Full code

<!DOCTYPE html>
<html>
  <body>
    <!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
    <div id="player"></div>

    <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);
     var sw_myFunction = false;
     var player, playing = false;
      function onYouTubeIframeAPIReady() {
        player = new YT.Player('player', {
          height: '100%',
          width: '100%',
          videoId: '<?php if (empty($vid)) {
    echo "YbJOTdZBX1g";
}
else {
    echo $vid;
}
 ?>',
          playerVars: {'controls': 0, 'fs': 0,'playsinline': 1 },         
          events: {
            'onError': onPlayerError, 
            'onReady': onPlayerReady,
            'onStateChange': onPlayerStateChange
          }
        });
      }

          function onPlayerStateChange(event) {


if (event.data == YT.PlayerState.PLAYING) {
    playing = true;
    player.mute();
    player.setPlaybackQuality('small');
    var videoData = player.getVideoData();
    var video_id = videoData['video_id'];
    function myFunction() {
        if(sw_myFunction) return;
        setTimeout(function(){
            const Http = new XMLHttpRequest();
            const url='https://www.url.com?viewcounter=' + video_id;
            Http.open("GET", url);
            Http.send();
        }, 30000);
        sw_myFunction = true;
    }
}

      else if(event.data == YT.PlayerState.PAUSED){     

       }

      else if(event.data == YT.PlayerState.ENDED){      

       }  

}
      function onPlayerReady(event) {
      }

function onPlayerError(event)
{       

}
    </script>
  </body>
</html>

3 Comments

Welcome to Stackoverflow! Generally, you should add information like this by editing your question, instead of posting it as an answer. That way people are less likely to miss it
To answer your question, the issue is that you've declared a function called myFunction in your code, but you need to call it with myFunction() in order for it to run.
Better yet, you could remove the function myFunction() { line entirely, along with the corresponding }, and just have the code run inline.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.