• Flash/Flex学习笔记(12):FMS 3.5之如何做视频实时直播


    硬件条件:一个摄像头 + 一台FMS服务器即可

    原理:摄像头实时采集视频源,然后推送到FMS服务器,其它客户从FMS上获取视频流。

    需要做二个fla,一个用于向FMS服务端推送视频源(即发送端),一个用于从FMS服务器获取并播放视频(即接收端)

    Server.fla关键代码:

    var cam:Camera;
    var vod:Video;
    var intervalId:uint;
    var intelvalTimes:uint=0;
    var isWorked=false;
    var nc:NetConnection;
    var ns:NetStream;
    
    btnPublish.addEventListener(MouseEvent.CLICK,btnPublishClick);
    lblMsg.text = "连接好摄像头后,\n点击下面的按钮"
    
    //摄像头有活动时,被触发
    function camActivityHandler(e:ActivityEvent) {
    	trace(e);
    	if (!isWorked) {
    		intervalId=setInterval(checkCallBack,100);
    	}
    }
    
    function checkCallBack():void {
    	intelvalTimes+=1;
    	trace(intelvalTimes);
    	if (cam.currentFPS>0) {
    		lblMsg.text="摄像头工作正常!";
    		isWorked=true;
    		clearInterval(intervalId);
    		ns.publish("myCamera", "live");
    		//同时处理本地播放
    		vod = new Video();
    		vod.attachCamera(cam);
    		vod.height=cam.height;
    		vod.width=cam.width;
    		vod.x = 45;
    		vod.y = 15;
    		addChild(vod);
    	} else {
    		if (intelvalTimes>=10) {//持续检测2秒,仍然无图象的话,认为"设备无法使用(占用中)"
    			lblMsg.text="设备无法使用(有可能被占用)";
    			clearInterval(intervalId);
    		}
    	}
    }
    
    //用户选择"同意"或"不允许"使用摄像头时触发
    function statusHandler(e:StatusEvent) {
    	trace(e);
    	if (e.code=="Camera.Muted") {
    		lblMsg.text="您不允许使用摄像头!";
    	} else if (e.code == "Camera.Unmuted") {
    		lblMsg.text="摄像头视频获取中...";
    	}
    }
    
    //推送按钮点击事件
    function btnPublishClick(e:MouseEvent) {
    	nc = new NetConnection();
    	nc.addEventListener(NetStatusEvent.NET_STATUS, NetStatusHandler);
    	nc.connect("rtmp://fms服务器ip地址/camlive");
    }
    
    //连接状态处理代码
    function NetStatusHandler(event:NetStatusEvent):void {
    	trace(event.info.code);
    	if (event.info.code=="NetConnection.Connect.Success") {		
    		cam=Camera.getCamera();
    		if (cam==null) {
    			this.lblMsg.text="未安装摄像头!";
    			return;
    		}
    		cam.addEventListener(StatusEvent.STATUS, statusHandler);
    		cam.addEventListener(ActivityEvent.ACTIVITY,camActivityHandler);
    		ns=new NetStream(nc);
    		ns.attachCamera(cam);
    	}
    }
    

    Client.fla关键代码:

    var nc:NetConnection;
    var ns:NetStream;
    var vod:Video;
    
    btnReceive.addEventListener(MouseEvent.CLICK,function(){
    	nc = new NetConnection();
    	nc.addEventListener(NetStatusEvent.NET_STATUS, NetStatusHandler);
    	nc.connect("rtmp://fms服务器ip地址/camlive");
    })
    
    //连接状态处理代码
    function NetStatusHandler(event:NetStatusEvent):void {
    	trace(event.info.code);
    	if (event.info.code=="NetConnection.Connect.Success") {
    		lblMsg.text = "正在获取视频..."
    		ns=new NetStream(nc);
    		ns.addEventListener(NetStatusEvent.NET_STATUS,nsNetStatusHandler);
    		ns.play("myCamera");
    		vod = new Video();
    		vod.x=45;
    		vod.y=15;
    		vod.height=120;
    		vod.width=160;
    		vod.attachNetStream(ns);
    		addChild(vod);		
    	}
    }
    
    function nsNetStatusHandler(e:NetStatusEvent){
    	trace(e.info.code);
    }
    

    在线演示:

    推送端
    接收端

    作者:菩提树下的杨过
    出处:http://yjmyzz.cnblogs.com
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    Leetcode 第 210 场周赛
    Leetcode 834. 树中距离之和
    Leetcode 第36场双周赛
    力扣 第 208 场周赛
    cf 665 DMaximum Distributed Tree
    Codeforces Round #672 (Div. 2) A~D
    Educational Codeforces Round 95 (Rated for Div. 2) A~D
    CCF CSP 201612-3 权限查询
    Codeforces Round #669 (Div. 2) A~C
    201703-4 地铁修建
  • 原文地址:https://www.cnblogs.com/yjmyzz/p/1686274.html
Copyright © 2020-2023  润新知