如何通过netConnection和netStream播放RTMP视频

5

我正在开发一个原型,需要通过RTMP协议播放视频。我的代码如下:

private function init():void
    {
        streamID:String = "mp4:myVideo";
        videoURL = "rtmp://fms.xstream.dk/*********.mp4";
        vid = new video();
        vid.width = 480;
        vid.height = 320;

        nc = new NetConnection();
        nc.client = {onBWDone: function():void
            {
            }};
        nc.addEventListener(NetStatusEvent.NET_STATUS, onConnectionStatus);
        nc.connect(videoURL);           
    }

    private function onConnectionStatus(e:NetStatusEvent):void
    {
        if (e.info.code == "NetConnection.Connect.Success")
        {
            trace("Creating NetStream");
            netStreamObj = new NetStream(nc);
            netStreamObj.client = new CustomClient();
            netStreamObj.play(streamID);
            vid.attachNetStream(netStreamObj);
            addChild(vid);
            intervalID = setInterval(playback, 1000);
        }
    }

    private function playback():void
    {
        trace((++counter) + " Buffer length: " + netStreamObj.bufferLength);
    }





class CustomClient 
{
public function onMetaData(info:Object):void
{
    trace("metadata: duration=" + info.duration + " width=" + info.width + " height=" + info.height + " framerate=" + info.framerate);
}
public function onCuePoint(info:Object):void
{
    trace("cuepoint: time=" + info.time + " name=" + info.name + " type=" + info.type);
}

但是它没有播放,也没有出现任何错误和播放,如果有人有任何想法,请帮忙。


在调用 nc.connect 之前,我会添加事件处理程序 nc.addEventListener,同样,在 onConnectionStatus 中加入一些跟踪。 - Lukasz 'Severiaan' Grela
我把nc.addEventListener放在nc.connect之前,但仍然没有任何反应,并且有一个trace("Creating NetStream"),我在输出中得到了那个追踪。 - Vipul
很好,你已经开始创建网络流了,但这不是你能得到的唯一信息,请在处理程序中将e.info.code作为第一行进行跟踪。 - Lukasz 'Severiaan' Grela
我在第一行放置了trace(e.info.code),它跟踪到“NetConnection.Connect.Success”,但仍然没有任何反应。 - Vipul
类似的问题在这里:http://stackoverflow.com/questions/8971272/as3-rtmp-video-stream-on-localhost-red5-path-issue - Paul Gregoire
那不是路径问题,Mondain。无论如何,我已经找到了我的答案,而你的“不需要”的评论非常非常晚了。谢谢。 - Vipul
2个回答

10

按照这种方式做对我有用。我只是用一个新闻频道的链接作为例子,所以尝试将其替换为您自己的流媒体链接。(注:不要在意像素化,这是一个低分辨率的示例链接)。

另外...首先,您打了一个错别字,在其中说vid = new video();(是不是应该是= new Video?)。这会影响后面的addChild(vid)行吗?其次,您需要像asyncErrorHandleronFCSubscribeonBWDone这样的函数,这些函数在使用RTMP时可以防止一些流抛出的错误(至少在我的过去经验中是这样的)。这个示例代码放在一个名为RTMP_test.as的文档类中(根据需要重命名)...

package  {

import flash.display.*; 
import flash.events.*;
import flash.net.*;
import flash.media.*;
import flash.system.*;
import flash.utils.ByteArray;

public class RTMP_test extends MovieClip 
{
    public var netStreamObj:NetStream;
    public var nc:NetConnection;
    public var vid:Video;

    public var streamID:String;
    public var videoURL:String;
    public var metaListener:Object;

public function RTMP_test () 
{ init_RTMP(); }

function init_RTMP():void
{
        /*
        streamID  = "mp4:myVideo";
        videoURL = "rtmp://fms.xstream.dk/*********.mp4";
        */
        streamID  = "QVCLive1@14308";
        videoURL = "rtmp://cp79650.live.edgefcs.net/live/";

        vid = new Video(); //typo! was "vid = new video();"

        nc = new NetConnection();
        nc.addEventListener(NetStatusEvent.NET_STATUS, onConnectionStatus);
        nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
        nc.client = { onBWDone: function():void{} };
        nc.connect(videoURL);           
}

private function onConnectionStatus(e:NetStatusEvent):void
{
        if (e.info.code == "NetConnection.Connect.Success")
        {
            trace("Creating NetStream");
            netStreamObj = new NetStream(nc);

            metaListener = new Object();
            metaListener.onMetaData = received_Meta;
            netStreamObj.client = metaListener;

            netStreamObj.play(streamID);
            vid.attachNetStream(netStreamObj);
            addChild(vid);
            //intervalID = setInterval(playback, 1000);
        }
}

private function playback():void
{ 
  //trace((++counter) + " Buffer length: " + netStreamObj.bufferLength); 
}

public function asyncErrorHandler(event:AsyncErrorEvent):void 
{ trace("asyncErrorHandler.." + "\r"); }

public function onFCSubscribe(info:Object):void
{ trace("onFCSubscribe - succesful"); }

public function onBWDone(...rest):void
{ 
    var p_bw:Number; 
    if (rest.length > 0)
      { p_bw = rest[0]; }
    trace("bandwidth = " + p_bw + " Kbps."); 
}

function received_Meta (data:Object):void
{
    var _stageW:int = stage.stageWidth;
    var _stageH:int = stage.stageHeight;

    var _videoW:int;
    var _videoH:int;
    var _aspectH:int; 

    var Aspect_num:Number; //should be an "int" but that gives blank picture with sound
    Aspect_num = data.width / data.height;

    //Aspect ratio calculated here..
    _videoW = _stageW;
    _videoH = _videoW / Aspect_num;
    _aspectH = (_stageH - _videoH) / 2;

    vid.x = 0;
    vid.y = _aspectH;
    vid.width = _videoW;
    vid.height = _videoH;
}

    } //end class

} //end package

更新后的代码:


  1. 新演示链接: 现在是QVC(英国购物)而不是Russia Today (国际新闻)。
  2. 新增行:nc.client = { onBWDone: function():void{} };(因为Flash Player现在更加严格。在没有这一行之前,它可以正常工作。)

谢谢VC.one,它正在工作。但是当我放入我的RTMP URL时,它不起作用,似乎我的URL有一些问题,无论如何非常感谢。 - Vipul
很难说你的URL出了什么问题,但是这行代码streamID = "mp4:myVideo";听起来好像无法连接到流。试试这样写streamID = "myVideo";或者试试这个...streamID = "*********.mp4"; videoURL = "rtmp://fms.xstream.dk/";除此之外,我无法在没有完整URL的情况下提供建议。另外,如果这只是从网络上找到的链接,那么流可能以某种方式受到保护。例如:他们自己的播放器会调整公共可见链接中的某些内容以获取实际流。既然你说这是一个演示原型,也许任何其他链接都足以展示你的概念的一部分吗? - VC.One
谢谢VC.One,现在它可以工作了,但我还有一个问题,我想在我的设备(iPad2)上播放它,但是当我创建它的IPA文件并将其安装到iPad上时,它显示空白白屏幕,你有什么关于MP4视频在IOS上能否播放的想法吗?如果不能,那么有什么替代方案吗? - Vipul
很遗憾,我不使用IOS,所以对技术问题一无所知。也许它不喜欢MP4文件?尝试在你的IPA文件中使用我的链接,它是FLV格式的。另一个选择是搜索Stack Overflow。 - VC.One
我该如何使用Adobe Air在Android上实现它? - Shani Goriwal

0

也许更完整的代码应该像这样,它可以播放实时频道。

package  {
import flash.events.NetStatusEvent;
import flash.events.AsyncErrorEvent;
import flash.display.MovieClip;
import flash.net.NetStream;
import flash.net.NetConnection;
import flash.media.Video;
import flash.utils.setInterval;


public class RTMP_test extends MovieClip {


    public var netStreamObj:NetStream;
    public var nc:NetConnection;
    public var vid:Video;

    public var streamID:String;
    public var videoURL:String;
    public var metaListener:Object;

    public var intervalID:uint;
    public var counter:int;

    public function RTMP_test ()
    { init_RTMP(); }

    function init_RTMP():void
    {

            streamID  = "RT_2";
            videoURL = "rtmp://fms5.visionip.tv/live/RT_2";


            vid = new Video(); //typo! was "vid = new video();"

            nc = new NetConnection();
            nc.addEventListener(NetStatusEvent.NET_STATUS, onConnectionStatus);
            nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
            nc.connect(videoURL);          
    }

    private function onConnectionStatus(e:NetStatusEvent):void
    {
            if (e.info.code == "NetConnection.Connect.Success")
            {
                trace("Creating NetStream");
                netStreamObj = new NetStream(nc);

                metaListener = new Object();
                metaListener.onMetaData = received_Meta;
                netStreamObj.client = metaListener;

                netStreamObj.play(streamID);
                vid.attachNetStream(netStreamObj);
                addChild(vid);
                intervalID = setInterval(playback, 1000);
            }
    }

    private function playback():void
    {
      trace((++counter) + " Buffer length: " + netStreamObj.bufferLength);
    }

    public function asyncErrorHandler(event:AsyncErrorEvent):void
    { trace("asyncErrorHandler.." + "\r"); }

    public function onFCSubscribe(info:Object):void
    { trace("onFCSubscribe - succesful"); }

    public function onBWDone(...rest):void
    {
        var p_bw:Number;
        if (rest.length > 0)
          { p_bw = rest[0]; }
        trace("bandwidth = " + p_bw + " Kbps.");
    }

    function received_Meta (data:Object):void
    {
        var _stageW:int = stage.stageWidth;
        var _stageH:int = stage.stageHeight;
        var _aspectH:int;
        var _videoW:int;
        var _videoH:int;

        var relationship:Number;
        relationship = data.height / data.width;

        //Aspect ratio calculated here..
        _videoW = _stageW;
        _videoH = _videoW * relationship;
        _aspectH = (_stageH - _videoH) / 2;

        vid.x = 0;
        vid.y = _aspectH;
        vid.width = _videoW;
        vid.height = _videoH;
    }

}

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接