如何用C#控制YouTube Flash播放器



我的目标是制作一个可以通过全球媒体密钥控制的开源YouTube播放器。我得到的全局关键问题,但是YouTube播放器和我的Windows表单应用程序之间的通信只是出于某种原因而行不通。

到目前为止,这就是我所拥有的:

private AxShockwaveFlashObjects.AxShockwaveFlash player;
player.movie = "http://youtube.googleapis.com/v/9bZkp7q19f0"
...
private void playBtn_Click(object sender, EventArgs e)
{
    player.CallFunction("<invoke name="playVideo" returntype="xml"></invoke>");
}

不幸的是,这返回:

"Error HRESULT E_FAIL has been returned from a call to a COM component."

我想念什么?我应该加载其他URL吗?
文档指出,YouTube播放器使用外部接口类从JavaScript或AS3控制它,因此它应该与C#。

一起使用

更新:


用于嵌入玩家的方法:http://www.youtube.com/watch?v=kg-z8jfoikw

还试图在WebBrowser控件中使用JavaScript-API,但没有运气(玩家只是没有响应JavaScript命令,甚至尝试将WebBrowser.url设置为工作演示,我所取得的成功就是让onYouTubePlayerReady()启动。使用简单的嵌入式对象版本)

我认为可能有一些我正在监督的安全问题,不知道。


更新2:


喜欢的解决方案,请参阅下面的答案。

听起来您试图将Adobe Flash用作接口;然后将某些变量传递回C#。

一个例子就是这样:

在Flash中;创建一个按钮... ActionScript:

on (press) {
    fscommand("Yo","dude");
}

然后,Visual Studio您只需要添加COM对象参考:ShockWave Flash对象

然后将嵌入到true;

然后在Visual Studio内部您应该能够转到属性;查找fscommand。FSCommand将允许您从Flash电影中实际连接该值。

AxShockwaveFlashObjects._IShockwaveFlashEvents_FSCommandEvent 

收集的;然后,只需使用e.commande.arg例如让收集的项目做点什么。

然后将其添加到EventHandler;

lbl_Result.Text="The "+e.args.ToString()+" "+e.command.ToString()+" was clicked";

和繁荣,它将其数据从Flash传输到Visual Studio。无需任何疯狂的困难插座。

在旁注;如果您在Visual Studio内有Flash,那么关键是要确保其"嵌入为true"。这将保存闪光灯对象中的所有路径参考;为了避免任何错误的路径。

我不确定这是您寻求的答案;或回答您的问题。但是没有更多有关您的目标/错误的详细信息。我无法帮助您。

希望这会有所帮助。第一部分实际上应该向您展示将冲击波嵌入到Visual Studio中的最佳方法。

确保添加正确的参考:

  1. 在您的项目中,打开'解决方案资源管理器'
  2. 右键单击'添加参考'
  3. 转到'com对象'

找到适当的对象;

COM Objects:
Shockwave ActiveX
Flash Accessibility
Flash Broker
Shockwave Flash

希望会有所帮助。

听起来您没有正确嵌入它;因此,您可以打电话给它。如果我有点误会;还是您的意思是:

如果您遇到困难,Ryk有一段时间的后备;使用嵌入YouTube视频的方法:

<% MyYoutubeUtils.ShowEmebddedVideo("<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/gtNlQodFMi8&hl=en&fs=1"></param><param name="allowFullScreen" value="true"></param><embed src="http://www.youtube.com/v/gtNlQodFMi8&hl=en&fs=1" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="344"></embed></object>") %>

或...

public static string ShowEmbeddedVideo(string youtubeObject)
{
    var xdoc = XDocument.Parse(youtubeObject);
    var returnObject = string.Format("<object type="{0}" data={1}"><param name="movie" value="{1}" />",
        xdoc.Root.Element("embed").Attribute("type").Value,
        xdoc.Root.Element("embed").Attribute("src").Value);
    return returnObject;
}

您可以在此处找到线程:https://stackoverflow.com/questions/2547101/purify-embedding-youtube-videos-method-in-c-sharp

如果我的帖子看起来分散,我确实深表歉意;但是我无法分辨是引起您困难的参考,变量,方法或嵌入的方法。真正希望这会有所帮助;或给我更多详细信息,我会相应地调整我的回复。


c#到ActionScript通信:

import flash.external.ExternalInterface;
ExternalInterface.addCallback("loadAndPlayVideo", null, loadAndPlayVideo);
function loadAndPlayVideo(uri:String):void
{
       videoPlayer.contentPath = uri;
}

然后在C#中;添加ActiveX控件的实例并将内容添加到构造函数中。

private AxShockwaveFlash flashPlayer;
public FLVPlayer ()
{
      // Add Error Handling; to condense I left out.
      flashPlayer.LoadMovie(0, Application.StartupPath + "\player.swf");
}
fileDialog = new OpenFileDialog();
fileDialog.Filter = "*.flv|*.flv";
fileDialog.Title = "Select a Flash Video File...";
fileDialog.Multiselect = false;
fileDialog.RestoreDirectory = true;
if (fileDialog.ShowDialog() == DialogResult.OK)
{
     flashPlayer.CallFunction("<invoke" + " name="loadAndPlayVideo" returntype="xml">       <arguements><string>" + fileDialog.FileName + "</string></arguements></invoke>");
}

ActionScript通信与C#:

import flash.external.ExternalInterface;
ExternalInterface.call("ResizePlayer", videoPlayer.metadata.width, videoPlayer.metadata.height);
flashPlayer.FlashCall += new _IShockwaveFlashEvents_FlashCallEventHandler(flashPlayer_FlashCall);

然后XML应该出现:

<invoke name="ResizePlayer" returntype="xml">
     <arguements>
            <number> 320 </number>
            <number> 240 </number>
     </arguments>
</invoke>

然后在事件处理程序中解析XML并在本地调用C#函数。

 XmlDocument document = new XmlDocument();
    document.LoadXML(e.request);
    XmlNodeList list = document.GetElementsByTagName("arguements");
    ResizePlayer(Convert.ToInt32(list[0].FirstChild.InnerText),   Convert.ToInt32(list[0].ChildNodes[1].InnerText));

现在他们都来回传递数据。这是一个基本示例;但是,通过使用ActionScript通信,您不应使用本机API遇到任何问题。

希望这会更有帮助。您可以通过公用事业课扩展该想法以进行重复使用。显然,上述代码有一些局限性;但是希望它将您指向正确的方向。您试图走的那个方向吗?还是我仍然错过了重点?


创建新的Flash电影;在ActionScript 3中。然后在初始第一帧中;应用以下:

Security.allowDomain("www.youtube.com");
var my_player:Object;
var my_loader:Loader = new Loader();
my_loader.load(new URLRequest("http://www.youtube.com/apiplayer?version=3"))
my_loader.contentLoaderInfo.addEventListener(Event.INIT, onLoaderInit);
function onLoaderInit(e:Event):void{
addChild(my_loader);
my_player = my_loader.content;
my_player.addEventListener("onReady", onPlayerReady); 
} 
function onPlayerReady(e:Event):void{
my_player.setSize(640,360);
my_player.loadVideoById("_OBlgSz8sSM",0);
} 

那么该脚本到底在做什么?它利用本机API并使用ActionScript通信。所以在下面我分解每行。

Security.allowDomain("www.youtube.com");

没有该行YouTube不会与对象相互作用。

var my_player:Object;

您不能只是将电影加载到电影中;因此,我们将创建一个变量对象。您必须加载一个特殊的.swf,其中包含对这些代码的访问。下面;就是这样。因此您可以访问API。

var my_loader:Loader = new Loader();
my_loader.load(new URLRequest("http://www.youtube.com/apiplayer?version=3")); 

现在,我们根据其文档将Google API引用。

my_loader.contentLoaderInfo.addEventListener(Event.INIT, onLoaderInit);

但为了实际与我们的对象合作;我们需要等待它完全初始化。因此,事件侦听器将等待;因此,我们知道何时可以将命令传递给它。

初始化时将触发onLoaderInit功能。然后,第一个任务是my_loader显示列表,以便显示视频。

addChild(my_loader);是加载一个;my_player = my_loader.content;将存储一个参考,以方便访问对象。

尽管已经初始化了;您必须等待进一步等待...您使用my_player.addEventListener("onReady", onPlayerReady);等待这些自定义事件。这将允许以后的功能处理。

现在,玩家准备好基本配置;

function onPlayerReady(e:Event):void{
my_player.setSize(640,360);
} 

上述功能启动非常基本的操作。然后,最后一行my_player.loadVideoById("_OBlgSz8sSM",0);是引用特定视频。

然后在您的舞台上;您可以创建两个按钮并应用:

play_btn.addEventListener(MouseEvent.CLICK, playVid); 
function playVid(e:MouseEvent):void { 
my_player.playVideo(); 
} 
pause_btn.addEventListener(MouseEvent.CLICK, pauseVid); 
function pauseVid(e:MouseEvent):void { 
my_player.pauseVideo();
}

这将为您提供游戏和暂停功能。您可以使用我们的其他项目:

loadVideoById() 
cueVideoById() 
playVideo() 
pauseVideo() 
stopVideo() 
mute()
unMute()

请记住,在完全初始化之前,不能使用或调用。但是使用它;使用较早的方法,您应该允许您布局,并实际上通过两者之间的变量进行操作。

希望这会有所帮助。

我首先要确保JavaScript可以与您的Flash应用交谈。

确保您有:allowScriptAccess="sameDomain"在嵌入式中设置(http://help.adobe.com/en_us/flashplatform/reference/referendions/actionscript/3/flash/externalterless/external/external/external/com-htternal/chtml#includeeexamplessamary ),

您应该验证html-> flash有效;然后c-> html;并逐渐工作到c-> you-tube-compont。您现在在C和You-tube组件之间有很多潜在的故障点,并且很难同时解决所有这些。p>经过大量尝试和头部撞击后,我找到了一个解决方案:

似乎Error HRESULT E_FAIL...当闪光灯dosen不了解所请求的闪存调用时发生。同样要使YouTube外部API工作,需要启用JS API:

player.movie = "http://www.youtube.com/v/VIDEO_ID?version=3&enablejsapi=1"

正如我在问题中所说的整个程序是开源的,因此您会在Bitbucket找到完整的代码。

任何建议,建议或合作者都非常感谢。

完整的解决方案:

这是嵌入和与YouTube播放器或任何其他Flash对象进行嵌入和交互的完整指南。

关注视频教程后,将Flash Player的FlashCall事件设置为将处理 flash-> C#交互的功能(在我的示例中,它是YTplayer_FlashCall

生成的'initializecomponent()`应为:

...
this.YTplayer = new AxShockwaveFlashObjects.AxShockwaveFlash();
this.YTplayer.Name = "YTplayer";
this.YTplayer.Enabled = true;
this.YTplayer.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("YTplayer.OcxState")));
this.YTplayer.FlashCall += new AxShockwaveFlashObjects._IShockwaveFlashEvents_FlashCallEventHandler(this.YTplayer_FlashCall);
...

flashcall事件处理程序

private void YTplayer_FlashCall(object sender, AxShockwaveFlashObjects._IShockwaveFlashEvents_FlashCallEvent e)
{
    Console.Write("YTplayer_FlashCall: raw: "+e.request.ToString()+"rn");
    // message is in xml format so we need to parse it
    XmlDocument document = new XmlDocument();
    document.LoadXml(e.request);
    // get attributes to see which command flash is trying to call
    XmlAttributeCollection attributes = document.FirstChild.Attributes;
    String command = attributes.Item(0).InnerText;
    // get parameters
    XmlNodeList list = document.GetElementsByTagName("arguments");
    List<string> listS = new List<string>();
    foreach (XmlNode l in list){
        listS.Add(l.InnerText);
    }
    Console.Write("YTplayer_FlashCall: "" + command.ToString() + "(" + string.Join(",", listS) + ")rn");
    // Interpret command
    switch (command)
    {
        case "onYouTubePlayerReady": YTready(listS[0]); break;
        case "YTStateChange": YTStateChange(listS[0]); break;
        case "YTError": YTStateError(listS[0]);  break;
        default: Console.Write("YTplayer_FlashCall: (unknownCommand)rn"); break;
    }
}

这将解决 flash-> c#通信

调用Flash外部功能(C# -> Flash):

private string YTplayer_CallFlash(string ytFunction){
    string flashXMLrequest = "";
    string response="";
    string flashFunction="";
    List<string> flashFunctionArgs = new List<string>();
    Regex func2xml = new Regex(@"([a-z][a-z0-9]*)((([^)]*)))?", RegexOptions.Compiled | RegexOptions.IgnoreCase);
    Match fmatch = func2xml.Match(ytFunction);
    if(fmatch.Captures.Count != 1){
        Console.Write("bad function request string");
        return "";
    }
    flashFunction=fmatch.Groups[1].Value.ToString();
    flashXMLrequest = "<invoke name="" + flashFunction + "" returntype="xml">";
    if (fmatch.Groups[3].Value.Length > 0)
    {
        flashFunctionArgs = pars*emphasized text*eDelimitedString(fmatch.Groups[3].Value);
        if (flashFunctionArgs.Count > 0)
        {
            flashXMLrequest += "<arguments><string>";
            flashXMLrequest += string.Join("</string><string>", flashFunctionArgs);
            flashXMLrequest += "</string></arguments>";
        }
    }
    flashXMLrequest += "</invoke>";
    try
    {
        Console.Write("YTplayer_CallFlash: "" + flashXMLrequest + ""rn");
        response = YTplayer.CallFunction(flashXMLrequest);                
        Console.Write("YTplayer_CallFlash_response: "" + response + ""rn");
    }
    catch
    {
        Console.Write("YTplayer_CallFlash: error "" + flashXMLrequest + ""rn");
    }
    return response;
}
private static List<string> parseDelimitedString (string arguments, char delim = ',')
{
    bool inQuotes = false;
    bool inNonQuotes = false;
    int whiteSpaceCount = 0;
    List<string> strings = new List<string>();
    StringBuilder sb = new StringBuilder();
    foreach (char c in arguments)
    {
        if (c == ''' || c == '"')
        {
            if (!inQuotes)
                inQuotes = true;
            else
                inQuotes = false;
            whiteSpaceCount = 0;
        }else if (c == delim)
        {
            if (!inQuotes)
            {
                if (whiteSpaceCount > 0 && inQuotes)
                {
                    sb.Remove(sb.Length - whiteSpaceCount, whiteSpaceCount);
                    inNonQuotes = false;
                }
                strings.Add(sb.Replace("'", string.Empty).Replace(""", string.Empty).ToString());
                sb.Remove(0, sb.Length);                       
            }
            else
            {
                sb.Append(c);
            }
            whiteSpaceCount = 0;
        }
        else if (char.IsWhiteSpace(c))
        {                    
            if (inNonQuotes || inQuotes)
            {
                sb.Append(c);
                whiteSpaceCount++;
            }
        }
        else
        {
            if (!inQuotes) inNonQuotes = true;
            sb.Append(c);
            whiteSpaceCount = 0;
        }
    }
    strings.Add(sb.Replace("'", string.Empty).Replace(""", string.Empty).ToString());

    return strings;
}

添加YouTube事件处理程序:

private void YTready(string playerID)
{
    YTState = true;
    //start eventHandlers
    YTplayer_CallFlash("addEventListener("onStateChange","YTStateChange")");
    YTplayer_CallFlash("addEventListener("onError","YTError")");
}
private void YTStateChange(string YTplayState)
{
    switch (int.Parse(YTplayState))
    {
        case -1: playState = false; break; //not started yet
        case 1: playState = true; break; //playing
        case 2: playState = false; break; //paused
        //case 3: ; break; //buffering
        case 0: playState = false; if (!loopFile) mediaNext(); else YTplayer_CallFlash("seekTo(0)"); break; //ended
    }
}
private void YTStateError(string error)
{
    Console.Write("YTplayer_error: "+error+"rn");
}

用法EX:

YTplayer_CallFlash("playVideo()");
YTplayer_CallFlash("pauseVideo()");
YTplayer_CallFlash("loadVideoById(KuNQgln6TL0)");
string currentVideoId = YTplayer_CallFlash("getPlaylist()");
string currentDuration = YTplayer_CallFlash("getDuration()");

函数YTplayer_CallFlashYTplayer_FlashCall应适用于任何 flash-c#通信,诸如YTplayer_CallFlash的S switch(命令)。

这使我陷入困境。

只需在您的URL中添加启用JS:

http://www.youtube.com/v/9bzkp7q19f0?version=3 &amp; enablejsapi = 1

呼叫功能现在对我来说很好!还要删除呼叫中的未支付的空间。

相关内容

  • 没有找到相关文章

最新更新