GeekChimps


FlexでRed5を利用してライブストリーミング

投稿者: miizasa, カテゴリー: Flex, Red5

前回はRed5のoflaDemoを使って動画のストリーミング再生をやりましたが今回はライブストリーミングに挑戦します。とは言ってもカメラやマイクの使い方ぐらいで前回のプレイヤーとあまり変わりません。
実は受信側に至っては前回のプレイヤーがそのまま使えます。streamidだけ合わせるだけで利用できます。
LivePublisher.mxml(ライブパブリッシャー)

actionscript
< view plain text >
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300" mouseOut="mouseOutHandler(event);" mouseChildren="true">
  3.     <mx:Script>
  4.         <![CDATA[
  5.             import flash.net.*;
  6.             import mx.controls.Alert;
  7.             import mx.core.UIComponent;
  8.  
  9.             // publicプロパティ===================================================================
  10.             public var streamid : String = "testlive";
  11.             public var protocols : String = "rtmp";    // rtmp rtmpt
  12.             public var host: String = "www.bamboo.mydns.jp";
  13.             public var videowidth : int = 320;
  14.             public var videoheight : int = 240;
  15.             public var publishtype : String = "live";     // live・record・append
  16.             public var fps: int = 30;     // 1~30
  17.             public var keyframe: int = 1;    // 1~48
  18.             public var quality : int = 90;    // 0~100
  19.  
  20.             [Bindable]
  21.             public var videoenable : Boolean = true;
  22.  
  23.             // privateプロパティ===================================================================
  24.             private var uiC : UIComponent = new UIComponent();
  25.             private var ncPub : NetConnection = new NetConnection();
  26.             private var ncView : NetConnection = new NetConnection();
  27.             private var nsPublish:NetStream;
  28.             private var nsPlay:NetStream;
  29.             private var videoURL : String;
  30.             private var mouseIn : Boolean;
  31.             private var ctrlvisible : Boolean;
  32.  
  33.             [Bindable]
  34.             private var isPlaying:Boolean = false;
  35.  
  36.             // pablicメソッド===================================================================
  37.             public function play():void{
  38.  
  39.                 // Viewer用NetConnectionのイベントリスナ設定
  40.                 ncView.addEventListener(NetStatusEvent.NET_STATUS, netViewStatusHandler);
  41.                 ncView.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
  42.                 ncView.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
  43.  
  44.                 // パラメータチェック
  45.  
  46.                 // URL組み立て
  47.                 videoURL = protocols + "://" + host + "/oflaDemo";
  48.  
  49.                 ncView.connect(videoURL);
  50.  
  51.             }
  52.  
  53.             public function playstop():void {
  54.                 if (nsPlay) {
  55.                     nsPlay.close();
  56.                 }
  57.             }
  58.  
  59.             public function publish():void{
  60.  
  61.                 // パブリッシャ用NetConnectionのイベントリスナ設定
  62.                 ncPub.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
  63.                 ncPub.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
  64.                 ncPub.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
  65.  
  66.                 // Viewer用NetConnectionのイベントリスナ設定
  67.                 ncView.addEventListener(NetStatusEvent.NET_STATUS, netViewStatusHandler);
  68.                 ncView.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
  69.                 ncView.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
  70.  
  71.                 // パラメータチェック
  72.  
  73.  
  74.  
  75.                 // URL組み立て
  76.                 videoURL = protocols + "://" + host + "/oflaDemo";
  77.  
  78.                 //パブリッシャ用コネクション接続
  79.                 ncPub.connect(videoURL);
  80.  
  81.             }
  82.  
  83.             public function publishstop():void {
  84.                 if (nsPublish) {
  85.                     nsPublish.close();
  86.                 }
  87.             }
  88.  
  89.             // privateメソッド===================================================================
  90.             // パブリッシュ用NetStatusイベントハンドラ
  91.             private function netStatusHandler(event:NetStatusEvent):void{
  92.                 switch (event.info.code) {
  93.                     case "NetConnection.Connect.Success":
  94.                         //connectStream();
  95.                         startPublish(publishtype,streamid);
  96.                         break;
  97.                     case "NetStream.Play.StreamNotFound":
  98.                         trace("Stream not found: " + videoURL);
  99.                         break;
  100.                 }
  101.  
  102.             }
  103.             // Viewer用NetStatusイベントハンドラ
  104.             private function netViewStatusHandler(event:NetStatusEvent):void{
  105.                 switch (event.info.code) {
  106.                     case "NetConnection.Connect.Success":
  107.                         connectStream();
  108.                         break;
  109.                     case "NetStream.Play.StreamNotFound":
  110.                         trace("Stream not found: " + videoURL);
  111.                         break;
  112.                 }
  113.  
  114.             }
  115.  
  116.             private function securityErrorHandler(event:SecurityErrorEvent):void{
  117.                 trace("securityErrorHandler: " + event);
  118.             }
  119.  
  120.             private function asyncErrorHandler(event:AsyncErrorEvent):void{
  121.                 trace("asyncErrorHandler: " + event);
  122.             }
  123.  
  124.             private function netIOErrorHandler(event:AsyncErrorEvent):void{
  125.                 trace("netIOErrorHandler: " + event);
  126.             }
  127.  
  128.             //
  129.             private function connectStream():void{
  130.                 nsPlay = new NetStream(ncView);
  131.                 nsPlay.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
  132.                 nsPlay.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
  133.  
  134.                 var video : Video = new Video(this.width, this.height);
  135.                 video.attachNetStream(nsPlay);
  136.  
  137.                 nsPlay.play(streamid);
  138.  
  139.                 uiC.addChild(video);
  140.                 uiC.addEventListener(MouseEvent.MOUSE_OVER, mouseOverHandler);
  141.  
  142.                 this.addChild(uiC);
  143.                 this.setChildIndex(ctrl,1);
  144.  
  145.                 sndonly.visible = !(videoenable);
  146.  
  147.                 btnPlay.selected = true;
  148.                 isPlaying = true;
  149.  
  150.             }
  151.  
  152.  
  153.             public function startPublish( publishMode : String, streamName : String ) : void
  154.             {
  155.                 try
  156.                 {
  157.                     var camera :Camera = Camera.getCamera();
  158.                     var microphone :Microphone = Microphone.getMicrophone();;
  159.                     //
  160.                     if ( microphone != null || camera != null )
  161.                     {
  162.                         // close previous stream
  163.                         if ( nsPublish != null )
  164.                         {
  165.                             // 現在の配信をとめる
  166.                             nsPublish.close();
  167.  
  168.                         }
  169.                         // Setup NetStream for publishing.
  170.                         nsPublish = new NetStream( ncPub );
  171.                         //
  172.                         nsPublish.addEventListener( NetStatusEvent.NET_STATUS, netStatusHandler );
  173.                         nsPublish.addEventListener( IOErrorEvent.IO_ERROR, netIOErrorHandler );
  174.                         nsPublish.addEventListener( AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler );
  175.                         //
  176.                         //nsPublish.client = new CustomClient();
  177.  
  178.                         // attach devices to NetStream.
  179.                         if ( camera != null )
  180.                         {
  181.                             sndonly.visible = false;
  182.                             videoenable = true;
  183.                             // カメラ設定(フレーム・画質など)
  184.                             camera.setKeyFrameInterval( keyframe );
  185.                             camera.setMode( this.width, this.height, fps );
  186.                             camera.setQuality( 0, quality );
  187.                             nsPublish.attachCamera( camera );
  188.                         }
  189.                         else {
  190.                             //カメラなしの場合には、画像表示
  191.                             sndonly.visible = true;
  192.                             videoenable = false;
  193.  
  194.                         }
  195.  
  196.                         if ( microphone != null)
  197.                         {
  198.                             nsPublish.attachAudio( microphone );
  199.                         }
  200.  
  201.                         // Start publishing.
  202.                         nsPublish.publish( streamName, publishMode );
  203.  
  204.                         // ビューア接続
  205.                         ncView.connect(videoURL);
  206.  
  207.                     }
  208.                     else
  209.                     {
  210.                         trace( "Can't publish stream, no input device(s) selected");
  211.                     }
  212.                 }
  213.                 catch( e : ArgumentError )
  214.                 {
  215.                     // Invalid parameters
  216.                     switch ( e.errorID )
  217.                     {
  218.                         // NetStream object must be connected.
  219.                         case 2126 :
  220.                             //
  221.                             trace( "Can't publish stream, not connected to server");
  222.                             trace(  "Not connected to server");
  223.                             break;
  224.                         //
  225.                         default :
  226.                            //
  227.                            trace( e.toString() );
  228.                            break;
  229.                     }
  230.                 }
  231.             }
  232.  
  233.             private function mouseOverHandler(event:MouseEvent):void {
  234.                 ctrl.visible = true;
  235.                 mouseIn = true;
  236.                 ctrlvisible = true;
  237.             }
  238.  
  239.             private function childmouseOverHandler(event:MouseEvent):void {
  240.                 mouseIn = true;
  241.             }
  242.  
  243.             private function mouseOutHandler(event:MouseEvent):void {
  244.                 setTimer();
  245.                 mouseIn = false;
  246.             }
  247.  
  248.             private function setTimer():void {
  249.                 var stopTimer:Timer = new Timer(3000, 1);
  250.                 stopTimer.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete);
  251.                 stopTimer.start();
  252.             }
  253.  
  254.             private function onTimerComplete(event:TimerEvent):void {
  255.                 if (mouseIn == false) {
  256.                     // 複数回処理しないためのチェック
  257.                     if (ctrl.visible == true) {
  258.                         // Effectによりコンポーネントのvisibleが設定されるのにDelayがあるので
  259.                         // さらなるチェック
  260.                         if (ctrlvisible == true) {
  261.                             ctrl.visible = false;
  262.                             ctrlvisible = false;
  263.                         }
  264.                     }
  265.                 }
  266.                 else {
  267.                     ctrl.visible = true;
  268.                     ctrlvisible = true;
  269.                 }
  270.             }
  271.  
  272.  
  273.         ]]>
  274.     </mx:Script>
  275.     <mx:Style>
  276.         .PlayStyle {
  277.             downSkin: Embed("../assets/play_right_g.JPG");
  278.             upSkin: Embed("../assets/play_right_b.JPG");
  279.             overSkin: Embed("../assets/play_right_y.JPG");
  280.             disabledSkin: Embed("../assets/play_right_w.JPG");
  281.             selectedDownSkin: Embed("../assets/tempStop_g.JPG");
  282.             selectedUpSkin: Embed("../assets/tempStop_b.JPG");
  283.             selectedOverSkin: Embed("../assets/tempStop_y.JPG");
  284.             selectedDisabledSkin: Embed("../assets/tempStop_w.JPG");
  285.         }
  286.         .StopStyle {
  287.             downSkin: Embed("../assets/stop_g.JPG");
  288.             upSkin: Embed("../assets/stop_b.JPG");
  289.             overSkin: Embed("../assets/stop_y.JPG");
  290.             disabledSkin: Embed("../assets/stop_w.JPG");
  291.             selectedDownSkin: Embed("../assets/stop_g.JPG");
  292.             selectedUpSkin: Embed("../assets/stop_b.JPG");
  293.             selectedOverSkin: Embed("../assets/stop_y.JPG");
  294.             selectedDisabledSkin: Embed("../assets/stop_w.JPG");
  295.         }
  296.     </mx:Style>
  297.  
  298.  
  299.     <mx:Fade id="fadeOut" duration="1000" alphaFrom="1.0" alphaTo="0.0"/>
  300.     <mx:Fade id="fadeIn" duration="1000" alphaFrom="0.0" alphaTo="1.0"/>
  301.     <mx:WipeUp id="wipeIn" duration="1000"/>
  302.     <mx:WipeDown id="wipeOut" duration="1000"/>
  303.     <mx:Canvas id="ctrl" left="0" top="0" right="0" bottom="0" visible="false" showEffect="fadeIn" hideEffect="fadeOut" alpha="0.5">
  304.         <mx:VBox left="0" right="0" top="0" bottom="0">
  305.             <mx:HBox x="63" y="155" width="100%" verticalAlign="middle" horizontalAlign="center" height="50%" mouseOver="childmouseOverHandler(event);">
  306.                 <mx:Button label="閉じる"/>
  307.             </mx:HBox>
  308.             <mx:HBox x="63" y="155" width="100%" horizontalAlign="center" verticalAlign="middle" height="50%" >
  309.                 <mx:Button styleName="PlayStyle" toggle="true" id="btnPlay" selected="{isPlaying}" width="50" height="50" mouseOver="childmouseOverHandler(event);" />
  310.                 <mx:Button styleName="StopStyle" width="50" height="50" mouseOver="childmouseOverHandler(event);"/>
  311.             </mx:HBox>
  312.         </mx:VBox>
  313.     </mx:Canvas>
  314.     <mx:Image id="sndonly" left="0" top="0" bottom="0" right="0" source="@Embed('../assets/screen_sound_only.png')" visible="false" mouseOver="mouseOverHandler(event);"/>
  315.  
  316. </mx:Canvas>

んでは続いて毎度お馴染みの上っ面
red5live.mxml(上っ面)

actionscript
< view plain text >
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"  backgroundColor="#FFFFFF" xmlns:ns1="*" creationComplete="init()">
  3.  
  4.     <mx:Label x="24" y="18" text="Publish"/>
  5.     <mx:Label x="309" y="18" text="View"/>
  6.     <mx:Button x="77" y="16" label="配信" click="pub.publish();"/>
  7.     <mx:Button x="346" y="16" label="受信" click="view.play();"/>
  8.     <ns1:LivePublisher id="pub"  x="24" y="44" width="320" height="240">
  9.     </ns1:LivePublisher>
  10.     <ns1:LivePublisher id="view" x="352" y="246" width="320" height="240" videoenable="{pub.videoenable}">
  11.     </ns1:LivePublisher>
  12.  
  13. </mx:Application>

完成したのがこれ

http://www.bamboo.mydns.jp/flex/red5live.swf

ビデオソースやマイクデバイスは先頭のやつを使ってしまっていますが
選択できるようにするといいですね。

    

関連(してる的な)記事

    

コメント(1)

コメントする

コメントリンクを nofollow free に設定することも出来ます。