apache-flex Flex:恢复Spark视频显示流

wkyowqbh  于 2022-11-01  发布在  Apache
关注(0)|答案(4)|浏览(201)

编辑如果有人至少能告诉我如何在流断开连接时接收事件,那就太好了。

这个控件的文档简直太可怕了。我有一个应用程序,它将有一个实时视频流,我正在寻找一种方法,使VideoDisplay控件恢复其连接的情况下,发生以下任何特定的情况:
1.应用程序启动,但流尚未联机。
1.应用程序正在流式传输,用户已断开与Internet的连接。
1.应用程序正在流式传输,视频服务器崩溃并重新启动。
我正在使用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>

有没有人知道如何让视频显示器从这些问题中恢复?任何帮助都将不胜感激,谢谢。

hi3rlvi2

hi3rlvi21#

如果有人遇到这个问题,这就是我解决它的方法。你需要将视频源设置为空白图像,以停止流媒体,否则它永远不会停止。这个解决方案适用于上述所有情况:

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>
oknrviil

oknrviil2#

作为一个变体,您可以从NetStream对象处理NetStream.Play.PublishNotify。

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") {

    }
 }
btqmn9zl

btqmn9zl3#

我用了Johnatan的代码沿着JayPea的想法来解决我的问题!
我使用了Johnatan提供的所有内容,并在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;
    }
}

这将在流停止并重新启动时重置源,从而导致视频显示再次播放。
注意:视频显示的autoPlay属性需要设置为“true”。

mpgws1up

mpgws1up4#

我知道很多年前就有人问过这个问题,但它仍然帮助我解决了我的问题,鼓励我深入研究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

这至少是我所理解的;最后它对我起作用了;- )

相关问题