Flex: восстановление потока Spark VideoDisplay - PullRequest
0 голосов
/ 08 декабря 2011

EDIT Если кто-то хотя бы скажет мне, как получить событие, когда потоки отключаются, это было бы здорово.

Документация для этого элемента управления просто ужасна. У меня есть приложение, которое будет иметь потоковое видео в реальном времени, и я ищу способ заставить элемент управления VideoDisplay восстановить соединение в случае возникновения какого-либо из этих конкретных сценариев:

  1. Приложение запускается, а поток еще не подключен.
  2. Приложение транслируется, и пользователь отключен от интернета.
  3. Приложение выполняет потоковую передачу, а видеосервер аварийно завершает работу и перезагружается.

Я использую Wowza Media Server и Wirecast для проверки этого. 1 и 3 не работают, я не уверен, что номер 2 работает. Я сделал работу номер 1, добавив этот очень сомнительный кусок кода:

    protected function onMediaPlayerStateChange(event:MediaPlayerStateChangeEvent):void
    {
        if (event.state == MediaPlayerState.PLAYBACK_ERROR)
        {
            var videoSource:DynamicStreamingVideoSource = this.videoDisplay.source as DynamicStreamingVideoSource;

            try
            {
                this.videoDisplay.source = null;
                this.videoDisplay.source = videoSource;
            }
            catch (any:*) {}
        }
    }

Как видите, мне нужен блок try / catch, поскольку оба вызова source вызывают исключения, но все, что происходит до того, как эти исключения, похоже, решает проблему # 1. Это не решает проблему № 3, потому что событие изменения состояния мультимедиа, по-видимому, не происходит при остановке видеосервера.

Это моя контрольная декларация:

<s:VideoDisplay id="videoDisplay" click="onVideoStreamClick(event)" mediaPlayerStateChange="onMediaPlayerStateChange(event)" muted="{this.videoMuted}" top="10" width="280" height="220" autoPlay="true" horizontalCenter="0">
    <s:source>
        <s:DynamicStreamingVideoSource id="videoSource" streamType="live" host="{FlexGlobals.topLevelApplication.parameters.videoStreamURL}">
            <s:DynamicStreamingVideoItem id="videoItemLow" streamName="{FlexGlobals.topLevelApplication.parameters.videoLow}" bitrate="{FlexGlobals.topLevelApplication.parameters.videoLowBitrate}" />
            <s:DynamicStreamingVideoItem id="videoItemMedium" streamName="{FlexGlobals.topLevelApplication.parameters.videoMedium}" bitrate="{FlexGlobals.topLevelApplication.parameters.videoMediumBitrate}" />
            <s:DynamicStreamingVideoItem id="videoItemHigh" streamName="{FlexGlobals.topLevelApplication.parameters.videoHigh}" bitrate="{FlexGlobals.topLevelApplication.parameters.videoHighBitrate}" />
        </s:DynamicStreamingVideoSource>
    </s:source>
</s:VideoDisplay>

Кто-нибудь знает, как заставить VideoDisplay восстанавливаться после этих проблем? Любая помощь приветствуется, спасибо.

Ответы [ 4 ]

1 голос
/ 10 февраля 2012

В качестве варианта вы можете обрабатывать NetStream.Play.PublishNotify из объекта NetStream.

var _source:DynamicStreamingResource;
_source = new DynamicStreamingResource("rtmp://...", StreamType.LIVE);

var streamItems:Vector.<DynamicStreamingItem> = new Vector.<DynamicStreamingItem>();
streamItems.push(new DynamicStreamingItem(streamName, 0));

_source.streamItems = streamItems;

_rtmpDynamicStreamingNetLoader = new RTMPDynamicStreamingNetLoader();
_rtmpDynamicStreamingNetLoader.addEventListener(LoaderEvent.LOAD_STATE_CHANGE, rtmpDynamicStreamingNetLoaderStateChangeHandler);

var cvp:VideoDisplay = new VideoDisplay();

_source.mediaType = MediaType.VIDEO;

var videoElement:MediaElement = new VideoElement(_source, _rtmpDynamicStreamingNetLoader);

cvp.source = videoElement;

private function rtmpDynamicStreamingNetLoaderStateChangeHandler(event:LoaderEvent):void
{
    var netStream:NetStream = event.loadTrait["netStream"] as NetStream;
    if (netStream != null && !netStream.hasEventListener(NetStatusEvent.NET_STATUS)) {
        netStream.addEventListener(NetStatusEvent.NET_STATUS, netStreamNetStatusHandler, false, 0, true);
    }
}

private function netStreamNetStatusHandler(event:NetStatusEvent):void
{
    if (event.info.code == "NetStream.Play.UnpublishNotify") {

    }
    if (event.info.code == "NetStream.Play.PublishNotify") {

    }
 }
1 голос
/ 09 декабря 2011

Если у кого-то есть такая проблема, я так решил ее. Вам нужно установить источник видео на пустое изображение, чтобы остановить потоковое воспроизведение, иначе оно никогда не остановится. Это решение работает для всех сценариев, описанных выше:

    private function resetVideo():void
    {           
        //save current source object
        this.videoEventsDisabled = true;
        var videoSource:DynamicStreamingVideoSource = this.videoDisplay.source as DynamicStreamingVideoSource;

        try //switch to blank image, only this will stop the video stream
        {
            this.videoDisplay.source = "assets/images/video_offline.png";
        }
        catch (any:*) {}

        //wait a few seconds and reset video source
        setTimeout(resetVideoSource, 2000, videoSource);
    }

    private function resetVideoSource(videoSource:DynamicStreamingVideoSource):void
    {
        this.videoEventsDisabled = false;
        this.videoDisplay.source = videoSource;
    }

    protected function onMediaPlayerStateChange(event:MediaPlayerStateChangeEvent):void
    {
        if (this.videoEventsDisabled)
        {
            return;
        }

        //something went wrong
        if (event.state == MediaPlayerState.PLAYBACK_ERROR)
        {
            resetVideo();
        }
    }

    protected function onCurrentTimeChange(event:TimeEvent):void
    {
        if (this.videoEventsDisabled)
        {
            return;
        }

        //if there was a number before, and its suddendly NaN, video is offline
        if (isNaN(event.time) && !isNaN(this.previousVideoTime))
        {
            resetVideo();
        }
        else //store event time for future comparisons
        {
            this.previousVideoTime = event.time;
        }
    }

MXML:

<s:VideoDisplay id="videoDisplay" click="onVideoStreamClick(event)" mediaPlayerStateChange="onMediaPlayerStateChange(event)" currentTimeChange="onCurrentTimeChange(event)" muted="{this.videoMuted}" top="10" width="280" height="220" autoPlay="true" horizontalCenter="0">
    <s:source>
        <s:DynamicStreamingVideoSource id="videoSource" streamType="live" host="{FlexGlobals.topLevelApplication.parameters.videoStreamURL}">
            <s:DynamicStreamingVideoItem id="videoItemLow" streamName="{FlexGlobals.topLevelApplication.parameters.videoLow}" bitrate="{FlexGlobals.topLevelApplication.parameters.videoLowBitrate}" />
            <s:DynamicStreamingVideoItem id="videoItemMedium" streamName="{FlexGlobals.topLevelApplication.parameters.videoMedium}" bitrate="{FlexGlobals.topLevelApplication.parameters.videoMediumBitrate}" />
            <s:DynamicStreamingVideoItem id="videoItemHigh" streamName="{FlexGlobals.topLevelApplication.parameters.videoHigh}" bitrate="{FlexGlobals.topLevelApplication.parameters.videoHighBitrate}" />
        </s:DynamicStreamingVideoSource>
    </s:source>
</s:VideoDisplay>
0 голосов
/ 04 июня 2017

Я знаю, что этот вопрос задавался много лет назад, но он все же помог мне решить мою проблему, побудив меня погрузиться в источники VideoDisplay (поскольку, очевидно, нет «чистого» решения; - (

И длятем, у кого та же проблема, мое «решение», может быть, тоже полезно:

Мне пришлось перезапустить то же видео после того, как пользователь нажал «Прервать», но затем решил воспроизвести его снова. Без «сброса» VideoDisplay это привело кчерный экран.

Вот как я решил проблему после того, как обнаружил, что в VideoDisplay была вызвана внутренняя функция "setupSource ()", когда в функции commitProperties () не определен thumnailSource.

Так как функция setupSource () не была общедоступной, я использовал это:

        myVideoDisplaySpark.enabled = false; // changes properties
        myVideoDisplaySpark.source = "";    // does not harm ;-)
        myVideoDisplaySpark.mx_internal::thumbnailSource = null; // forces a setupSource in commitProperties
        myVideoDisplaySpark.enabled = true;  // finally results in the call if setupSource

Это по крайней мере то, что я понял, и в конце это сработало для меня; -)

0 голосов
/ 15 июня 2016

Я использовал код Джонатана вместе с идеей JayPea для решения моей проблемы!

Я использовал все, что дал Джонатан, со следующим небольшим изменением netStreamNetStatusHandler ():

private function netStreamNetStatusHandler(event:NetStatusEvent):void
{
    trace(event.info.code);

    if (event.info.code == "NetStream.Play.PublishNotify")
    {
        try
        {
            cvp.source = ''; //Doesn't need to be a valid path. Empty string should suffice.
        }
        catch (error:Error)
        {
            trace('Video source error: ' + error.message);
        }

        cvp.source = videoElement;
    }
}

Thisсбрасывает источник, когда поток останавливается и перезапускается, вызывая повторное воспроизведение видеоизображения.

ПРИМЕЧАНИЕ. Для свойства autoPlay видеодисплея необходимо установить значение «true».

...