如何用c#控制youtube flash播放器?

Ste*_*gin 6 .net c# youtube flash youtube-api

我的目标是制作一个可以通过全球媒体键控制的开源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>");
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,这回归

"Error HRESULT E_FAIL has been returned from a call to a COM component."
Run Code Online (Sandbox Code Playgroud)

我错过了什么?我应该加载不同的URL吗?
该文档指出,YouTube播放器使用ExternalInterface类来控制JavaScript或AS3,因此它应该与c#一起使用.


更新:


用于嵌入播放器的方法:http://www.youtube.com/watch?v = kg-z8JfOIKw

也试图用JavaScript的API WebBrowser控件,但没有运气(球员只是没有到JavaScript命令做出反应,甚至试图设置WebBrowser.url工作演示,都认为我成功是让onYouTubePlayerReady()使用简单火嵌入对象版本)

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


更新2:


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

Ste*_*gin 2

经过多次尝试和绞尽脑汁,我找到了解决方案:

似乎Error HRESULT E_FAIL...当闪存不理解请求的闪存调用时就会发生这种情况。另外,为了让 youtube 外部 api 工作,需要启用js api :

player.movie = "http://www.youtube.com/v/VIDEO_ID?version=3&enablejsapi=1"
Run Code Online (Sandbox Code Playgroud)

正如我在问题中所说,整个程序是开源的,因此您可以在bitbucket找到完整的代码。
任何意见、建议或合作者都将受到高度赞赏。

完整的解决方案:

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

遵循视频教程后 ,将 flash 播放器的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);
...
Run Code Online (Sandbox Code Playgroud)

FlashCall 事件处理程序

private void YTplayer_FlashCall(object sender, AxShockwaveFlashObjects._IShockwaveFlashEvents_FlashCallEvent e)
{
    Console.Write("YTplayer_FlashCall: raw: "+e.request.ToString()+"\r\n");
    // 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) + ")\r\n");
    // 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)\r\n"); break;
    }
}
Run Code Online (Sandbox Code Playgroud)

这将解决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 + "\"\r\n");
        response = YTplayer.CallFunction(flashXMLrequest);                
        Console.Write("YTplayer_CallFlash_response: \"" + response + "\"\r\n");
    }
    catch
    {
        Console.Write("YTplayer_CallFlash: error \"" + flashXMLrequest + "\"\r\n");
    }

    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;
}
Run Code Online (Sandbox Code Playgroud)

添加 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+"\r\n");
}
Run Code Online (Sandbox Code Playgroud)

用法例如:

YTplayer_CallFlash("playVideo()");
YTplayer_CallFlash("pauseVideo()");
YTplayer_CallFlash("loadVideoById(KuNQgln6TL0)");
string currentVideoId = YTplayer_CallFlash("getPlaylist()");
string currentDuration = YTplayer_CallFlash("getDuration()");
Run Code Online (Sandbox Code Playgroud)

YTplayer_CallFlash这些功能YTplayer_FlashCall应该适用于任何flash-C#通信,只需进行细微调整,例如YTplayer_CallFlash开关(命令)。