Red5でチャットや動画ライブストリミング配信とかやってみたよ
Red5のサンプルがいくつか更新されていたのでちょこっと勉強がてら遊んでみました。
作ったもの
簡単なチャットシステム
簡単なドラッグ共有
簡単なライブ配信システム
#録画はソース部分の"live"=>"record"でOK
参考にさせていただいたページ
- Class NetStream
- Adobe Flash Media Server 3
- Flexで音声保存(RED5)
- H.264 動画を Flash Media Server 3 より Streaming 再生
こちらの本にRed5やらAMFやら旬な話題が載ってます。
The Essential Guide to Open Source Flash Development
- 作者: Chris Allen,Wade Arnold,Aral Balkan,Nicolas Cannasse,John Grden
- 出版社/メーカー: Apress
- 発売日: 2008/08
- メディア: ペーパーバック
- 購入: 9人 クリック: 52回
- この商品を含むブログ (3件) を見る
#公式のサンプルがFlex1.5なのかそのままではうまくFlex3では動かなかったので、がんばって自分用に書きました。
チャットプログラム myChat.mxml
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()" backgroundAlpha="1" backgroundColor="0xffffff"> <mx:Script> <![CDATA[ private var nc:NetConnection; private var ns:NetStream; private var dragging:Boolean = false; private var so:SharedObject; private function init():void{ nc = new NetConnection(); nc.client = new CustomClient(); nc.objectEncoding = ObjectEncoding.AMF0; nc.connect("rtmp://localhost/oflaDemo"); nc.addEventListener(NetStatusEvent.NET_STATUS,onNetStatus); nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onSecurityError); } private function onNetStatus(evt:NetStatusEvent):void { //trace( "onNetstatus" ); switch(evt.info.code) { case "NetConnection.Connect.Success": so = SharedObject.getRemote("ball", nc.uri, true ); if( so ){ so.addEventListener( SyncEvent.SYNC , function( evt:SyncEvent ):void{ if(dragging ) return; serverTxt.text = "x=> " + so.data.mousePosition.x + " , y=> " + so.data.mousePosition.y; logo.x = so.data.mousePosition.x; logo.y = so.data.mousePosition.y; }); so.connect(nc); } break; case "NetConnection.Connect.Closed": break; case "NetConnection.Connect.Failed": break; case "NetConnection.Connect.Rejected": break; default: } } private function onSecurityError(evt:SecurityErrorEvent):void { } private function startMove():void{ dragging = true; logo.startDrag(); } private function stopMove():void{ dragging = false; logo.stopDrag(); } private function onMouseMove():void{ if( dragging == true ){ localTxt.text = "x=> " + logo.x + " , y=> " + logo.y; so.setProperty("mousePosition", {x: logo.x, y: logo.y} ); } } ]]> </mx:Script> <mx:Image id="logo" x="51" y="111" width="192" height="176" source="logo.png" mouseDown="startMove()" mouseUp="stopMove()" mouseMove="onMouseMove()"/> <mx:Canvas x="10" y="10" width="255" height="72" backgroundAlpha="0.5" backgroundColor="0xffffff" dropShadowColor="0x000000" dropShadowEnabled="true" cornerRadius="10" borderColor="0xffccff" borderStyle="solid" borderThickness="3"> <mx:Label x="10" y="10" text="Local:"/> <mx:Label x="10" y="36" text="Server:"/> <mx:Label x="68" y="10" id="localTxt" /> <mx:Label x="68" y="36" id="serverTxt" /> </mx:Canvas> </mx:Application>
ドラッグ共有プログラム myBall.mxml
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()" backgroundAlpha="1" backgroundColor="0xffffff"> <mx:Script> <![CDATA[ private var nc:NetConnection = new NetConnection(); private var so:SharedObject; private function init():void{ nc = new NetConnection(); nc.client = new CustomClient(); nc.objectEncoding = ObjectEncoding.AMF0; nc.connect("rtmp://localhost/oflaDemo"); nc.addEventListener(NetStatusEvent.NET_STATUS,onNetStatus); nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onSecurityError); } private function onNetStatus(evt:NetStatusEvent):void { //trace( "onNetstatus" ); switch(evt.info.code) { case "NetConnection.Connect.Success": trace("Success"); initSO(); break; case "NetConnection.Connect.Closed": trace("Closed"); break; case "NetConnection.Connect.Failed": trace("Failed"); break; case "NetConnection.Connect.Rejected": trace("Rejected"); break; default: trace(evt.info.code); } } private function onSecurityError(evt:SecurityErrorEvent):void { trace("Security Error"); } private function initSO():void{ //trace( "initSO" ); so = SharedObject.getRemote( "chat" , nc.uri , true ); if( so ){ so.addEventListener( SyncEvent.SYNC , function( evt:SyncEvent ):void{ //trace( so.data.chatMessage ); if( so.data.chatMessage != undefined ){ history.text += so.data.chatMessage + "\n"; message.text = ""; } }); so.connect(nc); } } private function sendMessage():void{ //trace( "sendMessage" ); if( message.text != "" ){ //trace( "sendMessage2" ); so.setProperty( "chatMessage" , message.text ); } } ]]> </mx:Script> <mx:TextInput id="message" x="10" y="220" width="402" enter="sendMessage()" backgroundAlpha="0.5" backgroundColor="0xffffff" dropShadowColor="0x000000" dropShadowEnabled="true" cornerRadius="10" borderColor="0xffccff" borderStyle="solid" borderThickness="3" /> <mx:TextArea id="history" x="10" y="10" width="505" height="202" backgroundAlpha="0.5" backgroundColor="0xffffff" dropShadowColor="0x000000" dropShadowEnabled="true" cornerRadius="10" borderColor="0xffccff" borderStyle="solid" borderThickness="3"/> <mx:Button id="btn" x="420" y="220" label="コメントする" width="95" click="sendMessage()" height="24"/> </mx:Application>
動画ライブストリーミングプログラム myStreaming.mxml
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()" backgroundAlpha="1" backgroundColor="0xffffff"> <mx:Script> <![CDATA[ private var nc:NetConnection; private var ns:NetStream; private var cam:Camera; private var mic:Microphone; private function init():void{ nc = new NetConnection(); nc.client = new CustomClient(); nc.connect("rtmp://localhost/oflaDemo"); nc.addEventListener(NetStatusEvent.NET_STATUS,onNetStatus); nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onSecurityError); setupCameraMic(); } private function onNetStatus(evt:NetStatusEvent):void { //trace( "onNetstatus" ); switch(evt.info.code) { case "NetConnection.Connect.Success": ns = new NetStream( nc ); trace("Success"); break; case "NetConnection.Connect.Closed": trace("Closed"); break; case "NetConnection.Connect.Failed": trace("Failed"); break; case "NetConnection.Connect.Rejected": trace("Rejected"); break; default: } } private function onSecurityError(evt:SecurityErrorEvent):void { trace("Security Error"); } private function broadcastClick():void{ ns.attachCamera(cam); ns.attachAudio(mic); //ns.publish( "red5BroadcastDemo" , "record" ); ns.publish( "red5BroadcastDemo" , "live" ); playButton.enabled = false; stopButton.enabled = true; } private function stopClick():void{ ns.close(); playButton.enabled = true; stopButton.enabled = false; } private function setupCameraMic():void{ cam = Camera.getCamera(); cam.setMode(320, 240, 30); cam.setQuality(0,90); mic = Microphone.getMicrophone(); mic.rate = 44; if(cam != null) { videoContainer.attachCamera(cam); } } ]]> </mx:Script> <mx:Canvas x="42" y="27" width="338" height="260" backgroundAlpha="0.5" backgroundColor="0xffffff" dropShadowColor="0x000000" dropShadowEnabled="true" cornerRadius="10" borderColor="0xffccff" borderStyle="solid" borderThickness="3" > <mx:VideoDisplay id="videoContainer" x="6" y="7" width="320" height="240"/> </mx:Canvas> <mx:Canvas x="216" y="304" width="164" height="44" backgroundAlpha="0.5" backgroundColor="0xffffff" dropShadowColor="0x000000" dropShadowEnabled="true" cornerRadius="10" borderColor="0xffccff" borderStyle="solid" borderThickness="3" > <mx:Button id="playButton" x="9" y="8" label="broadcast" click="broadcastClick()"/> <mx:Button id="stopButton" x="100" y="8" label="stop" click="stopClick()" enabled="false"/> </mx:Canvas> </mx:Application>
動画ライブストリーミング再生 myStreamingPlayer.mxml
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" backgroundAlpha="1" backgroundColor="0xffffff" creationComplete="init()" xmlns:media="flash.media.*"> <mx:Script> <![CDATA[ import mx.core.UIComponent; private var nc:NetConnection; private var ns:NetStream; private var cam:Camera; private var mic:Microphone; private function init():void{ nc = new NetConnection(); nc.client = new CustomClient(); nc.connect("rtmp://localhost/oflaDemo"); nc.addEventListener(NetStatusEvent.NET_STATUS,onNetStatus); nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR,onSecurityError); } private function onNetStatus(evt:NetStatusEvent):void { //trace( "onNetstatus" ); switch(evt.info.code) { case "NetConnection.Connect.Success": setupCameraMic(); trace("Success"); break; case "NetConnection.Connect.Closed": trace("Closed"); break; case "NetConnection.Connect.Failed": trace("Failed"); break; case "NetConnection.Connect.Rejected": trace("Rejected"); break; default: } } private function onSecurityError(evt:SecurityErrorEvent):void { trace("Security Error"); } private function setupCameraMic():void{ ns = new NetStream( nc ); ns.client = new CustomClient(); var video:Video = new Video(); video.attachNetStream(ns); ns.play("red5BroadcastDemo" , -1 ); myVideoContainer.addChild(video); } private function onMetaData(data:Object):void{ } ]]> </mx:Script> <media:Video id="myVideo" width="320" height="240"/> <mx:Canvas x="33" y="40" width="342" height="269" backgroundAlpha="0.5" backgroundColor="0xffffff" dropShadowColor="0x000000" dropShadowEnabled="true" cornerRadius="10" borderColor="0xffccff" borderStyle="solid" borderThickness="3" > <mx:VideoDisplay id="myVideoContainer" width="320" height="240" x="8" y="10"/> </mx:Canvas> </mx:Application>