Skip to main content
September 1, 2010
Answered

FMIS Multipoint Publishing - Edge server unpublishes streams

  • September 1, 2010
  • 1 reply
  • 1521 views

Hi Guys,

I am facing a strange issue with a pair of FMIS servers set up with Multipoint Publishing.

Configuration is as follows:

Encoder >>>> FMIS1 >>>> FMIS2

When freshly started, I am able to view live streams from both servers, however, periodically, FMIS2 unpublishes the streams as seen in the log below.

When this happens lives streams are accessible from FMIS1 but not FMIS2. In order to resume live streams on FMIS2, FMIS1 must be restarted.

Any help would be greatly appreciated.

Logs:

2010-09-01 14:31:00 9244 (s)2641173 NGA_1 is unpublishing -

2010-09-01 14:31:00 9244 (s)2641173 FTV_1 is unpublishing -

2010-09-01 14:31:00 9244 (s)2641173 BBCWN_1 is unpublishing -

2010-09-01 14:31:00 9244 (s)2641173 CTI_1 is unpublishing -

2010-09-01 14:31:00 9244 (s)2641173 CNN_1 is unpublishing -

2010-09-01 14:31:00 9244 (s)2641173 NGA_2 is unpublishing -

2010-09-01 14:31:00 9244 (s)2641173 BBCWN_2 is unpublishing -

2010-09-01 14:31:00 9244 (s)2641173 NGC_1 is unpublishing -

2010-09-01 14:31:00 9244 (s)2641173 FTV_2 is unpublishing -

2010-09-01 14:31:00 9244 (s)2641173 CTI_2 is unpublishing -

2010-09-01 14:31:00 9244 (s)2641173 FC_2 is unpublishing -

2010-09-01 14:31:00 9244 (s)2641173 CTI_3 is unpublishing -

2010-09-01 14:31:00 9244 (s)2641173 NGA_3 is unpublishing -

2010-09-01 14:31:00 9244 (s)2641173 CNN_3 is unpublishing -

2010-09-01 14:31:00 9244 (s)2641173 NGC_2 is unpublishing -

2010-09-01 14:31:00 9244 (s)2641173 BBCWN_3 is unpublishing -

2010-09-01 14:31:00 9244 (s)2641173 FTV_3 is unpublishing -

2010-09-01 14:31:00 9244 (s)2641173 FC_1 is unpublishing -

2010-09-01 14:31:00 9244 (s)2641173 CNN_2 is unpublishing -

2010-09-01 14:31:00 9244 (s)2641173 FC_3 is unpublishing -

Configuration:

// Called when the client publishes

application.onPublish = function(client, myStream) {

    trace(myStream.name + " is publishing into application " + application.name);

    // This is an example of using the multi-point publish feature to republish

    // streams to another application instance on the local server.

    if (application.name == "CompanyLive/_definst_"){

        trace("Republishing the stream " + myStream.name + "into /CompanyLive");

        nc = new NetConnection();

     nc.connect( "rtmp://192.168.1.13/ComapnyLive" );

        ns = new NetStream(nc);

        // called when the server NetStream object has a status

        ns.onStatus = function(info) {

            trace("Stream Status: " + info.code)

            if (info.code == "NetStream.Publish.Start") {

                trace("The stream is now publishing");

            }          

        }

        ns.setBufferTime(2);

        ns.attach(myStream);

        ns.publish( myStream.name, "live" );

    }

}

application.onUnpublish = function( client, myStream ) {

    trace(myStream.name + " is unpublishing"  );

}

    This topic has been closed for replies.
    Correct answer SE_0208

    Interestingly the Core and Edge logs didn't hold much info:

    Both servers have entries like so in core:

    2010-09-01 20:30:55 5248 (i)2581233 Core (5248) disconnecting from admin: 200. -

    2010-09-01 20:31:07 5248 (i)2581238 Core (5248) connecting to admin. -

    2010-09-01 20:31:07 5248 (i)2581231 Core (5248) connected to admin. -

    2010-09-01 20:31:08 5248 (i)2581234 Core (5248) connection to admin accepted. -

    Neither of them have anything since the last restart in edge.

    I have removed the app from FMIS2 and restarted, just seen pretty much the same issue arise, all streams were present, down to none now.


    I think i got your problem - What is happening is your are publishing 7 streams from your encoder to "CompanyLive/_definst_" on your FMIS1. Now what happens is you have code like

    nc = new NetConnection();

    nc.connect( "rtmp://XXX.XX.XX.13/CompanyLive" );

    ns = new NetStream(nc);

    So when first stream in published via your encoder - it starts republishing. Just after that another stream from encoder comes and now since it again using same variables which are in local scope, you previous publish is gone for toss - and it goes on. I hope you got the issue.

    The way around is to do code it properly. Just use array to store netconnections and netstream objects and use them accordingly.

    i will just give you hint here:

    application.nc = new Array();

    application.ns= new Array();

    application.nc = new NetConnection();

    application.nc.connect("rtmp://XXX.XX.XX.13/CompanyLive" );

    application.ns = new NetStream(nc);

    ...so on so forth

    Please don't take my code as final , and work on it to write proper code - i wrote it bit of hurry but i hope it helps you.

    1 reply

    Participating Frequently
    September 1, 2010

    Is this the only code you have in your application or is there is something else. Also on second server what code do you have?

    Also can you tell me bit about your workflow. Are you publishing only one stream to the application on FMIS1? What encoder are you using to publish?

    Also what do you see logs of FMIS1 and FMIS2 - i mean core and edge logs.

    September 1, 2010

    Hi there,

    Thanks very much for your reply, I am publishing 7 streams to the application on FMIS1 from an Envivio encoder.

    Here is the content of the applications, I will post logs in separate replies.

    FMIS 1 Core

    ==========

    /*

    * application.onAppStart:

    * is called when application load. It contains Live (out of the box)

    * application specific initializations.

    */

    application.onAppStart = function()

    {

    // Logging

    trace("Starting Live Service...");

    //  Turning on the Authentication by default

    this.HTMLDomainsAuth = true;

    this.SWFDomainsAuth = true;

    // Populating the list of domains which are allowed to host HTML file

    // which in turn may embed a SWF that connects to this application

    this.allowedHTMLDomains = this.readValidDomains("allowedHTMLdomains.txt","HTMLDomains");

    // Populating the list of domains which are allowed to host a SWF file

    // which may connect to this application

    this.allowedSWFDomains = this.readValidDomains("allowedSWFdomains.txt","SWFDomains");

    // Logging

    if(this.HTMLDomainsAuth){

    trace("Authentication of HTML page URL domains is enabled");

    }

    if(this.SWFDomainsAuth){

    trace("Authentication of SWF URL domains is enabled");

    }

    trace("...loading completed.");

    }

    /*

    *  application.validate:

    * function to validate a given URL by matching through a list of

    * allowed patterns.

    *

    * Parameters:

    * url: contains the input url string.

    * patterns: Array; an array of permmited url patterns.

    *

    * return value:

    * true; when 'url domain" contains a listed domains as a suffix.

    false; otherwise.

    */

    application.validate = function( url, patterns )

    {

    // Convert to lower case

    url = url.toLowerCase();

    var domainStartPos = 0; // domain start position in the URL

    var domainEndPos = 0; // domain end position in the URL

    switch (url.indexOf( "://" ))

    {

    case 4:

    if(url.indexOf( "http://" ) ==0)

    domainStartPos = 7;

    break;

    case 5:

    if(url.indexOf( "https://" ) ==0)

    domainStartPos = 8;

    break;

    }

    if(domainStartPos == 0)

    {

    // URL must be HTTP or HTTPS protocol based

    return false;

    }

    domainEndPos = url.indexOf("/", domainStartPos);

    if(domainEndPos>0)

    {

    colonPos = url.indexOf(":", domainStartPos);

    if( (colonPos>0) && (domainEndPos > colonPos))

    {

    // probably URL contains a port number

    domainEndPos = colonPos; // truncate the port number in the URL

    }

    }

    for ( var i = 0; i < patterns.length; i++ )

    {

    var pos = url.lastIndexOf( patterns);

    if ( (pos > 0) && (pos  < domainEndPos) && (domainEndPos == (pos + patterns.length)) )

    return true;

    }

    return false;

    }

    /*

    * application.onConnect:

    * Implementation of the onConnect interface function (optional).

    *  it is invoked whenever a client connection request connection. Live app uses this

    *  function to authenticate the domain of connection and authorizes only

    *  for a subscriber request.

    */

    application.onConnect = function( p_client, p_autoSenseBW )

    {

    // Check if pageUrl is from a domain we know.

    // Check pageurl

    // A request from Flash Media Encoder is not checked for authentication

    if( (p_client.agent.indexOf("FME")==-1) && (p_client.agent.indexOf("FMLE")==-1))

    {

    // Authenticating HTML file's domain for the request :

    // Don't call validate() when the request is from localhost

    // or HTML Domains Authentication is off.

    if ((p_client.ip != "127.0.0.1") && application.HTMLDomainsAuth

    &&  !this.validate( p_client.pageUrl, this.allowedHTMLDomains ) )

    {

    trace("Authentication failed for pageurl: " + p_client.pageUrl + ", rejecting connection from "+p_client.ip);

    return false;

    }

    // Authenticating the SWF file's domain for the request :

    // Don't call validate() when the request is from localhost

    // or SWF Domains Authentication is off.

    if ((p_client.ip != "127.0.0.1") && application.SWFDomainsAuth

    &&  !this.validate( p_client.referrer, this.allowedSWFDomains ) )

    {

    trace("Authentication failed for referrer: " + p_client.referrer + ", rejecting connection from "+p_client.ip);

    return false;

    }

    // Logging

    trace("Accepted a connection from IP:"+ p_client.ip

    + ", referrer: "+ p_client.referrer

    + ", pageurl: "+ p_client.pageUrl);

    }else{

    // Logging

    trace("Adobe Flash Media Encoder connected from "+p_client.ip);

    }

    // As default, all clients are disabled to access raw audio and video and data bytes in a stream

    // through the use of BitmapData.draw() and SoundMixer.computeSpectrum()., Please refer

    // Stream Data Access doccumentations to know flash player version requirement to support this restriction

    // Access permissions can be allowed for all by uncommenting the following statements

    //p_client.audioSampleAccess = "/";

    //p_client.videoSampleAccess = "/";

    this.acceptConnection(p_client);

    // A connection from Flash 8 & 9 FLV Playback component based client

    // requires the following code.

    if (p_autoSenseBW)

    p_client.checkBandwidth();

    else

    p_client.call("onBWDone");

    }

    /*

    * Client.prototype.getPageUrl

    * Public API to return URL of the HTML page.

    *

    */

    Client.prototype.getPageUrl = function() {

    return this.pageUrl;

    }

    /*

    * Client.prototype.getReferrer

    * Public API to return Domain URL of the client SWF file.

    *

    */

    Client.prototype.getReferrer = function() {

    return this.referrer;

    }

    /*

    * FCPublish :

    * FME calls FCPublish with the name of the stream whenever a new stream

    * is published. This notification can be used by server-side action script

    * to maintain list of all streams or also to force FME to stop publishing.

    * To stop publishing, call "onFCPublish" with an info object with status

    * code set to "NetStream.Publish.BadName".

    */

    Client.prototype.FCPublish = function( streamname )

    {

    // setup your stream and check if you want to allow this stream to be published

    if ( true) // do some validation here

    {      // this is optional.

    this.call("onFCPublish", null, {code:"NetStream.Publish.Start", description:streamname});

    }

    else

    {

    this.call("onFCPublish", null, {code:"NetStream.Publish.BadName", description:streamname});

    }

    }

    /*

    * FCUnpublish :

    * FME notifies server script when a stream is unpublished.

    */

    Client.prototype.FCUnpublish = function( streamname )

    {

    // perform your clean  up

        this.call("onFCUnpublish", null, {code:"NetStream.Unpublish.Success", description:streamname});

    }

    /*

    * releaseStream :

    * When FME connection to FMS drops during a publishing session it will

    * try and republish the stream when connection is restored. On certain

    * occasions FMS will reject the new stream because server is still

    * unaware of the connection drop, sometimes this can take a few minutes.

    * FME calls "releaseStream" method with the stream name and this can be

    * used to forcibly clear the stream.

    */

    Client.prototype.releaseStream = function(streamname)

    {

    s = Stream.get(streamname);

    s.play(false);

    }

    /*

    * application.readValidDomains

    * Function to read Allowed domain file

    * Parameters:

    * fileName:

    * name of the file in the application directory

    * which contains one valid domain name per line. This file can contain

    * comments followed by a '#' as the very first charector in that line.

    * a non-comment entry with a space is considered as an error case.

    * returns

    * an array in which each entry contains a domain name

    * listed in the file.

    */

    application.readValidDomains = function( fileName , domainsType )

    {

    var domainFile = new File(fileName);

    var domainsArray = new Array();

    var index = 0;

    var lineCount = 0;

    var tempLine;

    domainFile.open("text", "read");

    // Read the file line-by-line and fill the domainsArray

    // with valid entries

    while (domainFile.isOpen && ! domainFile.eof() )

    {

    tempLine = domainFile.readln();

    lineCount++;

    if( !tempLine  || tempLine.indexOf("#") == 0)

    {

    continue;

    }

    tempLine = tempLine.trim();

    if(tempLine.indexOf(" ")!=-1)

    {

    trace("undesired <space>, domain entry ignored. "+fileName+":"+(lineCount+1));

    }

    else

    {

    domainsArray[index] =  tempLine.toLowerCase();

    index++;

    if(tempLine == "*")

    {

    switch (domainsType){

    case "HTMLDomains":

    trace ("Found wildcard (*) entry: disabling authentication for HTML file domains ") ;

    application.HTMLDomainsAuth = false;

    break;

    case "SWFDomains":

    trace ("Found wildcard (*) entry: disabling authentication for SWF file domains ") ;

    this.SWFDomainsAuth = false;

    break;

    default:

    // Do nothing

    break;

    }

    }

    }

    } // End while

    // Something is wrong! the domains file must be accessible.

    if( !domainFile.isOpen){

    trace("Error: could not open '"+fileName+"', rejecting all clients except localhost. ");

    }

    else

    {

    domainFile.close();

    }

    return domainsArray;

    }

    /**

    * String.prototype.trim:

    * Function to trim spaces in start an end of an input string.

    * returns:

    * a trimmed string without any leading & ending spaces.

    *

    */

    String.prototype.trim = function () {

    return this.replace(/^\s*/, "").replace(/\s*$/, "");

    }

    // Called when the client publishes

    application.onPublish = function(client, myStream) {

        trace(myStream.name + " is publishing into application " + application.name);

        // This is an example of using the multi-point publish feature to republish

        // streams to another application instance on the local server.

        if (application.name == "CompanyLive/_definst_"){

            trace("Republishing the stream " + myStream.name + "into /CompanyLive");

            nc = new NetConnection();

            nc.connect( "rtmp://xxx.xx.xx13/CompanyLive" );

            ns = new NetStream(nc);

            // called when the server NetStream object has a status

            ns.onStatus = function(info) {

                trace("Stream Status: " + info.code)

                if (info.code == "NetStream.Publish.Start") {

                    trace("The stream is now publishing");

                }          

            }

            ns.setBufferTime(2);

            ns.attach(myStream);

            ns.publish( myStream.name, "live" );

        }

    }

    application.onUnpublish = function( client, myStream ) {

        trace(myStream.name + " is unpublishing"  );

    }

    FMIS2 Edge

    ==========

    /*

    * application.onAppStart:

    * is called when application load. It contains Live (out of the box)

    * application specific initializations.

    */

    application.onAppStart = function()

    {

    // Logging

    trace("Starting Live Service...");

    //  Turning on the Authentication by default

    this.HTMLDomainsAuth = true;

    this.SWFDomainsAuth = true;

    // Populating the list of domains which are allowed to host HTML file

    // which in turn may embed a SWF that connects to this application

    this.allowedHTMLDomains = this.readValidDomains("allowedHTMLdomains.txt","HTMLDomains");

    // Populating the list of domains which are allowed to host a SWF file

    // which may connect to this application

    this.allowedSWFDomains = this.readValidDomains("allowedSWFdomains.txt","SWFDomains");

    // Logging

    if(this.HTMLDomainsAuth){

    trace("Authentication of HTML page URL domains is enabled");

    }

    if(this.SWFDomainsAuth){

    trace("Authentication of SWF URL domains is enabled");

    }

    trace("...loading completed.");

    }

    /*

    *  application.validate:

    * function to validate a given URL by matching through a list of

    * allowed patterns.

    *

    * Parameters:

    * url: contains the input url string.

    * patterns: Array; an array of permmited url patterns.

    *

    * return value:

    * true; when 'url domain" contains a listed domains as a suffix.

    false; otherwise.

    */

    application.validate = function( url, patterns )

    {

    // Convert to lower case

    url = url.toLowerCase();

    var domainStartPos = 0; // domain start position in the URL

    var domainEndPos = 0; // domain end position in the URL

    switch (url.indexOf( "://" ))

    {

    case 4:

    if(url.indexOf( "http://" ) ==0)

    domainStartPos = 7;

    break;

    case 5:

    if(url.indexOf( "https://" ) ==0)

    domainStartPos = 8;

    break;

    }

    if(domainStartPos == 0)

    {

    // URL must be HTTP or HTTPS protocol based

    return false;

    }

    domainEndPos = url.indexOf("/", domainStartPos);

    if(domainEndPos>0)

    {

    colonPos = url.indexOf(":", domainStartPos);

    if( (colonPos>0) && (domainEndPos > colonPos))

    {

    // probably URL contains a port number

    domainEndPos = colonPos; // truncate the port number in the URL

    }

    }

    for ( var i = 0; i < patterns.length; i++ )

    {

    var pos = url.lastIndexOf( patterns);

    if ( (pos > 0) && (pos  < domainEndPos) && (domainEndPos == (pos + patterns.length)) )

    return true;

    }

    return false;

    }

    /*

    * application.onConnect:

    * Implementation of the onConnect interface function (optional).

    *  it is invoked whenever a client connection request connection. Live app uses this

    *  function to authenticate the domain of connection and authorizes only

    *  for a subscriber request.

    */

    application.onConnect = function( p_client, p_autoSenseBW )

    {

    // Check if pageUrl is from a domain we know.

    // Check pageurl

    // A request from Flash Media Encoder is not checked for authentication

    if( (p_client.agent.indexOf("FME")==-1) && (p_client.agent.indexOf("FMLE")==-1))

    {

    // Authenticating HTML file's domain for the request :

    // Don't call validate() when the request is from localhost

    // or HTML Domains Authentication is off.

    if ((p_client.ip != "127.0.0.1") && application.HTMLDomainsAuth

    &&  !this.validate( p_client.pageUrl, this.allowedHTMLDomains ) )

    {

    trace("Authentication failed for pageurl: " + p_client.pageUrl + ", rejecting connection from "+p_client.ip);

    return false;

    }

    // Authenticating the SWF file's domain for the request :

    // Don't call validate() when the request is from localhost

    // or SWF Domains Authentication is off.

    if ((p_client.ip != "127.0.0.1") && application.SWFDomainsAuth

    &&  !this.validate( p_client.referrer, this.allowedSWFDomains ) )

    {

    trace("Authentication failed for referrer: " + p_client.referrer + ", rejecting connection from "+p_client.ip);

    return false;

    }

    // Logging

    trace("Accepted a connection from IP:"+ p_client.ip

    + ", referrer: "+ p_client.referrer

    + ", pageurl: "+ p_client.pageUrl);

    }else{

    // Logging

    trace("Adobe Flash Media Encoder connected from "+p_client.ip);

    }

    // As default, all clients are disabled to access raw audio and video and data bytes in a stream

    // through the use of BitmapData.draw() and SoundMixer.computeSpectrum()., Please refer

    // Stream Data Access doccumentations to know flash player version requirement to support this restriction

    // Access permissions can be allowed for all by uncommenting the following statements

    //p_client.audioSampleAccess = "/";

    //p_client.videoSampleAccess = "/";

    this.acceptConnection(p_client);

    // A connection from Flash 8 & 9 FLV Playback component based client

    // requires the following code.

    if (p_autoSenseBW)

    p_client.checkBandwidth();

    else

    p_client.call("onBWDone");

    }

    /*

    * Client.prototype.getPageUrl

    * Public API to return URL of the HTML page.

    *

    */

    Client.prototype.getPageUrl = function() {

    return this.pageUrl;

    }

    /*

    * Client.prototype.getReferrer

    * Public API to return Domain URL of the client SWF file.

    *

    */

    Client.prototype.getReferrer = function() {

    return this.referrer;

    }

    /*

    * FCPublish :

    * FME calls FCPublish with the name of the stream whenever a new stream

    * is published. This notification can be used by server-side action script

    * to maintain list of all streams or also to force FME to stop publishing.

    * To stop publishing, call "onFCPublish" with an info object with status

    * code set to "NetStream.Publish.BadName".

    */

    Client.prototype.FCPublish = function( streamname )

    {

    // setup your stream and check if you want to allow this stream to be published

    if ( true) // do some validation here

    {      // this is optional.

    this.call("onFCPublish", null, {code:"NetStream.Publish.Start", description:streamname});

    }

    else

    {

    this.call("onFCPublish", null, {code:"NetStream.Publish.BadName", description:streamname});

    }

    }

    /*

    * FCUnpublish :

    * FME notifies server script when a stream is unpublished.

    */

    Client.prototype.FCUnpublish = function( streamname )

    {

    // perform your clean  up

        this.call("onFCUnpublish", null, {code:"NetStream.Unpublish.Success", description:streamname});

    }

    /*

    * releaseStream :

    * When FME connection to FMS drops during a publishing session it will

    * try and republish the stream when connection is restored. On certain

    * occasions FMS will reject the new stream because server is still

    * unaware of the connection drop, sometimes this can take a few minutes.

    * FME calls "releaseStream" method with the stream name and this can be

    * used to forcibly clear the stream.

    */

    Client.prototype.releaseStream = function(streamname)

    {

    s = Stream.get(streamname);

    s.play(false);

    }

    /*

    * application.readValidDomains

    * Function to read Allowed domain file

    * Parameters:

    * fileName:

    * name of the file in the application directory

    * which contains one valid domain name per line. This file can contain

    * comments followed by a '#' as the very first charector in that line.

    * a non-comment entry with a space is considered as an error case.

    * returns

    * an array in which each entry contains a domain name

    * listed in the file.

    */

    application.readValidDomains = function( fileName , domainsType )

    {

    var domainFile = new File(fileName);

    var domainsArray = new Array();

    var index = 0;

    var lineCount = 0;

    var tempLine;

    domainFile.open("text", "read");

    // Read the file line-by-line and fill the domainsArray

    // with valid entries

    while (domainFile.isOpen && ! domainFile.eof() )

    {

    tempLine = domainFile.readln();

    lineCount++;

    if( !tempLine  || tempLine.indexOf("#") == 0)

    {

    continue;

    }

    tempLine = tempLine.trim();

    if(tempLine.indexOf(" ")!=-1)

    {

    trace("undesired <space>, domain entry ignored. "+fileName+":"+(lineCount+1));

    }

    else

    {

    domainsArray[index] =  tempLine.toLowerCase();

    index++;

    if(tempLine == "*")

    {

    switch (domainsType){

    case "HTMLDomains":

    trace ("Found wildcard (*) entry: disabling authentication for HTML file domains ") ;

    application.HTMLDomainsAuth = false;

    break;

    case "SWFDomains":

    trace ("Found wildcard (*) entry: disabling authentication for SWF file domains ") ;

    this.SWFDomainsAuth = false;

    break;

    default:

    // Do nothing

    break;

    }

    }

    }

    } // End while

    // Something is wrong! the domains file must be accessible.

    if( !domainFile.isOpen){

    trace("Error: could not open '"+fileName+"', rejecting all clients except localhost. ");

    }

    else

    {

    domainFile.close();

    }

    return domainsArray;

    }

    /**

    * String.prototype.trim:

    * Function to trim spaces in start an end of an input string.

    * returns:

    * a trimmed string without any leading & ending spaces.

    *

    */

    String.prototype.trim = function () {

    return this.replace(/^\s*/, "").replace(/\s*$/, "");

    }

    // Called when the client publishes

    application.onPublish = function(client, myStream) {

        trace(myStream.name + " is publishing into application " + application.name);

        // This is an example of using the multi-point publish feature to republish

        // streams to another application instance on the local server.

        if (application.name == "CompanyLive/_definst_"){

            trace("Republishing the stream " + myStream.name + "into /CompanyLive");

            nc = new NetConnection();

          //  nc.connect( "rtmp://XXX.XX.XX.13/CompanyLive" );

            ns = new NetStream(nc);

            // called when the server NetStream object has a status

            ns.onStatus = function(info) {

                trace("Stream Status: " + info.code)

                if (info.code == "NetStream.Publish.Start") {

                    trace("The stream is now publishing");

                }          

            }

            ns.setBufferTime(2);

            ns.attach(myStream);

            ns.publish( myStream.name, "live" );

        }

    }

    application.onUnpublish = function( client, myStream ) {

        trace(myStream.name + " is unpublishing"  );

    }

    Participating Frequently
    September 1, 2010

    If you are not doing anything on second server you can remove code from there. I mean just publish to blank app there. Also logs which you pasted in first post were they logs from second or first server?