Skip to main content
June 15, 2009
Answered

Flash Media Server 3 - Can RTMP and HTTP tunneling be configured?

  • June 15, 2009
  • 1 reply
  • 5253 views

I have read some forums posted in here and also searched the web extensively but cannot find a clear answer or get HTTP tunneling to work with Flash Media Server 3.

Q1: Can Flash Media Server 3 be configured for RTMP and HTTP tunneling to work? The reason I need to know if this will work is due to more and more clients are reporting that videos are not playing for them and I have determined that these clients are sitting behind a firewall that has port 1935 blocked. So I would like to configure the FLV playback control to try to stream the file over RTMP and if that does not work, use HTTP.

Can someone please help! Is there a whitepaper that you can point me to or even provide an example to me.

Here is my asctionscript that I have tried to get this to work, but it does not.

Some other notes are, the .FLV files live in this folder: D:\Adobe\Flash Media Server 3\applications\vod\media

The videos are recorded and then converted into .FLV files and loaded into this folder.

I have everything hard coded below to try and get it to work this way first and thought that would be easier for you to help me. The ultimate solution is I use a FLVPlayback control and pass the location and .FLV file name on the query string "Details.aspx?VIDEO=rtmp://216.203.12.15/vod/flv". I have pasted the object code * to show this example below the asctionscript.

package
{
    import flash.display.Sprite;
    import flash.filters.BlurFilter;
    import fl.video.FLVPlayback;
    import flash.display.LoaderInfo;
   
    import flash.net.NetConnection;
    import flash.events.NetStatusEvent;
    import flash.net.NetStream;
    import flash.media.Video;


    public class Streams extends Sprite
    {
        var nc:NetConnection;
        var stream:NetStream;
        var playStream:NetStream;
        var video:Video;
        //Variable that passes in .flv from query string
        var videoPath:String = ""

        public function Streams()
        {
            nc = new NetConnection();
            nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);

           //This is where I attempt to connect via RTMP and if that does not work try RTMPT over HTTP port 80

            nc.connect("rtmp://216.203.12.15/vod");

            nc.connect("rtmpt://216.203.12.15:80/vod");

        }
       
       
       
        private function netStatusHandler(event:NetStatusEvent):void
        {
            trace("connected is: " + nc.connected );
            trace("event.info.level: " + event.info.level);
            trace("event.info.code: " + event.info.code);
           
            switch (event.info.code)
            {
                case "NetConnection.Connect.Success":
                    trace("Congratulations! you're connected");
                    connectStream(nc);
                    // createPlayList(nc);
                    // instead you can also call createPlayList() here
                    break;
                case "NetConnection.Connect.Failed":
                case "NetConnection.Connect.Rejected":
                    trace ("Oops! the connection was rejected");
                    break;
                case "NetStream.Play.Stop":
                    trace("The stream has finished playing");
                    break;
                case "NetStream.Play.StreamNotFound":
                    trace("The server could not find the stream you specified");
                    break;
                case "NetStream.Publish.BadName":
                    trace("The stream name is already used");
                    break;
            }
        }
       
       
        // play a recorded stream on the server
        private function connectStream(nc:NetConnection):void {
            stream = new NetStream(nc);
            stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
            //stream.client = new CustomClient();

            video = new Video();
            video.attachNetStream(stream);

            stream.play("Peter_Christie_widescreen_bloomberg_hr", 0);
            addChild(video);
        }           
    }  
}

*OBJECT EXAMPLE TO SHOW HOW .FLV IS PASSED ON THE QUERY STRING WHICH THE FLVplayback control reads:

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="480" height="440" id="MediaPlayer"> 
<param name="movie" value="/Media/VideoPlayer_Large.swf?VIDEO=rtmp://216.203.12.15/vod/Peter_Christie_widescreen_bloomberg_hr&MM_ComponentVersion=1&autoPlay=false&autoRewind=true" />
<param name="FlashVars" VALUE="rtmp://216.203.12.15/vod/Peter_Christie_widescreen_bloomberg_hr&MM_ComponentVersion=1&autoPlay=false&autoRewind=true" />
<param name="allowScriptAccess" value="sameDomain" /> <param name="quality" value="high" />
<param name="VIDEO" value="rtmp://216.203.12.15/vod/Peter_Christie_widescreen_bloomberg_hr&MM_ComponentVersion=1&autoPlay=false&autoRewind=true" />
<embed src="/Media/VideoPlayer_Large.swf?VIDEO=rtmp://216.203.12.15/vod/Peter_Christie_widescreen_bloomberg_hr&MM_ComponentVersion=1&autoPlay=false&autoRewind=true" quality="high" pluginspage="http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash" flashvars="&MM_ComponentVersion=1&autoPlay=false&autoRewind=true" type="application/x-shockwave-flash" width="480" height="440" name="MediaPlayer">
</embed>
</object>
    This topic has been closed for replies.
    Correct answer

    Assuming your FMS is configured to bind to port 80, and there is nothing else on the FMs machine binding to port 80 on the same IP, your FMS should be all set to accept tunneled requests using the rtmpt protocol over port 80.

    Where you're going wrong is how you're making the connection in your client side code. You don't want to make multiple connect statements as you are.. you want to make one, and then either let the flashplayer run through it's default connection process, or set up a timer to handle protocol failures in your own code.

    When you invoke NetConnection.connect without specifying a port (or a protocol other than rtmp) in the url, the flashplayer will first attempt an rtmp connection over port 1935. If that fails, the flashplayer will automatically attempt a tunneled connection over port 80. The status event won't be dispatched until the Flashplayer either gets a successful connection, or fails on all port/protocol combinations. So, you just need to make one call to connect().

    If you prefer to try specific port/protocol combinations and define your own timeout, you can define the port/protocol in the url

    nc.connect("rtmp://myserver.com:1935/app/instance");

    or

    nc.connect("rtmpt://myserver.com:80/app/instance");

    When you define the port/protocol, the flashplayer will attempt to make the connection on that port/protocol only, and dispatch the status event based on that single attempt.

    So, if you don't want to rely on the flashplayer to handle this, you would first try rtmp/1935. In your status handler, you would inspect the event's info.code property. If you don't get a successful connect, then try rtmpt/80

    1 reply

    Correct answer
    June 15, 2009

    Assuming your FMS is configured to bind to port 80, and there is nothing else on the FMs machine binding to port 80 on the same IP, your FMS should be all set to accept tunneled requests using the rtmpt protocol over port 80.

    Where you're going wrong is how you're making the connection in your client side code. You don't want to make multiple connect statements as you are.. you want to make one, and then either let the flashplayer run through it's default connection process, or set up a timer to handle protocol failures in your own code.

    When you invoke NetConnection.connect without specifying a port (or a protocol other than rtmp) in the url, the flashplayer will first attempt an rtmp connection over port 1935. If that fails, the flashplayer will automatically attempt a tunneled connection over port 80. The status event won't be dispatched until the Flashplayer either gets a successful connection, or fails on all port/protocol combinations. So, you just need to make one call to connect().

    If you prefer to try specific port/protocol combinations and define your own timeout, you can define the port/protocol in the url

    nc.connect("rtmp://myserver.com:1935/app/instance");

    or

    nc.connect("rtmpt://myserver.com:80/app/instance");

    When you define the port/protocol, the flashplayer will attempt to make the connection on that port/protocol only, and dispatch the status event based on that single attempt.

    So, if you don't want to rely on the flashplayer to handle this, you would first try rtmp/1935. In your status handler, you would inspect the event's info.code property. If you don't get a successful connect, then try rtmpt/80

    June 15, 2009

    First JayCharles, thank you very much for the quick and valuable response.

    I just read how to make FMS bind to port 80 and this is what I did.

    I updated the "Adaptor.xml" file to the following: NOTE: 80 was not originally in there.

    <HostPort name="edge1" ctl_channel="localhost:19350">${ADAPTOR.HOSTPORT}</HostPort> (ORIGINAL)

    <HostPort name="edge1" ctl_channel="localhost:19350,80">${ADAPTOR.HOSTPORT}</HostPort> (UPDATED)

    Then, I hard coded just 1 nc.connect("rtmpt://216.203.12.15:80/vod"); using rtmpt, to test that the .flv would stream via HTTP. Please note that I also updated and provide my updated my client side code to NOT make any connection. Just one connection in the asctionscript. The result is no video is playing now?

    Did I do something wrong with adding port 80 in the HostPort tag? Thank you in advance for your help. I am hard coding rtmpt in the asctionscript to test that it works over HTTP because my firewall is not blocking port 1935 and I want to make sure it will work.

    Here is the updated asctionscript code.

    package
    {
        import flash.display.Sprite;
        import flash.filters.BlurFilter;
        import fl.video.FLVPlayback;
        import flash.display.LoaderInfo;
       
        import flash.net.NetConnection;
        import flash.events.NetStatusEvent;
        import flash.net.NetStream;
        import flash.media.Video;


       public class Streams extends Sprite
        {
            var nc:NetConnection;
            var stream:NetStream;
            var playStream:NetStream;
            var video:Video;
            //Variable that passes in .flv from query string
            var videoPath:String = ""

            public function Streams()
            {
                nc = new NetConnection();
                nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
                //nc.connect("rtmp://localhost/Streams");
                //nc.connect("rtmp://216.203.12.15/vod");
                nc.connect("rtmpt://216.203.12.15:80/vod");           

            }
                  
            private function netStatusHandler(event:NetStatusEvent):void
            {
                trace("connected is: " + nc.connected );
                trace("event.info.level: " + event.info.level);
                trace("event.info.code: " + event.info.code);
               
                switch (event.info.code)
                {
                    case "NetConnection.Connect.Success":
                        trace("Congratulations! you're connected");
                        connectStream(nc);
                        // createPlayList(nc);
                        // instead you can also call createPlayList() here
                        break;
                    case "NetConnection.Connect.Failed":
                    case "NetConnection.Connect.Rejected":
                        trace ("Oops! the connection was rejected");
                        break;
                    case "NetStream.Play.Stop":
                        trace("The stream has finished playing");
                        break;
                    case "NetStream.Play.StreamNotFound":
                        trace("The server could not find the stream you specified");
                        break;
                    case "NetStream.Publish.BadName":
                        trace("The stream name is already used");
                        break;
                }
            }
           
           
            // play a recorded stream on the server
            private function connectStream(nc:NetConnection):void {
                stream = new NetStream(nc);
                stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
                //stream.client = new CustomClient();

                video = new Video();
                video.attachNetStream(stream);
                           
                stream.play("Peter_Christie_widescreen_bloomberg_hr", 0);
                addChild(video);
            }           
        }  
    }


    Here is the updated client side code:


    <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" width="480" height="440" id="MediaPlayer"> <param name="movie" value="/Media/VideoPlayer_Large_Tunnel.swf" /> 
    <param name="FlashVars" value="Peter_Christie_widescreen_bloomberg_hr &MM_ComponentVersion=1&autoPlay=false&autoRewind=true" /> 
    <param name="allowScriptAccess" value="sameDomain" /> 
    <param name="quality" value="high" /> <param name="VIDEO" value="Peter_Christie_widescreen_bloomberg_hr &MM_ComponentVersion=1&autoPlay=false&autoRewind=true" />
    <embed src="/Media/VideoPlayer_Large_Tunnel.swf" quality="high" pluginspage="http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash" flashvars="&MM_ComponentVersion=1&autoPlay=false&autoRewind=true" type="application/x-shockwave-flash" width="480" height="440" name="MediaPlayer">
    </embed> 
    </object>

    Participant
    June 15, 2009

    Hi BradLovas, I've recently ran into a problem trying to make it work due to a missconfiguration in my load balancer. Make sure you have stick sessions (same user always routed to the same machine) configured, otherwise you won't be able to have the http streaming negotiated. That is, if you are streaming through a load balancer...