I’m working with embedded videos from YouTube and Vimeo inside an iframe element. I need to check whether the video is currently playing or paused when my function runs.
My setup works like this: when users click on a thumbnail image, my code loads the corresponding video into the iframe. There’s also a pause button that stops the video and hides the iframe.
I know about the YouTube API method getPlayerState()
and Vimeo’s getPaused()
function, but I can’t get them to work properly. I want to check the playback status programmatically instead of relying on click events.
<iframe id="videoFrame" width="640" height="360" src="" frameborder="0" allowfullscreen></iframe>
<script src="https://player.vimeo.com/api/player.js"></script>
<script src="https://www.youtube.com/iframe_api"></script>
function switchVideo(videoId) {
var frameElement = document.getElementById('videoFrame');
var videoUrl = '';
if (videoId === 'yt_sample') {
videoUrl = "https://www.youtube.com/embed/dQw4w9WgXcQ?enablejsapi=1";
} else if (videoId === 'vimeo_sample') {
videoUrl = "https://player.vimeo.com/video/148751763?api=1";
}
frameElement.src = videoUrl;
}
function checkVideoStatus() {
var frames = document.querySelectorAll('iframe');
frames.forEach(function(frame) {
var source = frame.getAttribute('src');
if (source && source.includes('youtube.com/embed')) {
var ytPlayer = new YT.Player(frame, {});
var status = ytPlayer.getPlayerState(); // This doesn't work
console.log('YouTube status:', status);
}
if (source && source.includes('player.vimeo.com')) {
var vimeoPlayer = new Vimeo.Player(frame);
vimeoPlayer.getPaused().then(function(paused) {
console.log('Vimeo paused:', paused); // Always returns false
});
}
});
}
The YouTube state check doesn’t work at all, and the Vimeo method always returns false even when the video is paused. How can I properly detect the playback state for both platforms?
Yeah, you’re creating new player instances every time checkVideoStatus runs - that won’t work. Once you initialize a YouTube or Vimeo player on an iframe, you can’t just create another one. Store the player objects in global variables and reuse them. Also, YouTube needs the API ready callback and Vimeo needs proper initialization time.
You’re trying to call player methods before the iframe communication kicks in. YouTube and Vimeo both use postMessage between your page and their iframe, and that setup takes time. I ran into this same thing on a video portal project. You need to use the ready events correctly and track player state. For YouTube, put your player creation inside onYouTubeIframeAPIReady and use onStateChange to monitor what’s happening. For Vimeo, wait for the ‘loaded’ event before calling any methods. What worked better for me was building a status tracker. I update a global state object whenever play/pause events fire, then check that object instead of asking the players directly. Kills the timing problems since you’re working with known states instead of polling the iframe.
Cross-origin restrictions are blocking your API calls. YouTube and Vimeo iframes run in sandboxed environments that block JavaScript access unless you configure them right. For YouTube, you’ve got enablejsapi=1
but you’re missing the origin
parameter - it needs to match your domain. With Vimeo, use the exact iframe element created when you set the src. Don’t query select it later or it breaks. Both use postMessage protocol, so any mismatch in player references kills the connection. I’ve hit this before - the iframe needs to load completely before you make API calls. Add load event listeners and only initialize players after the load event fires. Check your browser console for CORS errors too. They’ll show you exactly what’s getting blocked.
This is a timing and player initialization issue. You’re creating a new YT.Player instance without waiting for it to be ready - that won’t work. Store the player reference when you first create it and use event listeners instead.
I’ve hit this same problem before. Here’s what works: when you set the iframe src, initialize the players right away and store references globally. For YouTube, use the onReady callback so you know the API’s loaded. Vimeo players need time to establish communication with the iframe.
Store your player instances in variables outside your functions, then reference those stored players in checkVideoStatus instead of creating new ones each time. Don’t call checkVideoStatus immediately after setting the iframe source - wait until the players have fully loaded. The APIs need time to connect your script to the embedded player.