Flash捕获实时视频

使用Flash Media Live Encoder ,可以非常方便的录制实时视频(live video)。Flash Media Live Encoder 的选项很多而且很细,品质控制也很不错。如何在AS3中实现这些?

参考FMS的Help,我简单的封装了这样一个类:

package com.swordair.as3
{	
	/**
	 * 
	 * @author iifksp
	 * 
	 */
	import flash.events.NetStatusEvent;
	import flash.media.Camera;
	import flash.media.Microphone;
	import flash.net.NetConnection;
	import flash.net.NetStream;

	public class LiveVideoCapturer
	{
		private var nc:NetConnection; 
		private var ns:NetStream; 
		private var cam:Camera; 
		private var mic:Microphone;

		public function LiveVideoCapturer(address:String = null)
		{
			nc = new NetConnection(); 
			nc.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus); 
			nc.connect(address);
			nc.client = this;
		}
		public function onBWDone():void{
		}
		private function onNetStatus(event:NetStatusEvent):void{ 
			trace(event.info.code); 
				if(event.info.code == "NetConnection.Connect.Success"){ 
					publishCamera();
			}
		}
		private function publishCamera():void{ 
			cam = Camera.getCamera(); 
			cam.setMode(640,480,20);
			cam.setQuality(50000,90);
			mic = Microphone.getMicrophone(); 
			ns = new NetStream(nc); 
			ns.attachCamera(cam); 
			ns.attachAudio(mic); 
			ns.publish("swordair", "live");
		}
	}
}

这个类简单的获取摄像头和麦克风,然后调用NetStream对象nsattachCameraattachAudio将其附加,最后通过对象nspublish()方法发布到Flash Media Server。

FMS会回调nsclient对象的onBWDone()方法,所以指定client并添加onBWDone()。这里将client指向类本身然后添加了一个public的onBWDone()方法供FMS调用。如果缺失onBWDone()方法,可能得到这样的错误:

Error #2044: 未处理的 AsyncErrorEvent:。 text=Error #2095: flash.net.NetConnection 无法调用回调 onBWDone。 error=ReferenceError: Error #1069: 在 flash.net.NetConnection 上找不到属性 onBWDone,且没有默认值。

整个过程就是:获取资源 - 建立连接 - 发布;ns.publish()的两个参数分别是流的标识字符串和发布方式,发布方式可以使live(默认,不录制)、record(录制,覆盖同名)和append(录制,附加同名)。

如果要回放录制的视频,对于flash的Video而言,使用相同的连接nc创建一个NetStream对象,调用其play()方法,最后使用Video对象attachNetStream()播放该流。

var nsPlayer = new NetStream(nc); 
nsPlayer.play("swordair"); 
var vidPlayer = new Video(); 
vidPlayer.attachNetStream(nsPlayer); 
addChild(vidPlayer); 

对于Flex的VideoDisplay,可以简单的设置rtmp地址:

<mx:VideoDisplay 
	id="vd1"
	source="rtmp://localhost/live/swordair" 
	width="100%" 
	height="100%" 
	autoBandWidthDetection="false" 
	live="true" 
	maintainAspectRatio="true"/>

Flex4的VideoPlayer相当出色,可惜至少在我测试的时候(FlashBuilder4 beta 2 SDK Build 4.0.0.10485),出现了严重的延迟问题。回放实时流的延迟甚至超过15秒钟,这简直无法忍受。最终放弃VideoPlayer而改用mx:VideoDisplay,延迟在2-3秒。也可能只是我的设置问题,但是VideoPlayer的相关参考还相对较少,希望Flex4正式可以解决这些可能存在的问题。

参考资料

Adobe Flash Media Server 3.5 - Capturing live video