AMS doesn't receive unpublish command SOMETIMES over rtmpt

224 views Asked by At

This one has had me going for a week at least. I am trying to record a video file to AMS. It works great almost all of the time, except about 1 in 10 or 15 recording sessions, I never receive 'NetStream.Unpublish.Success' on my netstream from AMS when I close the stream. I am connecting to AMS using rtmpt when this happens, it seems to work fine over rtmp. Also, it seems like this only happens in safari on mac, but since its so intermittent I don't really trust that. Here is my basic flow:

// just a way to use promises with netStatusEvents
private function netListener(code:String, netObject:*):Promise {
    var deferred:Deferred = new Deferred();

    var netStatusHandler:Function = function (event:NetStatusEvent):void {
        if (event.info.level == 'error') {
            deferred.reject(event);
        } else if (event.info.code == code) {
            deferred.resolve(netObject);
            // we want this to be a one time listener since the connection can swap between record/playback
            netObject.removeEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
        }

    };

    netObject.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);

    return deferred.promise;
}

// set up for recording
private function initRecord():void {

    Settings.recordFile = Settings.uniquePrefix + (new Date()).getTime();

    // detach any existing NetStream from the video
    _view.video.attachNetStream(null);

    // dispose of existing NetStream
    if (_videoStream) {
        _videoStream.dispose();
        _videoStream = null;
    }

    // disconnect before connecting anew
    (_nc.connected ? netListener('NetConnection.Connect.Closed', _nc) : Promise.when(_nc))
    .then(function (nc:NetConnection):void {

        netListener('NetConnection.Connect.Success', _nc)
        .then(function (nc:NetConnection):void {

            _view.video.attachCamera(_webcam);
            // get new NetStream
            _videoStream = getNetStream(_nc);

            ExternalInterface.call("CTplayer." + Settings.instanceName + ".onRecordReady", true);

        }, function(error:NetStatusEvent):void {
            ExternalInterface.call("CTplayer." + Settings.instanceName + ".onError", error.info);
        });

        _nc.connect(Settings.recordServer);

    }); // end ncClose

    if (_nc.connected) _nc.close();

}

// stop recording
private function stop():void {

    netListener('NetStream.Unpublish.Success', _videoStream)
    .then(function (ns:NetStream):void {        
        ExternalInterface.call("CTplayer." + Settings.instanceName + ".onRecordStop", Settings.recordFile);
    });

    _videoStream.attachCamera(null);
    _videoStream.attachAudio(null);
    _videoStream.close();
}

// start recording
private function record():void {

    netListener('NetStream.Publish.Start', _videoStream)
    .then(function (ns:NetStream):void {
        ExternalInterface.call("CTplayer." + Settings.instanceName + ".onRecording");
    });

    _videoStream.attachCamera(_webcam);
    _videoStream.attachAudio(_microphone);
    _videoStream.publish(Settings.recordFile, "record"); // fires NetStream.Publish.Success

}

Update I am now using a new NetConnection per connection attempt and also not forcing port 80 (see my 'answer' below). This has not solved my connection woes, only made the instances more infrequent. Now like every week or so I still have some random failure of ams or flash. Most recently someone made a recording and then flash player was unable to load the video for playback. The ams logs show a connection attempt and then nothing. There should at least be a play event logged for when i load the metadata. This is quite frustrating and impossible to debug.

2

There are 2 answers

0
Stefan On

I would try 2 distinct NetConnection objects, one for record and one for replay. This will remove your complexities around listeners adding/removing and connect/reconnect/disconnect logic and would IMO be cleaner. NetConnections are cheap, and I've always used one per task at hand. The other advantage is that you can connect both at startup so the replay connection is ready instantly.

I've not seen a Promise used here before, but I'm not qualified to comment if that may cause a problem or not.

0
Rob Allsopp On

I think my issue was connecting over port 80. I originally thought I had to use port 80 with rtmpt, so I set my Settings.recordServer variable to rtmpt://myamsserver.net:80/app. I'm now using a shotgun approach where I try a bunch of port/protocol combos at once and pick the first one to connect. It is almost always picking port 443 over rtmpt, which seems much faster and more stable all around than 80, and I haven't had this issue since. It could also be due to not reusing the same NetConnection object like Stefan suggested, its hard to say.