如何在Red5 IServerStream中添加直播源?

时间:2013-10-09 11:13:12

标签: video streaming server-side live red5

问题

我已经在这个基于oflaDemo的自定义应用程序中创建并启动了Red5服务器端流:

serverStream = StreamUtils.createServerStream( app , "mystream" );

// repeats /streams/prometheus.flv from oflaDemo several times (20sec):
serverStream.addItem( SimplePlayItem.build( "prometheus" , 0 , 20000 ) );
serverStream.addItem( SimplePlayItem.build( "prometheus" , 0 , 20000 ) );

// now I want to add "camsource" stream, wich is published from Flash client:
serverStream.addItem( SimplePlayItem.build( "camsource" , 0 , 20000 ) );
...
serverStream.play();
prometheus.flv很好地播放2倍,但是当“camsource”出现时,结果是:

[Red5_Scheduler_Worker-3] org.red5.server.stream.ProviderService - Exception attempting to lookup file: ServletContext resource [/streams/camsource.flv] cannot be resolved to URL because it does not exist

如何创建重新发布从Flash客户端发布的用户流的IServerStream?

我可以在Flash中通过NetStream .play(...)看到flv stream和cam stream,但我无法以编程方式创建IServerStream以从实时源发布。

comsource发布和serverStream属于同一范围。

我目前的工作路径

由于This response on Red5 group,我创建了自己的ServerStream,我可以手动推送重定向/伪数据包(我不确定这是否正确完成):

public static class LiveTVServerStream extends ServerStream {

    public void manuallyPushPacket( IStreamPacket packet ) {
        for ( IStreamListener listener : getStreamListeners() ) {
            listener.packetReceived( this , packet );
        }
    }
}

然后我创建这样的流并在appStart()中注册它:

liveTVServerStream = new LiveTVServerStream();
liveTVServerStream.setScope( appScope );
liveTVServerStream.setName( "livetv" );
liveTVServerStream.setPublishedName( "livetv" );
// Add single starting video because ServerStream requires at least 1 item
liveTVServerStream.addItem( SimplePlayItem.build( "prometheus" , 0 , 20000 ) );
liveTVServerStream.start();

IContext context = scope.getContext();
IProviderService providerService = (IProviderService) context.getBean( IProviderService.BEAN_NAME );
providerService.registerBroadcastStream( scope , "livetv" , liveTVServerStream);

然后,如果我的“新闻记者”(来自Flash的网络摄像头的视频源)开始广播,我将数据包重定向到liveTVServerStream

public void streamPublishStart( final IBroadcastStream stream ) {
   if ( !stream.getPublishedName().equals( "newsreporter" ) ) {
      return;
   }

logInfo( "News reporter connected - redirecting packets" );
    stream.addStreamListener( new IStreamListener() {
        volatile int dispatchedPacketCount = 0;
        volatile int ignoredPacketCount = 0;

        @Override
        public void packetReceived( IBroadcastStream newsReporterStream , IStreamPacket packet ) {
            if ( packet instanceof IRTMPEvent ) {
                dispatchedPacketCount++;
                if ( (dispatchedPacketCount % 50) == 0 ) {
                    logInfo( "Dispatched packets: " + dispatchedPacketCount + " ignored packets: " + ignoredPacketCount );
                }

                // delta-time calculations
                long t1 = newsReporterStream.getCreationTime();
                long t2 = liveTVServerStream.getCreationTime();
                long delta = t2 - t1;
                int t3 = ((IRTMPEvent) packet).getTimestamp();
                t3 += delta;
                ((IRTMPEvent) packet).setTimestamp( t3 );

                liveTVServerStream.manuallyPushPacket( packet );
            } else {
                ignoredPacketCount++;
            }

        }
    } );

当前结果

可以找到Red5控制台的日志here

“新闻记者”闪存工作正常 - 从网络摄像头发送视频。但是当我订阅“livetv”流时,没有视频。 Flash部件可以工作 - 使用ServerStream对其进行测试,其中包含几个队列中的.flv文件和Flash连接&像电视直播一样正确播放。

1 个答案:

答案 0 :(得分:2)

使用ClientBroadcastStream

成功解决了问题
liveTVClientStream = new ClientBroadcastStream();
liveTVClientStream.setScope( app);


IContext context = scope.getContext();
IProviderService providerService = (IProviderService) context.getBean( IProviderService.BEAN_NAME );
providerService.registerBroadcastStream( scope , "livetv" , liveTVClientStream );

liveTVClientStream.setPublishedName( "livetv");
liveTVClientStream.setName( "livetv");

现在我们可以在另一个流上设置监听器并将IStreamPacket转换为IRTMPEvent并将其放入我们的主流.dispatchEvent