我的目标是制作一个可以通过全球媒体密钥控制的开源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.command
和e.arg
例如让收集的项目做点什么。
然后将其添加到EventHandler;
lbl_Result.Text="The "+e.args.ToString()+" "+e.command.ToString()+" was clicked";
和繁荣,它将其数据从Flash传输到Visual Studio。无需任何疯狂的困难插座。
在旁注;如果您在Visual Studio内有Flash,那么关键是要确保其"嵌入为true"。这将保存闪光灯对象中的所有路径参考;为了避免任何错误的路径。
我不确定这是您寻求的答案;或回答您的问题。但是没有更多有关您的目标/错误的详细信息。我无法帮助您。
希望这会有所帮助。第一部分实际上应该向您展示将冲击波嵌入到Visual Studio中的最佳方法。
确保添加正确的参考:
- 在您的项目中,打开'解决方案资源管理器'
- 右键单击'添加参考'
- 转到'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_CallFlash
,YTplayer_FlashCall
应适用于任何 flash-c#通信,诸如YTplayer_CallFlash
的S switch(命令)。
这使我陷入困境。
只需在您的URL中添加启用JS:
http://www.youtube.com/v/9bzkp7q19f0?version=3 &amp; enablejsapi = 1
呼叫功能现在对我来说很好!还要删除呼叫中的未支付的空间。