質問

I am using Air to stream webcame to FMS (Flash Media Server), as you know this has no problem on desktop, but can i stream from mobiles (Android, iOS)? here is my code:

var nc:NetConnection = new NetConnection();
var bandwidth:int = 0; 
var quality:int = 50;
var camera:Camera = Camera.getCamera();

camera.setQuality(bandwidth, quality);
camera.setMode(430,320,15, true);

var video:Video = new Video();
video.attachCamera(camera);
addChild(video);
video.width = 430;
video.height = 320;


nc.connect("rtmp://***");
nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);

function netStatusHandler(event:NetStatusEvent):void{
    if (event.info.code == "NetConnection.Connect.Success")
    {
    label10.text = 'Connected';
    var ns:NetStream = new NetStream(nc);
    ns.attachCamera(camera);
    ns.publish("NewStream1", "live");
    }

}

i don't have a FMS to test on it, have anyone try this or at aleast is there a way to test this without buying FMS?

役に立ちましたか?

解決

I have done streaming from mobile AIR applications via Wowza media server. The standard streaming code should work, just note that H.264 video isn't supported in iOS via Flash.

他のヒント

Yes, you can!

I have concentrated on this topic some time, and now i can publish stream to streaming media server and subscribe it.My streaming media server is Red5, it is free and greate, it you try to use it you will know.Red5 was writen by Java but it was writen for Flash, and its client uses Flash or Flex recommended.

As you know NetConnection and NetStream from ActionScript are greate, and you can use them to publish stream to Red5 or FMS, you can also use them to subscribe stream.

If you want to write mobile application with ActionScript, you can refer to this link. http://help.adobe.com/en_US/flex/mobileapps/index.html Firstly you should create a Flex mobile application, in its first view you can paste the code below.And when you are able to publish stream, you will know how to subscribe it.

This is my main code, in this code i used adobe's stratus service to test my project. I'm sorry to be able to help you so much:

    import mx.core.UIComponent;
        import mx.events.FlexEvent;

        import org.osmf.elements.VideoElement;

        import spark.components.VideoDisplay;

        private var netConnection:NetConnection = null;
        private var netStream:NetStream = null;
        private var netGroup:NetGroup = null;
        private var video:Video = null;
        private var sequenceNumber:uint = 0;

        //Stratus 服务器地址
        private const SERVER:String = "rtmfp://stratus.adobe.com/";
        //开发者Key,请使用你申请的Key
        private const DEVKEY:String = "1710124cbf69e3f25b780c13-d6cbf2cb35a1";
        //组的名字,名字要唯一
        private const GROUP_PREFIX:String = "www.flextheworld.com.stratus2.demo";

        //[Bindable]的作用是进行绑定,如果定义的值改变那么所有被它影响的引用都将改变其值,会有事件发送以获得引用的改变
        [Bindable] 
        private var connected:Boolean = false;
        [Bindable] 
        private var joinedGroup:Boolean = false;

        private var cam:Camera;

        protected function creationCompleteHandler(event:FlexEvent):void
        {
            groupName.text = "channel" + (int(Math.random() * 899) + 101);
            cam = Camera.getCamera();
            if(cam){
                cam.setMode(width, width, 25);
                cam.setQuality(144000,85);
                cam.setKeyFrameInterval(5);
                cam.setLoopback    (false);    
                var video: Video = new Video(cam.width, cam.height);
                ui.width = video.width;
                ui.height = video.height;
                /*ui.addChild(video);*/
                video.attachCamera(cam);


            }
        }


        /**
         * NetStream和Group的事件响应
         * */
        private function netStatusHandler(e:NetStatusEvent):void
        {
            switch(e.info.code)
            {
                case "NetConnection.Connect.Success": //与Stratus链接成功,开始创建/进入组
                    onConnect();
                    break;

                case "NetConnection.Connect.Closed":
                case "NetConnection.Connect.Failed":
                case "NetConnection.Connect.Rejected":
                case "NetConnection.Connect.AppShutdown":
                case "NetConnection.Connect.InvalidApp":    
                    onDisconnect();
                    break;

                case "NetStream.Connect.Success": //Net Stream 链接成功
                    onNetStreamConnect();
                    break;

                case "NetStream.Connect.Rejected": // e.info.stream
                case "NetStream.Connect.Failed": // e.info.stream
                    doDisconnect();
                    break;

                case "NetGroup.Connect.Success": // e.info.group
                    onNetGroupConnect();
                    break;

                case "NetGroup.Connect.Rejected": // e.info.group
                case "NetGroup.Connect.Failed": // e.info.group
                    doDisconnect();
                    break;

                case "NetGroup.Posting.Notify": // 收到信息
                case "NetStream.MulticastStream.Reset":
                case "NetStream.Buffer.Full":
                    break;

                case "NetGroup.SendTo.Notify": // e.info.message, e.info.from, e.info.fromLocal
                case "NetGroup.LocalCoverage.Notify": //
                case "NetGroup.Neighbor.Connect": // e.info.neighbor
                case "NetGroup.Neighbor.Disconnect": // e.info.neighbor
                case "NetGroup.MulticastStream.PublishNotify": // e.info.name
                case "NetGroup.MulticastStream.UnpublishNotify": // e.info.name
                case "NetGroup.Replication.Fetch.SendNotify": // e.info.index
                case "NetGroup.Replication.Fetch.Failed": // e.info.index
                case "NetGroup.Replication.Fetch.Result": // e.info.index, e.info.object
                case "NetGroup.Replication.Request": // e.info.index, e.info.requestID
                default:
                    break;
            }
        }

        private function doConnect():void
        {
            if(joinedGroup){
                doDisconnect()
                return;
            }

            startBtn.label = "链 接 中";
            startBtn.enabled = false;
            //updateStatus("Connecting to \"" + SERVER + "\"");
            netConnection = new NetConnection();
            //传入的两个参数分别为事件类型和监听器,这个监听器接收第一个参数定义的事件类型且不能有返回值。
            netConnection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
            netConnection.connect(SERVER + DEVKEY);
        }

        /**
         * 与Stratus 链接成功后触发
         * */
        private function onConnect():void
        {
            //GroupSpecifier 类用于构造可传递给 NetStream 和 NetGroup 构造函数的不透明的 groupspec 字符串
            var groupSpecifier:GroupSpecifier;

            //updateStatus("与Stratus链接成功\n");
            connected = true;

            //定义组,根据用户输入的groupName构造了唯一的GroupSpecifier
            groupSpecifier = new GroupSpecifier(GROUP_PREFIX + groupName.text);
            //允许多播
            groupSpecifier.multicastEnabled = true;
            //允许发送数据
            groupSpecifier.postingEnabled = true;
            //打开频道,只有打开服务器通道,服务器才能将支持功能提供给组成员。
            groupSpecifier.serverChannelEnabled = true;

            //创建netStream与用户组的链接,我们用他来发送视频和音频流
            /*
            * groupspecWithAuthorizations()返回可传递给 NetStream 和 NetGroup 构造函数的不透明的 groupspec 字符串,包括授权。
            * 在对等多播组中发布或播放,需指定 groupspec字符串
            */
            netStream = new NetStream(netConnection, groupSpecifier.groupspecWithAuthorizations());
            netStream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);

            //加入用户组 
            //NetGroup 类的实例表示 RTMFP组中的成员资格,此类可以监视服务质量,发布,直接路由(发送),对象复制
            netGroup = new NetGroup(netConnection, groupSpecifier.groupspecWithAuthorizations());
            netGroup.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);

            //updateStatus("加入用户组 \"" + groupSpecifier.groupspecWithAuthorizations() + "\"\n");
        }

        /**
         *
         * NetStraeam链接到用户组后触发
         * */
        private function onNetStreamConnect():void
        {
            //加载话筒
            netStream.client = this;                
            var mic:Microphone = Microphone.getMicrophone();
            if(mic)
            {
                mic.codec = SoundCodec.SPEEX;
                mic.setSilenceLevel(0);

                netStream.attachAudio(mic);

                    //updateStatus("话筒设置完毕\n");
            }
            //加载视频,并发布视频和话筒
            publishVideo();

        }
        /**
         * 发布视听流
         * */
        private function publishVideo():void{
            netStream.attachCamera(cam)
            //发布名字为stream 的流。这个部分这里就不讲解了,在原来的p2p教程里有详细说明 
            netStream.publish("stream");

        }

        private function onNetGroupConnect():void
        {
            startBtn.label = "直 播 中";
            startBtn.enabled = true;
            //加入用户组成功
            joinedGroup = true;
        }

        /**
         * 断开链接
         * */
        private function doDisconnect():void
        {
            if(netConnection){
                startBtn.label = "停 止 中";
                startBtn.enabled = false;
                netConnection.close();
            }

        }

        /**
         * netconnection断开后执行
         * */
        private function onDisconnect():void
        {
            startBtn.label = "开始 直 播";
            startBtn.enabled = true;
            netConnection = null;
            netStream = null;
            netGroup = null;
            connected = false;
            joinedGroup = false;
        }

    ]]>
</fx:Script>


<s:VGroup paddingTop="10" paddingLeft="10" paddingRight="10" id="cameraDisplay" width="100%"  >
    <s:Label fontSize="30" text="直播频道" />
    <s:TextInput id="groupName" width="100%" />
    <mx:UIComponent id="ui"  />
    <s:Group width="100%">
        <s:layout>
            <s:HorizontalLayout horizontalAlign="center" paddingTop="20" />
        </s:layout>
        <s:Button id="startBtn" fontSize="60" chromeColor="#9F2A2F"  label="开 始 直 播" click="doConnect()" />
    </s:Group>

</s:VGroup>
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top