首先提出需求吧
现在需求很简单
2个用户登录在同一页面,然后可以视频聊天(语音也可以)。
界面比较简单:就是2个视频框,一个显示自己,另外一个显示正在和自己聊天的对象的视频。
需要的工具有VS2008 FMS FLASH CS4 IIS
需要的知识点有 JS和AS的交互, FMS的直播和发布,C#和JS的交互。
ASP.NET 有2个页面 一个是登录页面,一个是视频页面。登录页面用来记录客户的APPLICATION。视频页面是2个FLASH。一个是自己的视频,另外一个是别人的视频。
FLASH需要准备2个 一个是用来发布视频的和观看自己的视频的。另外一个是用来播放别人视频的。
思路是:一个客户A 登录,服务器将记录下APLICATION(IP,NAME) ,其中name是客户A发布的视频的名字 (注意这里不能用SESSIOn)。然后另外一个客户B登录上来同样记录之,并且这个时候服务器端将客户A 的name通过JS传递给AS,这个时候FLASH选择播放客户A的视频流。
需要注意的地方:JS调用AS的函数的时候,利用 ExternalInterface.addCallback,注意自己的顺序,以及它们的记载顺序。具体问题在代码中标注了。
存在BUG是 多个用户的时候可能 A看到 B,B看到C,C看到A 。2个人视频的话没问题。
主要代码部分如下
c#页面
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>实时视频</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<table style="width: 100%; height: 314px;">
<tr>
<td>
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,0,0" width="550" height="400" id="MyVideo" align="middle">
<param name="allowScriptAccess" value="always" />
<param name="allowFullScreen" value="false" />
<param name="movie" value="MyVideo.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /> <embed src="MyVideo.swf" quality="high" bgcolor="#ffffff" width="550" height="400" name="MyVideo" align="middle" allowScriptAccess="sameDomain" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer_cn" />
</object>
</td>
<td>
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,0,0" width="550" height="400" id="YouVideo" align="middle">
<param name="allowScriptAccess" value="always" />
<param name="allowFullScreen" value="false" />
<param name="movie" value="YouVideo.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#ffffff" /> <embed src="YourVideo.swf" quality="high" bgcolor="#ffffff" width="550" height="400" name="YouVideo" align="middle" allowScriptAccess="sameDomain" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer_cn" />
</object>
</td>
</tr>
<tr><td>
<input id="publish" type="button" value="发布" οnclick="publishvideo();"/>
</td>
<td>
<input id="play" type="button" value="开始" οnclick="palyvideo();"/>
</td></tr>
</table>
<asp:Literal runat="server" ID="lt_Js"></asp:Literal>
</div>
</form>
</body>
</html>
C#后台
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string ip = Request.ServerVariables["REMOTE_HOST"].ToString();
string name = Application[ip].ToString();
string js1 = "<script language=/"javascript/" type=/"text/javascript/"> function publishvideo(){document[/"MyVideo/"].MyName(/"" + name + "/");}</script>";
// string js1 = "<script language=/"javascript/" type=/"text/javascript/"> function publishvideo(){document[/"MyVideo/"].MyName(/"" + name + "/");alert(/"" + name + "/");}</script>";//这里加入ALERT后有的时候可以 有的时候不可以
//string js1 = "<script language=/"javascript/" type=/"text/javascript/">setTimeout(function(){document[/"MyVideo/"].MyName(/"" + name + "/");}, 20000);alert(" + name + ");</script>";
lt_Js.Text = js1;
//随机获取另外一个IP地址进行聊天
if (Application.Count > 0)//session 不得行
{
//test
Response.Write(Application.Count);
for (int i = 0; i < Application.Count; i++)
{
Response.Write(Application[i].ToString());
}
Random rm = new Random(0);
int random = rm.Next(Application.Count);
for (int i = 0; i < 1000; i++)
{
if (Application[random].ToString() == name)
{
random = rm.Next(Application.Count);
}
else
{
break;
}
}
string othername = Application[random].ToString();
//输出到JS文件
string js2 = "<script language=/"javascript/" type=/"text/javascript/">function palyvideo(){document[/"YouVideo/"].OtherPeople(/"" + othername + "/");}</script>";
// string js2 = "<script language=/"javascript/" type=/"text/javascript/">function palyvideo(){document[/"YouVideo/"].OtherPeople(/"" + othername + "/");alert(/"" + othername + "/");}</script>";
// string js2 = "<script language=/"javascript/" type=/"text/javascript/">setTimeout(function(){document[/"YouVideo/"].OtherPeople(/"" + othername + "/");}, 20000);alert(/""+othername+"/");</script>";
// string js2 = "<script language=/"javascript/" type=/"text/javascript/"> function OtherPeople(othername){ othername=/"" + othername + "/";} </script>"; //这个是从AS得到值
lt_Js.Text += js2;
}
else
{
//没有其他用户 只有等待了
}
}
}
接受端FLASH的代码如下
//实现从另外一个客户端得到视频和声音 其实就是读取 另一个客户端的实时视频流
package
{
import flash.net.*;
import flash.events.*;
import flash.display.*;
import flash.media.*;
import flash.external.ExternalInterface;
public class YouVideo extends Sprite
{
private var video:Video;
private var nc:NetConnection;
private var ns:NetStream;
private var otherName:String;
public function YouVideo():void
{
nc = new NetConnection();
// nc.addEventListener(NetStatusEvent.NET_STATUS,onNetStatusHandler);//这里不用监听了
//trace(111);
ExternalInterface.addCallback("OtherPeople",OtherPeople);//这个加载顺序有点问题,应该是FLASH加载完这个
//并将之转换成html中的SWF的函数后,JS才可以调用,就是可能发生 JS错误 未找到对象。
//在JS文件中选择ALERT后 刷新AS可以读取到JS传过来的值
//这里有另外一种变通的办法 加按钮,让客户选择发布视频。这样的话,就可以了。
//具体实现办法首先 ExternalInterface.addCallback在构造函数中加载。
//其次添加一个按钮在HTML页面中,让用户选择视频,这个时候触发addCallback中的注册的AS方法。
//最后在AS的方法中添加监听,一旦检测到就发布视频或者播放视频。
//这里我们采用这种方法
//还有一种办法 彻底放弃和JS的交互 选用XML来进行交互。
}
//调用外部的内容 只有 JS才能执行这个函数 也就是HTML中的按钮决定了播放和发布视频流
function OtherPeople(param)
{
otherName=param;
nc.connect("rtmp://192.168.13.49/LiveStreams");
nc.addEventListener(NetStatusEvent.NET_STATUS,onNetStatusHandler);
}
private function onNetStatusHandler(evt:NetStatusEvent):void
{
trace(evt.info.code);
if(evt.info.code=="NetConnection.Connect.Success")
{
PlayNetStream()
}
}
private function PlayNetStream():void
{
ns=new NetStream(nc);
ns.addEventListener(NetStatusEvent.NET_STATUS,onNetStatusHandler);
ns.client=new CustomClient();
video=new Video();
video.attachNetStream(ns);
trace(ns);
ns.play(otherName);
addChild(video);
}
}
}
发布端FLASH的AS代码
//主要实现 显示自己的视频和声音
//另外发布自己的视频流
package
{
import flash.net.*;
import flash.events.*;
import flash.media.*;
import flash.display.*;
import fl.controls.*;
import flash.external.*;
public class MyVideo extends Sprite
{
private var nc:NetConnection;
private var ns:NetStream;
private var video:Video;
private var cam:Camera;
private var mic:Microphone;
private var myName:String;
public function MyVideo():void
{
ExternalInterface.addCallback("MyName",MyName);
video=new Video();
cam = Camera.getCamera();
mic = Microphone.getMicrophone();
if(cam==null)
{
trace("没检测到视频摄像头");
}
else
{
video.attachCamera(cam);
}
addChild(video);
}
//外部调用的内容
function MyName(param)
{
myName=param;
//这里发布自己的视频流
nc = new NetConnection();
nc.connect("rtmp://192.168.13.49/LiveStreams");
nc.addEventListener(NetStatusEvent.NET_STATUS,onNetStatusHandler);
}
private function onNetStatusHandler(evt:NetStatusEvent):void
{
// trace(evt.info.code);
//myName=evt.info.code;
if(evt.info.code=="NetConnection.Connect.Success")
{
PublishNetStream();
}
}
public function PublishNetStream():void
{
ns=new NetStream(nc);
ns.addEventListener(NetStatusEvent.NET_STATUS,onNetStatusHandler);
ns.client=new CustomClient();
ns.attachCamera(cam);
ns.attachAudio(mic);
ns.publish(myName,"live");//这个要需动态的定义自己 从JS得到
}
}
}