在 Windows 8 Metro js 应用程序中控制 iframe YouTube 播放器 [英] Controlling an iframe YouTube player within a Windows 8 Metro js app

查看:20
本文介绍了在 Windows 8 Metro js 应用程序中控制 iframe YouTube 播放器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在尝试使用 Windows 8 Metro js 应用程序(使用 HTML/Javascript/CSS 创建的应用程序,打算在即将推出的 Windows 8 的 Windows 应用商店中发布的应用程序)的功能时,我创建了一个非常简单的测试动态创建基于 iframe 的 YouTube 播放器的应用程序,与特定视频相关联.到目前为止,一切都很好.

While experimenting a little with the capabilities of Windows 8 Metro js apps (the ones created using HTML/Javascript/CSS, meant to be published on the Windows Store of the upcoming Windows 8), I went and created a very simple test application that creates dynamically an iframe-based YouTube player, tied to a specific video. So far, so good.

后来,我希望能够从在该 iframe 上播放的视频中获得反馈.谷歌为实现这一点提供了广泛的帮助,并解释说你需要动态地创建一个指向 YouTube iframe API 的标签,然后,一旦它完成加载,它会自动在你的代码中调用onYouTubeIframeAPIReady()"函数,因此它知道 API 已准备好与您最近创建的播放器一起操作,方法是调用操作播放器的函数,而不是返回统计信息,甚至附加监视播放器状态的事件处理程序.够简单了吧?

Later, I wanted to be able to get feedback from the video being played at that iframe. Google offers extensive help on achieving this, and explains that you need to, dynamically, create a tag pointing to the YouTube iframe API, and then, once it finishes loading, it will automatically call a "onYouTubeIframeAPIReady()" function in your code, so it knows the API is ready to operate with your recently created player, by calling functions that manipulate the player, and others than return statistics, and even attach event handlers that monitor the state of the player. Easy enough, right?

不幸的是,Windows 8 Metro js 应用程序并非如此.

Unfortunately, that's not the case with Windows 8 Metro js apps.

事实证明,由于应用程序在所谓的本地上下文"中运行,与网络上下文"不同,因此您实际上无法插入 <script > 标签指向远程资源,在网络上,这些应用程序.这意味着,我永远无法访问 YouTube iframe API 来处理我的播放器.

It turns out that, because of apps running in what's called the "local context", apart and distinct from the "web context", you cannot actually insert < script > tags pointing to remote resources, on the Web, for these apps. This meaning, I would never be able to get access to the YouTube iframe API to handle my player.

现在,检查 < 中引用的代码.脚本 > 标签,我意识到,截至今天,有 2 个相关的 .js 文件,一个实际上试图启动另一个,其中一个(显然)是独立的.看到这一点后,我抓取了两个 .js 文件的副本,将它们存储到我的项目中,进行了所有更改,以便项目在本地引用它们,而不是远程引用它们,瞧!现在,我从 iframe YouTube 播放器获得了功能齐全的反馈!

Now, examining the code being referenced in the < script > tag, I realized that, as of today, there are 2 related .js files, one actually attempting to launch the other, with that one being (apparently) self-contained. Upon seeing this, I grabbed a copy of both .js files, stored them into my project, did all the changes so the project referenced them locally, instead of remotely, and voila! Now I have fully-functional feedback from my iframe YouTube player!

然而,尽管成功了,我还是忍不住认为我在作弊.我正在保存我不应该控制的两个 .js 文件的副本.所有这些感觉就像一个,嗯,肮脏的黑客"只是为了让我的应用程序正常工作.

However, in spite of having succeeded, I can't quite help but think I'm cheating on here. I'm saving a copy of two .js files that I shouldn't be in control of. All this feels like a, um, "dirty hack" just to make things work in my app.

所以,知道这一点,我问你:有没有其他方法可以查询和控制嵌入到我的 Windows 8 Metro js 应用程序中的基于 iframe 的 YouTube 播放器,知道由于本地上下文"限制,我根本无法从 Google 引用 iframe API?

So, knowing this, I ask you: Is there any other way, whatsoever, that I could query AND control an iframe-based YouTube player embedded into my Windows 8 Metro js app, knowing that due to "local context" restrictions, I simply can't reference the iframe API from Google?

此外,基于 iframe 的播放器很可能不是我想要实现的真正解决方案(即能够从播放器获得及时反馈).如果是这样,你还有什么推荐的?我愿意接受这里的大多数建议.

Also, it could very well be that the iframe-based player is not the real solution for what I'm intending to achieve (which is, being able to get timely feedback from the player). If so, what else do you recommend? I'm open to most suggestions in here.

如果你有兴趣,这些是我的测试应用程序的default.html"和default.js",所以你可以看到我在说什么:

If you're interested, these are the "default.html" and "default.js" of my test app, so you can see what I'm talking about:

default.html:

default.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>PruebaYouTube</title>

    <!-- WinJS references -->
    <link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" />
    <script src="//Microsoft.WinJS.1.0/js/base.js"></script>
    <script src="//Microsoft.WinJS.1.0/js/ui.js"></script>

    <!-- PruebaYouTube references -->
    <link href="/css/default.css" rel="stylesheet" />
    <script src="/js/default.js"></script>
</head>
<body>
    <p id="contentGoesHere">Content goes here</p>
    <div id="playerPlaceholder"></div>
    <button id="createPlayer" style="display: none">Create Player</button>
</body>
</html>

default.js:(yt_iframe_api.jsyt_widgetapi.js 是我的 YouTube API 文件副本)

default.js: (yt_iframe_api.js and yt_widgetapi.js are my copies of the YouTube API files)

// For an introduction to the Blank template, see the following documentation:
// http://go.microsoft.com/fwlink/?LinkId=232509

var currentPlayer,
    embeddedText;

function initApp() {

    var ytScript = document.createElement('script');
    ytScript.src = "/js/yt_iframe_api.js";
    var firstScriptTag = document.getElementsByTagName('script')[0];
    firstScriptTag.parentNode.insertBefore(ytScript, firstScriptTag);

}

function onYouTubeIframeAPIReady() {

    var createPlayerButton = document.getElementById("createPlayer");
    createPlayerButton.style.display = "";

}

function onPlayerReady(event) {

    while (embeddedText.firstChild) {
        embeddedText.removeChild(embeddedText.firstChild);
    }
    embeddedText.appendChild(document.createTextNode("Listo!"));

}

function onPlayerStateChange(event) {

    while (embeddedText.firstChild) {
        embeddedText.removeChild(embeddedText.firstChild);
    }
    embeddedText.appendChild(document.createTextNode("Estado: " + event.data));

}

function createYouTubePlayer(mouseEvent) {

    var playerPlaceholder = document.getElementById("playerPlaceholder");
    while (playerPlaceholder.firstChild) {
        playerPlaceholder.removeChild(playerPlaceholder.firstChild);
    }

    var playerFrame = document.createElement("iframe");
    playerFrame.id = "playerFrame";
    playerFrame.setAttribute("type", "text/html");
    playerFrame.style.position = "absolute";
    playerFrame.style.top = "100px";
    playerFrame.style.left = "100px";
    playerFrame.width = "640px";
    playerFrame.height = "390px";
    playerFrame.src = "http://www.youtube.com/embed/u1zgFlCw8Aw?controls=0&autoplay=1";
    playerFrame.frameBorder = "0";

    playerPlaceholder.appendChild(playerFrame);

    embeddedText = document.createElement("p");
    embeddedText.style.fontSize = "24px";
    embeddedText.style.position = "absolute";
    embeddedText.style.top = "150px";
    embeddedText.style.left = "150px";

    playerPlaceholder.appendChild(embeddedText);

    currentPlayer = new YT.Player('playerFrame', {
        events: {
            'onReady': onPlayerReady,
            'onStateChange': onPlayerStateChange
        }
    });
}

function attachAllEvents() {

    var createPlayerButton = document.getElementById("createPlayer");
    createPlayerButton.addEventListener("click", createYouTubePlayer, false);

}

(function () {
    "use strict";

    WinJS.Binding.optimizeBindingReferences = true;

    var app = WinJS.Application;
    var activation = Windows.ApplicationModel.Activation;

    app.onactivated = function (args) {
        if (args.detail.kind === activation.ActivationKind.launch) {
            if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                // TODO: This application has been newly launched. Initialize
                // your application here.
                initApp();
            } else {
                // TODO: This application has been reactivated from suspension.
                // Restore application state here.
            }
            args.setPromise(WinJS.UI.processAll().done(attachAllEvents));
        }
    };

    app.oncheckpoint = function (args) {
        // TODO: This application is about to be suspended. Save any state
        // that needs to persist across suspensions here. You might use the
        // WinJS.Application.sessionState object, which is automatically
        // saved and restored across suspension. If you need to complete an
        // asynchronous operation before your application is suspended, call
        // args.setPromise().
    };

    app.start();
})();

推荐答案

我是这样弄的,希望对你有帮助.我使用 jQuery 进行 ajax 调用,并使用 Player Framework 来显示视频:

I made it in this way, I hope it can help you. I used jQuery for ajax calls and Player Framework to show the video:

$.ajax({
        url: "http://www.youtube.com/watch?NR=1&v=ZBDmUqp0JTU&feature=endscreen&nomobile=1",
        success: function (request) {

            var reg = new RegExp(/url_encoded_fmt_stream_map=(.*?)(&|\")/);
            var match = reg.exec(request);
            var data = decodeURIComponent(match[1]);

            var arr = data.split(",");

            var youtube = [];
            var cont = 0;

            for (var d in arr) {

                var url = "";
                var signature = "";
                var tuple = {};

                var _d = arr[d].split('&');                    

                for (var p in _d) {

                    var _p = _d[p];                        
                    var index = _p.indexOf('=');                        

                    if (index != -1 && index < _p.length) {

                        try {

                            var key = _p.substring(0, index);
                            var value = decodeURIComponent(_p.substring(index + 1));

                            if (key == 'url') {
                                url = value;
                            } else if (key == 'itag') {
                                tuple.Itag = parseInt(value);
                            } else if (key == 'type' && value.indexOf("video/mp4") > -1) {
                                tuple.Type = value;
                            } else if (key == 'sig') {
                                signature = value;
                            }

                        } catch(e) {}                                                        

                    }

                };

                tuple.url = url + "&signature=" + signature;

                if (url != null && tuple.Itag > 0 && tuple.Type != null && tuple.Type.indexOf("video/mp4") > -1) {
                    youtube.push(tuple.url);
                }

                cont++;

                if (cont == arr.length) {                        

                    var xvideo = document.getElementById("xvideo");
                    var control = new PlayerFramework.MediaPlayer(xvideo);
                    control.height = 600;
                    control.width = 800;
                    control.src = youtube[0];
                    control.load();

                    console.log("\rVideo MP4:\r", youtube[0]);

                };

            };



        }
    });

它并不完美,但您明白了.

It is not perfect but you got the idea.

这是我获取代码的地方:https://mytoolkit.svn.codeplex.com/svn/Shared/Multimedia/YouTube.cs

Here is where i took the code: https://mytoolkit.svn.codeplex.com/svn/Shared/Multimedia/YouTube.cs

PS:抱歉我的英语不好,我来自秘鲁;)

PS: Sorry for my bad english I'm from Perú ;)

这篇关于在 Windows 8 Metro js 应用程序中控制 iframe YouTube 播放器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆