zoukankan      html  css  js  c++  java
  • 利用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.cspublic class
     MyVideoApp : ApplicationAdapter
    {
        
    public
    override bool AppStart(FluorineFx.Messaging.Api.IScope application)
        {
            RegisterStreamPublishSecurity(
    new
    PublishSecurity());
            
    return
     base.AppStart(application);
        }
    }
    PublishSecurity.cs
    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
    ;
    } IConnection connection = FluorineContext.Current.Connection; if (!
    "authenticated"
    .Equals(connection.GetAttribute(
    "UserType"
    )))
                {
                   
    // User was not authenticatedreturnfalse
    ;
                }
                if (!name.StartsWith(
    "testing"
    ))
                    
    returnfalse
    ;
                else
                    
    returntrue
    ;
            }
        }
    }
    

    客户端代码:

    <?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>
  • 相关阅读:
    设计模式大赛 -- 大话设计模式
    访问者模式 -- 大话设计模式
    puts的用处
    scanf的使用
    iOS,手势识别简单使用
    iOS,多媒体,地图相关
    iOS,文本输入,键盘相关
    iOS,XMPP本地环境搭建和框架使用
    iOS,自动布局autoresizing和auto layout,VFL语言
    iOS,图片处理
  • 原文地址:https://www.cnblogs.com/CoderWayne/p/1777904.html
Copyright © 2011-2022 走看看