6

私の目標は、グローバルメディアキーを介して制御できるオープンソースの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プレーヤーはExternalInterfaceクラスを使用してJavaScriptまたはAS3から制御するため、c#で動作するはずであると記載されています。


更新しました:


プレーヤーの埋め込みに使用される方法:http ://www.youtube.com/watch?v = kg-z8JfOIKw

また、WebBrowserコントロールでJavaScript-APIを使用しようとしましたが、運がありませんでした(プレーヤーは、JavaScriptコマンドに応答せずWebBrowser.url動作するデモに設定しようとしました。成功したのはonYouTubePlayerReady()、単純な埋め込みオブジェクトを使用してを起動することだけです。バージョン

私が監視しているセキュリティの問題があるかもしれないと思います、わかりません。


更新2:


良い解決策は、以下の私の答えを参照してください。

4

4 に答える 4

4

インターフェースとしてAdobeFlashを使おうとしているようです。次に、特定の変数をC#に戻します。

例はこれです:

フラッシュで; ボタンを作成...Actionscript:

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

次に、Visual StudioでCOMオブジェクト参照を追加する必要があります:Shockwave Flash Object

次に、埋め込みをtrueに設定します。

次に、Visual Studio内で、[プロパティ]に移動できるはずです。fscommandを見つけます。fsコマンドを使用すると、Flashムービーの値を物理的に接続できます。

AxShockwaveFlashObjects._IShockwaveFlashEvents_FSCommandEvent 

それは収集します。次に、を使用e.commandしてe.arg、たとえば、収集したアイテムに何かを実行させます。

次に、これをEventHandlerに追加します。

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

そして、ブームはそのデータをFlashからVisualStudioに送信しています。クレイジーで難しいソケットは必要ありません。

ちなみに; Visual Studio内にFlashがある場合、重要なのは、Flashが「埋め込みがtrueに設定されている」ことを確認することです。これにより、Flashオブジェクト内のすべてのパス参照が保持されます。間違ったパスへの誤呼び出しを避けるため。

それがあなたの求めている答えかどうかはわかりません。またはあなたの質問に答えます。しかし、あなたの目標/エラーに関する詳細はありません。私はあなたを助けることができません。

お役に立てれば。最初の部分は、実際に、ShockwaveをVisualStudioに埋め込むための最良の方法を示しているはずです。

正しい参照を追加してください。

  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>");
}

C#へのActionScript通信:

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 Communicationを利用することで、ネイティブAPIの利用に問題は発生しません。

それがもっと役立つことを願っています。ユーティリティクラスによってそのアイデアを拡張して再利用できます。明らかに、上記のコードにはいくつかの制限があります。しかし、うまくいけば、それはあなたを正しい方向に向けます。その方向はあなたが行こうとしていたのですか?それとも私はまだポイントを逃しましたか?


新しいFlashムービーを作成します。次に、ActionScript3で。最初の最初のフレームで。以下を適用します。

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を利用し、ActionScriptCommunicationを使用しています。それで、以下で私は各行を分解します。

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

その行がないと、YouTubeはオブジェクトと対話しません。

var my_player:Object;

ムービーをムービーにロードするだけでは不十分です。したがって、変数Objectを作成します。これらのコードへのアクセスを含む特別な.swfをロードする必要があります。以下; まさにそれをします。したがって、APIにアクセスできます。

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

ドキュメントごとにGoogleAPIを参照するようになりました。

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);は特定のビデオを参照しています。

それからあなたのステージで。2つのボタンを作成して適用できます。

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()

完全に初期化されるまで、これらを使用または呼び出すことはできないことに注意してください。しかし、それを使用します。以前の方法では、目標をレイアウトし、実際に2つの間で変数を渡して操作できるようにする必要があります。

うまくいけば、それがお役に立てば幸いです。

于 2012-11-13T20:13:34.953 に答える
2

まず、JavaScriptがFlashアプリと通信できることを確認します。

次のことを確認してください:allowScriptAccess="sameDomain"埋め込みに設定します(http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/external/ExternalInterface.html#includeExamplesSummaryから)。

html->flashが機能することを検証する必要があります。次にC->html; そして徐々にC->you-tube-componentまで作業します。現在、Cとyou-tube-componentの間に多くの潜在的な障害点があり、それらすべてに同時に対処することは困難です。

于 2012-11-16T22:01:58.240 に答える
2

何度も試して頭を悩ませた後、私は解決策を見つけました:

Error HRESULT E_FAIL...フラッシュが要求されたフラッシュ呼び出しを理解しないときに起こるようです。また、YouTubeの外部APIを機能させるには、jsAPIを有効にする必要があります。

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

質問で述べたように、プログラム全体がオープンソースであるため、完全なコードはbitbucketにあります。
アドバイス、提案、協力者は大歓迎です。

完全なソリューション:

これは、YouTubeプレーヤーまたはその他のフラッシュオブジェクトを埋め込んで操作するための完全なガイドです。

ビデオチュートリアルに従った後 、フラッシュプレーヤーの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()+"\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;
    }
}

これにより、フラッシュ-> c#通信が解決されます

フラッシュ外部関数の呼び出し(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;
}

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");
}

使用例:

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

関数YTplayer_CallFlashは、のスイッチ(コマンド)などの微調整を加えたフラッシュC#YTplayer_FlashCall通信で機能するはずです。YTplayer_CallFlash

于 2012-11-28T12:18:03.033 に答える
0

これは私を何時間も困惑させました。

URLにenableJSを追加するだけです。

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

CallFunctionは私にとって今はうまく機能しています!また、通話中の不要なスペースを削除します。

于 2013-05-12T14:52:44.150 に答える