利用FluorineFX录制音频与视频
要做一个完整的录制程序,处理RPC请求的类不仅要继承ApplicationAdapter,还要继承IStreamService接口,该接口定义了play(),pause(),publish(),createStream()等一系列方法来完善程序
关于安全性,可以自定义一个实现FluorineFx.Messaging.Api.Stream.IStreamPublishSecurity接口的类,并定义一个IsPublishAllowed()方法,在该方法里可以判断发布流的类型、流的名称以及对发布流进行授权等相关操作。然后重写applicationAdapter类的appStart()方法,并注册该安全策略:RegisterStreamPublishSecurity(new PublishSecurity());
录制的文件保存在apps/MyRoom/streams下
录制时通过netStream.publish(name,type)来实现的,参数说明如下:
name:String (default = null) — 标识该流的字符串。 如果传递 false,则发布操作将停止。 订阅此流的客户端必须在调用 NetStream.play() 时仍然传递此名称。 不必在流名称中包含文件扩展名
type:String (default = null) — 指定如何发布该流的字符串。 有效值为“record”、“append”和“live”。 默认值为“live”
如果传递“record”,则 Flash Player 将发布并录制实时数据,同时将录制的数据保存到名称与传递给 name 参数的值相匹配的 FLV 文件中。 该文件保存在服务器上服务器应用程序所在目录的子目录中。 如果该文件已经存在,则覆盖该文件。
如果传递“append”,则 Flash Player 将发布并录制实时数据,同时将录制的数据追加到名称与传递给 name 参数的值相匹配的 FLV 文件中,该文件保存在服务器上服务器应用程序所在目录的子目录中。 如果未找到名称与 name 参数相匹配的文件,则创建一个。
如果省略此参数或传递“live”,则 Flash Player 将发布实时数据而不进行录制。 如果存在名称与传递给 name 参数的值相匹配的文件,则删除它。
服务器端代码:
MyVideoApp : ApplicationAdapter {public
override bool AppStart(FluorineFx.Messaging.Api.IScope application) { RegisterStreamPublishSecurity(new
PublishSecurity());return
base.AppStart(application); } }
using System; using System.Collections.Generic; using System.Text; using FluorineFx.Messaging.Api.Stream; using FluorineFx.Messaging.Api; using FluorineFx.Context; namespace ServiceLibrary5 {public class
PublishSecurity : IStreamPublishSecurity {public
bool IsPublishAllowed(IScope scope, string name, string mode) {//if (!"live".Equals(mode))//{// // Not a live stream// return false;//}
if (!"record"
.Equals(mode)) {//不是录制流
returnfalse
;"authenticated"
} IConnection connection = FluorineContext.Current.Connection; if (!
.Equals(connection.GetAttribute("UserType"
))) {// User was not authenticatedreturnfalse
; } if (!name.StartsWith("testing"
))returnfalse
; elsereturntrue
; } } }
客户端代码:
<?xml version="1.0"
encoding="utf-8"
?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute"
> <mx:UIComponent id="uiBox"
width="320"
height="240"
/> <mx:Label x="371"
y="222"
text="Label"
id="lblMessage"
/> <mx:Button x="371"
y="48"
label="连接服务器"
click="onConnect()"
/> <mx:Button x="371"
y="94"
label="开始录制"
click="onStartRecord()"
/> <mx:Button x="371"
y="136"
label="停止录制"
click="onStopRecord()"
/> <mx:Button x="371"
y="180"
label="播放视频"
click="onPlayRecord()"
/> <mx:Script> <![CDATA[private var
nc:NetConnection;private function
onConnect():void
{ nc =new
NetConnection(); nc.addEventListener(NetStatusEvent.NET_STATUS,onNetStatus); nc.connect("rtmp://localhost:8323/MyVideoRoom"
); nc.client = this; }private function
onNetStatus(event:NetStatusEvent):void
{if
(event.info.code =="NetConnection.Connect.Success"
) {this
.lblMessage.text ="连接服务器成功"
; } else {this
.lblMessage.text ="连接服务器失败"
; } }private function
onStartRecord():void
{if
(nc) {var
ns:NetStream =new
NetStream(nc);var
mic:Microphone = Microphone.getMicrophone();var
camera:Camera = Camera.getCamera(); ns.attachAudio(mic); ns.attachCamera(camera); ns.publish("demo001"
,"record"
);this
.lblMessage.text ="录制中……"
; } }private function
onStopRecord():void
{if
(nc) { nc.close();this
.lblMessage.text ="已停止录制"
; } }private function
onPlayRecord():void
{ nc =new
NetConnection(); nc.addEventListener(NetStatusEvent.NET_STATUS,onNetStatus2); nc.connect("rtmp://localhost:8323/MyVideoRoom"
); }private function
onNetStatus2(event:NetStatusEvent):void
{if
(event.info.code =="NetConnection.Connect.Success"
) {var
ns:NetStream =new
NetStream(nc);var
video:Video =new
Video(); video.attachNetStream(ns);this
.uiBox.addChild(video); ns.play("demo001"
); } } ]]> </mx:Script> </mx:Application>