Как управлять флэш-плеером youtube с помощью c#?

моя цель-сделать проигрыватель YouTube с открытым исходным кодом, который можно управлять с помощью глобальных медиа-ключей. Глобальная ключевая проблема, которую я получил, но связь между проигрывателем YouTube и моим приложением Windows Forms просто не работает по какой-то причине.

пока это то, что у меня есть:

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 player использует класс ExternalInterface для управления им из JavaScript или AS3 so он должен работать с C#.


обновление:


метод, используемый для встраивания игрока:http://www.youtube.com/watch?v=kg-z8JfOIKw

также попытался использовать JavaScript-API в элементе управления WebBrowser, но не повезло (игрок просто не отвечал на команды JavaScript, пытался даже set WebBrowser.url до рабочая демо, все, что мне удалось получить onYouTubePlayerReady() стрелять с помощью простого версия встроенного объекта )

Я думаю, что могут быть некоторые проблемы безопасности, которые я контролирую, не знаю.


обновление 2:


любимое решение, см. Мой ответ ниже.

4 ответов


похоже, что вы пытаетесь использовать Adobe Flash в качестве интерфейса; затем передайте определенные переменные обратно в C#.

примером может быть следующее:

в Flash; создать кнопку... В ActionScript:

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

тогда Visual Studio вам просто нужно добавить ссылку на COM-объект: Shockwave Flash Object

затем установите embed в true;

затем внутри Visual Studio вы сможете перейти к свойствам; найти fscommand. Этот fscommand позволит вам физически подключить значение из Flash-фильма.

AxShockwaveFlashObjects._IShockwaveFlashEvents_FSCommandEvent 

который собирает; тогда просто используйте e.command и e.arg например, чтобы собрать элемент сделать что-то.

затем добавьте это в EventHandler;

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

и бум он передает данные из Flash в Visual Studio. Нет необходимости в каких-либо сумасшедших сложных розетках.

на боковой ноте; если у вас есть Flash внутри Visual Studio, ключ должен убедитесь, что " embed имеет значение true."В котором будут храниться все пути, ссылки внутри Flash-объекта; чтобы избежать каких-либо miscalling на ошибочные пути.

я не уверен, является ли это ответом на ваш поиск; или отвечает на ваш вопрос. Но без дополнительной информации о вашей цели / ошибке. Я не могу вам помочь.

надеюсь, что это помогает. Первая часть должна фактически показать вам лучший способ внедрения Shockwave в Visual Studio.

убедитесь, что вы добавили правильный ссылка:

  1. внутри вашего проекта Open 'Обозреватель'
  2. щелкните правой кнопкой мыши 'Добавить Ссылку'
  3. на 'COM Object'

найти подходящий объект;

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 to отобразите список так, чтобы появилось видео.

на 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" установить в embed (от http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/external/ExternalInterface.html#includeExamplesSummary).

вы должны проверить, что html - > flash работает; затем C - > html; и постепенно работать до c->you-tube-component. у вас есть много потенциальных точек отказа между C и вы-tube-компонент прямо сейчас, и трудно обратиться ко всем из них одновременно.


после многих попыток и ударов по голове я нашел решение:

кажется, что Error HRESULT E_FAIL... происходит, когда вспышка не понимает запрошенный флэш-вызов. Также для работы внешнего api youtube,С. API необходимо включить:

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

как я уже сказал в вопросе, вся программа с открытым исходным кодом, поэтому вы найдете полный код в bitbucket.
любые советы, предложения или сотрудники высоко оценить.

решение:

вот полное руководство по встраиванию и взаимодействию с проигрывателем YouTube или любым другим flash-объектом.

после видео уроке , установите Flash player в FlashCall событие для функции, которая будет обрабатывать вспышка - >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# сообщении

вызов внешних функций 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;
}

добавление обработчиков событий 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");
}

использование ex:

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

функции YTplayer_CallFlash, YTplayer_FlashCall должен работать для любого flash-C# связь с незначительными настройками, такими как ' (команда.)


Это поставило меня в тупик на несколько часов.

просто добавьте enable JS в свой URL:

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

CallFunction отлично работает для меня сейчас! Также удалите неиспользуемое пространство в вызове.