Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

YouTube embed API issue on IOS and Android

An issues popped up in the last few days with the YouTube embed API. The issue is that when you embed a video with the official API, it simply doesn't allow you to access to the API. When you try to access to the API, you got error message on the log (IOS) and if you try to play the video through the API the video blacks out. If you load it via the API, but you do not use the API, the user is able to play the video with tap.

The issue persist on the following browsers:

IOS 7 Safari on iPad and iPhone IOS 7 Chrome on iPad and iPhone Android 4 Chrome

(My play button uses the API to play the video and that produce the error) JSfiddle: http://jsfiddle.net/frdd8nvr/6/

Error message:

Unable to post message to https://www.youtube.com. Recipient has origin http://fiddle.jshell.net.
postMessage[native code]:0
Jwww-widgetapi.js:26:357
Nwww-widgetapi.js:25
(anonymous function)[native code]:0
html5player.js:1201:97

Blocked a frame with origin "https://www.youtube.com" from accessing a frame with origin "http://jsfiddle.net".  The frame requesting access has a protocol of "https", the frame being accessed has a protocol of "http". Protocols must match.

Some debug info:

As I see the API create the iframe on the site. The src is sometime http and sometime https.

http://www.youtube.com/embed/ZPy9VCovVME?enablejsapi=1&origin=http%3A%2F%2Ffiddle.jshell.net&autoplay=0&modestbranding=1&wmode=opaque&forceSSL=false

My test showed that most of the times YouTube servers simply LOCATION: https://... the request to the https url, but around 10% they served the http request with proper content.

I think somehow the issue related with the forced https, but I was not able to figure out the solution. Have you experienced the same? Do you have some kind of solution for this problem? Is it a YouTube bug?

My test code:

<div id="myvideo"></div>
<button id="play-button">Play</button>

JS:

var tag = document.createElement("script");
tag.src = "//www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

onYouTubeIframeAPIReady = function () {
    var vars = {
        enablejsapi: 1,
        origin: window.location.protocol + "//" + window.location.host,
        autoplay: 0,
        modestbranding: 1,
        wmode: "opaque",
        forceSSL: false
    };

    if (+(navigator.platform.toUpperCase().indexOf('MAC') >= 0 && navigator.userAgent.search("Firefox") > -1)){
        vars.html5 = 1;
    }
            var playerobj = new YT.Player('myvideo', {
                videoId: 'ZPy9VCovVME',
                wmode: 'opaque',
                playerVars: vars,
                events: {
                    onReady: function(){
                        $('#play-button').on('click', function(){
                           playerobj.playVideo(); 
                        });
                        //playerobj.playVideo();
                    },
                    onStateChange: function(state){
                        switch(state.data){
                            case YT.PlayerState.PLAYING:
                                break;
                            //case YT.PlayerState.PAUSED:
                            case YT.PlayerState.ENDED:
                                break;
                        }
                    }
                }
            });
}
like image 205
Roland Soós Avatar asked Sep 05 '14 11:09

Roland Soós


1 Answers

First, I think this is a duplicate of the following question: YouTube IFrame API play method doesn't work before touch on some Android tablets

I could reproduce the same problem on the YouTube Player Demo page.

The error

Unable to post message to https://www.youtube.com. Recipient has origin http://fiddle.jshell.net.

is only occuring on your jsfiddle. On the demo page this error is not occuring, therefore your observed bug seems not to be related to the error logged in the console. I checked this with chrome on Android 4.4.4.

Workaround

I have a dirty workaround which works on chrome on Android 4.4.4 (Nexus5) and 4.1.2 (S2). I have no iOS Device to test this. The workaround works on my phones, because the video always starts the second time I click the play-button.

http://jsfiddle.net/kjwpwpx8/6/

I can always start the video on click-Events after the playVideo function was called once before. In my workaround I put two iframes on the page. One is hidden while the other one is visible. If the page is viewed by a mobile browser I call the playVideo function of the second video after the OnReady-Event. The video won't play as the browser blocks this.

Now when our play-button is pressed the first video becomes hidden and stopped and the second video becomes visible and the playVideo function is called again.

Here is the important code:

var playerOptions = {
    videoId: 'ZPy9VCovVME',
    wmode: 'opaque',
    playerVars: vars,
    events: {}
};

var playerobj1 = new YT.Player('myvideo1', playerOptions);
var playerobj2 = null;

playerOptions.events.onReady = function(){
    $('#play-button').on('click', function(){
        $("#videowrapper .video1wrapper").hide();
        playerobj1.stopVideo();

        $("#videowrapper .video2wrapper").show();
        playerobj2.playVideo();
    });

    if(isMobileBrowser)
        playerobj2.playVideo();
};

playerobj2 = new YT.Player('myvideo2', playerOptions);
like image 82
PSanetra Avatar answered Sep 28 '22 04:09

PSanetra