3

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

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

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

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

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

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

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

此外,基于 iframe 的播放器很可能不是我打算实现的真正解决方案(即能够从播放器获得及时的反馈)。如果是这样,你还有什么推荐的?我对这里的大多数建议持开放态度。


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

默认.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 文件副本)

// 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();
})();
4

1 回答 1

4

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

$.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]);

                };

            };



        }
    });

它并不完美,但你明白了。

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

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

于 2012-10-23T21:33:57.870 回答