<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" height="350" width="350" creationComplete="init()">  
<mx:Script>  
<![CDATA[
import mx.utils.URLUtil;  
//预定义声明  
import mx.controls.Alert;  
import mx.events.SliderEvent;  
    
//创建一个基本的网络连接对象  
private var vi:Video;
private var cam:Camera;//定义一个摄像头
private var inNs:NetStream; //流
private var outNs:NetStream; 
private var nc:NetConnection;  //连接
private var mic:Microphone; //定义一个麦克风
 
private var _duration:Number;//视频播放时间
private var playPosition:Number; //定义播放进度位置
private var soundPosition:Number;//定义声音大小控制条的位置
private var flag:Boolean = false;
private var lastVideoName:String = ""; //视频录制后保存的名字
private var _url:String = "rtmp://192.168.10.106/flex"; public function init():void{
setupCamera();//初始化摄像头信息
}
//开始录制按扭点击
public function clickConnect():void{

nc = new NetConnection();
nc.addEventListener(NetStatusEvent.NET_STATUS,nsHandler);
nc.connect(_url,true); //连接red5服务器
}
 
public function nsHandler(evt:NetStatusEvent):void{
if (evt.info.code == "NetConnection.Connect.Success"){ //如果连接成功
Alert.show("连接成功");
playClick();
}else{
Alert.show("连接失败");
Alert.show(evt.info.application);
}
}
/* 
nc = new NetConnection();
nc.objectEncoding = ObjectEncoding.AMF0;
nc.client = this;
nc.connect("rtmp://服务器名/应用名",true);
ns.publish(stream名,"live");
nc.call("startRecord",new Responder(getInfor,onState),文件名,stream名);
function getInfor(reobj:Object):void {
trace("Server returning Infor: "+reobj);
}
function onState(err:Object):void {
trace("Connection result error: "+err);

*/
//开始录制
public function playClick():void{ 

if(vi != null){
vi.clear();
vdisplay.removeChild(vi);
vi = new Video();
vi.width = 350;
vi.height = 240;
vi.attachCamera(cam);
vdisplay.addChild(vi);
}
outNs = new NetStream(nc); 
outNs.attachCamera(cam); //把摄像头存入outNs
outNs.attachAudio(mic); //把麦克风存入outNs
lastVideoName = "red5RecordDemo_" + Math.random()+getTimer();
// Alert.show(lastVideoName);
outNs.publish(lastVideoName,"append");
startRec.enabled = false;
stopRec.enabled = true; 
Alert.show("开始录像");
}

//停止录制
public function stopClick():void{
//关闭ns与red5的连接
outNs.close(); 
vi.clear();
vdisplay.removeChild(vi);
//锁定开始按键使其生效
startRec.enabled = true;
//锁定停止按键使其失效
stopRec.enabled = false;
ExternalInterface.call("getFile",lastVideoName);
}

//录制完以后播放
public function playLastVideo():void{
if(nc!=null){
addEventListener(Event.ENTER_FRAME,onEnterFrame);
inNs = new NetStream(nc);

//定义onMetaData,获取视频相关数据
var customClient:Object = new Object();
customClient.onMetaData = function(metadata:Object):void{
_duration = metadata.duration; //获取视频持续时间
t_sh.maximum = _duration;      //播放进度条的最大值
}
//每次new customClient的时候就调用回调函数(个人理解)
//指定在其上调用回调方法的对象。 默认对象为 this,将创建 NetStream 对象。如果将 client 属性设置为另一个对象,则将对该对象调用回调方法。 
inNs.client = customClient;  



vi = new Video();
vi.width = 320;
vi.height = 240;
vi.attachNetStream(inNs);
vdisplay.addChild(vi); 
inNs.play(lastVideoName+".flv");
addEventListener(Event.ENTER_FRAME,onEnterFrame); 
}
}

//初始化摄像头
public function setupCamera():void{
//启动摄像头
cam = Camera.getCamera(); 
if(cam != null){
cam.addEventListener(StatusEvent.STATUS,onStatusHandler);
cam.setMode(350,240,30);
cam.setQuality(0,70);//设置清晰度
vi = new Video();
vi.width = 350;
vi.height = 240;
vi.attachCamera(cam);
vdisplay.addChild(vi);
}
mic = Microphone.getMicrophone();
if(mic != null){
mic.setSilenceLevel(0,-1); //设置麦克风保持活动状态并持续接收集音频数据
mic.gain = 80; //设置麦克风声音大小
}
}

private function onStatusHandler(event:StatusEvent):void{
if(!cam.muted){ //判断摄像头存不存在
startRec.enabled = true;
}else{
Alert.show("错误:无法链接到活动摄像头!");
}
cam.removeEventListener(StatusEvent.STATUS,onStatusHandler);
}
//拉动进度条
public function thumbPress(event:SliderEvent):void{
inNs.togglePause();  //暂停或恢复流的回放
removeEventListener(Event.ENTER_FRAME,onEnterFrame);
}
//进度条变化
private function thumbChanges(event:SliderEvent):void{
playPosition = t_sh.value;//当前播放视频进度的位置=当前播放进度条的位置
inNs.seek(playPosition); //搜索流的指定位置
addEventListener(Event.ENTER_FRAME,onEnterFrame);
}

private function thumbRelease(event:SliderEvent):void{//释放mouse后执行
inNs.seek(playPosition); //查找当前进度条位置
inNs.togglePause();
addEventListener(Event.ENTER_FRAME,onEnterFrame);
}

public function onEnterFrame(event:Event):void{
if(_duration > 0 && inNs.time > 0){ //如果视频时间和正在播放视频的时间大于0
t_sh.value =inNs.time;   //播放头的位置
lbtime.text = formatTimes(inNs.time) + " / "+ formatTimes(_duration);

if(formatTimes(inNs.time)==formatTimes(_duration)){//如果播放完毕,则关毕流,初始化摆放时间的label
if(flag==true){//如果是加载,就不执行 ||false代表是加载,true代表是播放结束
removeEventListener(Event.ENTER_FRAME,onEnterFrame);
inNs.close();
lbtime.text = "0:00 / "+ formatTimes(_duration);
}
setTimeout(function():void{flag = true;},1000);
}
}

//时间格式操作
private function formatTimes(value:int):String{
var result:String = (value % 60).toString();
if(result.length == 1) {
result = Math.floor(value / 60).toString() + ":0" + result;
} else {
result = Math.floor(value / 60).toString() + ":" + result;
}
return result;


//声音音量控制
private function sound_thumbChanges(event:SliderEvent):void{
soundPosition = th_sound.value;
}

private function sound_thumbRelease(event:SliderEvent):void{
vdisplay.volume = soundPosition;
}

]]>
</mx:Script> <mx:VideoDisplay x="0" y="0" width="350" height="240"  id="vdisplay" backgroundColor="#F7F1F1"/>
<mx:Button x="10" y="250" label="开始录制" id="startRec" click="clickConnect()" enabled="true" />
<mx:Button x="10" y="280" label="停止录制" width="70" id="stopRec" click="stopClick()" enabled="true" />
<mx:Button x="253" y="268" label="播放" click="playLastVideo()"/>
<mx:Label x="237" y="242" text="0:00/0:00" width="89" textAlign="center" height="18" id="lbtime"/>
<mx:Label x="187" y="270" text="sound" height="20" width="44" textAlign="center"/>
<mx:HSlider x="98" y="248" width="143" id="t_sh" thumbPress="thumbPress(event)" thumbRelease="thumbRelease(event)" change="thumbChanges(event)"/>
<mx:HSlider x="98" y="272" width="91" id="th_sound" minimum="0" maximum="1" value="{vdisplay.volume}" change="sound_thumbChanges(event)" thumbRelease="sound_thumbRelease(event)"/>
</mx:Application>红色这段代码我不理解,为什么他这里定义的一个_duration = metadata.duration;这样能给_duration赋上视频时间值,还有这个回调函数
customClient.onMetaData = function(metadata:Object):void{
_duration = metadata.duration; //获取视频持续时间
t_sh.maximum = _duration;      //播放进度条的最大值
}
是什么时候调用的,这段代码理解不了,请高手指点!

解决方案 »

  1.   

    看来LZ是个高手阿 .正在初学flex/.
      

  2.   

    我也是才入门,不是高手,找高手指点呢
    貌似flex懂的人不多哦
      

  3.   

    _duration = metadata.duration;
    是为了显示视频的持续时间,没有的话程序拖动进度条的时候无法判断哪里是头。
    你看下面的代码
    t_sh.maximum = _duration; 就表明了_duration的作用。
    至于什么时候调用的,
     每当function playLastVideo():调用时,那么你说的回调函数就应该是什么时候被调用的。
    我理解是这样的哦