无法呈现red5录制的媒体流

时间:2016-05-31 09:46:54

标签: java streaming red5

我有从red5发布的流回放录制的媒体文件的问题,以下是我的代码。我可以看到一个名为out.flv的文件被创建,但是这个out.flv无法播放。

public class Red5ClientTest {

    private static Timer timer;

    private static RTMPClient client;

    private static String sourceStreamName;

    private static int videoTs;

    private static int audioTs;

    private static FLVWriter writer;

    private static int bytesRead =0;

    public static void main(String[] args) throws IOException {
        String sourceHost = "localhost";
        int sourcePort = 1935;
        String sourceApp = "oflaDemo";
        sourceStreamName = "myStream";
        timer = new Timer();        

        client = new RTMPClient();

        String path = "c:\\temp\\out.flv";
        File file = new File(path);
        if (!file.exists()) {
            file.createNewFile();
        }
        writer = new FLVWriter(file,true);

        client.setStreamEventDispatcher(new StreamEventDispatcher());
        client.setStreamEventHandler(new INetStreamEventHandler() {
            public void onStreamEvent(Notify notify) {
                System.out.printf("onStreamEvent: %s\n", notify);
                ObjectMap<?, ?> map = (ObjectMap<?, ?>) notify.getCall().getArguments()[0];
                String code = (String) map.get("code");
                System.out.printf("<:%s\n", code);
                if (StatusCodes.NS_PLAY_STREAMNOTFOUND.equals(code)) {
                    System.out.println("Requested stream was not found");
                    client.disconnect();

                }
                else if (StatusCodes.NS_PLAY_UNPUBLISHNOTIFY.equals(code)
                        || StatusCodes.NS_PLAY_COMPLETE.equals(code)) {
                    System.out.println("Source has stopped publishing or play is complete");
                    client.disconnect();
                }
            }
        });
        client.setConnectionClosedHandler(new Runnable() {
            public void run() {
                if (writer != null) {
                    writer.close();

                }
                System.out.println("Source connection has been closed, proxy will be stopped");
                System.exit(0);
            }
        });
        client.setExceptionHandler(new ClientExceptionHandler() {
            @Override
            public void handleException(Throwable throwable) {
                throwable.printStackTrace();
                System.exit(1);
            }
        });

        // connect the consumer
        Map<String, Object> defParams = client.makeDefaultConnectionParams(sourceHost, sourcePort,
                sourceApp);
        // add pageurl and swfurl
        defParams.put("pageUrl", "");
        defParams.put("swfUrl", "app:/Red5-StreamRelay.swf");
        // indicate for the handshake to generate swf verification data
        client.setSwfVerification(true);
        // connect the client
        client.connect(sourceHost, sourcePort, defParams, new IPendingServiceCallback() {
            public void resultReceived(IPendingServiceCall call) {
                System.out.println("connectCallback");
                ObjectMap<?, ?> map = (ObjectMap<?, ?>) call.getResult();
                String code = (String) map.get("code");
                if ("NetConnection.Connect.Rejected".equals(code)) {
                    System.out.printf("Rejected: %s\n", map.get("description"));
                    client.disconnect();
                    //proxy.stop();
                }
                else if ("NetConnection.Connect.Success".equals(code)) {
                    // 1. Wait for onBWDone
                    timer.schedule(new BandwidthStatusTask(), 2000L);
                    Object result = call.getResult();
                    System.out.println("Red5ClientTest.main()");
                }
                else {
                    System.out.printf("Unhandled response code: %s\n", code);
                }
            }
        });

        // keep sleeping main thread while the proxy runs

        // kill the timer
        //timer.cancel();
        System.out.println("Stream relay exit");

    }

    /**
     * Handles result from subscribe call.
     */
    private static final class SubscribeStreamCallBack implements IPendingServiceCallback {

        public void resultReceived(IPendingServiceCall call) {
            System.out.println("resultReceived: " + call);
            Object result = call.getResult();
            System.out.println("results came {}" + result);
        }

    }

    private static final class StreamEventDispatcher implements IEventDispatcher {

        public void dispatchEvent(IEvent event) {
            System.out.println("ClientStream.dispachEvent()" + event.toString());
            try {

                //RTMPMessage build = RTMPMessage.build((IRTMPEvent) event);




                IRTMPEvent rtmpEvent = (IRTMPEvent) event;
                ITag tag = new Tag();
                tag.setDataType(rtmpEvent.getDataType());
                if (rtmpEvent instanceof VideoData) {
                    videoTs += rtmpEvent.getTimestamp();
                    tag.setTimestamp(videoTs);
                }
                else if (rtmpEvent instanceof AudioData) {
                    audioTs += rtmpEvent.getTimestamp();
                    tag.setTimestamp(audioTs);
                }


                IoBuffer data = ((IStreamData) rtmpEvent).getData().asReadOnlyBuffer();
                tag.setBodySize(data.limit());
                tag.setBody(data);
                try {
                    writer.writeTag(tag);

                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                System.out.println("writting....");    


            }
            catch (Exception e) {//IOException
                e.printStackTrace();
            }
        }

    }

    private static final class BandwidthStatusTask extends TimerTask {

        @Override
        public void run() {
            // check for onBWDone
            System.out.println("Bandwidth check done: " + client.isBandwidthCheckDone());
            // cancel this task
            this.cancel();
            // create a task to wait for subscribed
            timer.schedule(new PlayStatusTask(), 1000L);
            // 2. send FCSubscribe
            client.subscribe(new SubscribeStreamCallBack(), new Object[] { sourceStreamName });
        }

    }

    private static final class PlayStatusTask extends TimerTask {

        @Override
        public void run() {
            // checking subscribed
            System.out.println("Subscribed: " + client.isSubscribed());
            // cancel this task
            this.cancel();
            // 3. create stream
            client.createStream(new CreateStreamCallback());
        }

    }

    /**
     * Creates a "stream" via playback, this is the source stream.
     */
    private static final class CreateStreamCallback implements IPendingServiceCallback {

        public void resultReceived(IPendingServiceCall call) {
            System.out.println("resultReceived: " + call);
            int streamId = ((Number) call.getResult()).intValue();
            System.out.println("stream id: " + streamId);
            // send our buffer size request
            if (sourceStreamName.endsWith(".flv") || sourceStreamName.endsWith(".f4v")
                    || sourceStreamName.endsWith(".mp4")) {
                client.play(streamId, sourceStreamName, 0, -1);
            }
            else {
                client.play(streamId, sourceStreamName, -1, 0);
            }
        }

    }

}

我在这里可能做错了什么?

1 个答案:

答案 0 :(得分:1)

终于搞定了

public class TeqniRTMPClient {

    private static final Logger logger = LoggerFactory.getLogger(MyRtmpClient.class);

    public static void main(String args[]) throws IOException {
        TeqniRTMPClient client = new TeqniRTMPClient("localhost", 1935, "oflaDemo", "myStream");
        client.recordStream();
    }

    private RTMPClient client;

    private ITagWriter writer;

    private String sourceHost;

    private int sourcePort;

    private String sourceApp;

    private String sourceStreamName;

    private int lastTimestamp;

    private int startTimestamp = -1;

    public TeqniRTMPClient(String sourceHost, int sourcePort, String sourceApp,
            String sourceStreamName) {
        super();
        this.sourceHost = sourceHost;
        this.sourcePort = sourcePort;
        this.sourceApp = sourceApp;
        this.sourceStreamName = sourceStreamName;
    }

    public void recordStream() throws IOException {
        client = new RTMPClient();

        String path = "c:\\temp\\out.flv";
        File file = new File(path);
        if (!file.exists()) {
            file.createNewFile();
        }

        FLVService flvService = new FLVService();
        flvService.setGenerateMetadata(true);
        try {
            IStreamableFile flv = flvService.getStreamableFile(file);
            writer = flv.getWriter();
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }



        client.setStreamEventDispatcher(new StreamEventDispatcher());
        client.setStreamEventHandler(new INetStreamEventHandler() {
            public void onStreamEvent(Notify notify) {
                System.out.printf("onStreamEvent: %s\n", notify);
                ObjectMap<?, ?> map = (ObjectMap<?, ?>) notify.getCall().getArguments()[0];
                String code = (String) map.get("code");
                System.out.printf("<:%s\n", code);
                if (StatusCodes.NS_PLAY_STREAMNOTFOUND.equals(code)) {
                    System.out.println("Requested stream was not found");
                    client.disconnect();

                }
                else if (StatusCodes.NS_PLAY_UNPUBLISHNOTIFY.equals(code)
                        || StatusCodes.NS_PLAY_COMPLETE.equals(code)) {
                    System.out.println("Source has stopped publishing or play is complete");
                    client.disconnect();

                }
            }
        });
        client.setExceptionHandler(new ClientExceptionHandler() {
            @Override
            public void handleException(Throwable throwable) {
                throwable.printStackTrace();
                System.exit(1);
            }
        });

        client.setConnectionClosedHandler(new Runnable() {
            public void run() {
                if (writer != null) {
                    writer.close();

                }
                System.out.println("Source connection has been closed, proxy will be stopped");
                System.exit(0);
            }
        });

        // connect the consumer
        Map<String, Object> defParams = client.makeDefaultConnectionParams(sourceHost, sourcePort,
                sourceApp);
        // add pageurl and swfurl
        defParams.put("pageUrl", "");
        defParams.put("swfUrl", "app:/Red5-StreamRelay.swf");
        // indicate for the handshake to generate swf verification data
        client.setSwfVerification(true);
        // connect the client
        client.connect(sourceHost, sourcePort, defParams, new IPendingServiceCallback() {
            public void resultReceived(IPendingServiceCall call) {
                System.out.println("connectCallback");
                ObjectMap<?, ?> map = (ObjectMap<?, ?>) call.getResult();
                String code = (String) map.get("code");
                if ("NetConnection.Connect.Rejected".equals(code)) {
                    System.out.printf("Rejected: %s\n", map.get("description"));
                    client.disconnect();
                }
                else if ("NetConnection.Connect.Success".equals(code)) {
                    // 1. Wait for onBWDone
                    client.createStream(new CreateStreamCallback());
                    Object result = call.getResult();
                    System.out.println("Red5ClientTest.main()");
                }
                else {
                    System.out.printf("Unhandled response code: %s\n", code);
                }
            }
        });
    }

    class CreateStreamCallback implements IPendingServiceCallback {

        public void resultReceived(IPendingServiceCall call) {
            System.out.println("resultReceived: " + call);
            int streamId = ((Number) call.getResult()).intValue();
            System.out.println("stream id: " + streamId);
            // send our buffer size request
            if (sourceStreamName.endsWith(".flv") || sourceStreamName.endsWith(".f4v")
                    || sourceStreamName.endsWith(".mp4")) {
                client.play(streamId, sourceStreamName, 0, -1);
            }
            else {
                client.play(streamId, sourceStreamName, -1, 0);
            }
        }

    }

    class StreamEventDispatcher implements IEventDispatcher {

        private int videoTs;

        private int audioTs;

        public void dispatchEvent(IEvent event) {
            System.out.println("ClientStream.dispachEvent()" + event.toString());
            try {



                IRTMPEvent rtmpEvent = (IRTMPEvent) event;
                logger.debug("rtmp event: " + rtmpEvent.getHeader() + ", "
                        + rtmpEvent.getClass().getSimpleName());
                if (!(rtmpEvent instanceof IStreamData)) {
                    logger.debug("skipping non stream data");
                    return;
                }
                if (rtmpEvent.getHeader().getSize() == 0) {
                    logger.debug("skipping event where size == 0");
                    return;
                }

                byte dataType = rtmpEvent.getDataType();
                ITag tag = new Tag();
                tag.setDataType(dataType);
                if (rtmpEvent instanceof VideoData) {
                    VideoData video = (VideoData) rtmpEvent;
                    FrameType frameType = video.getFrameType();
                    videoTs += rtmpEvent.getTimestamp();
                    tag.setTimestamp(videoTs);
                }
                else if (rtmpEvent instanceof AudioData) {
                    audioTs += rtmpEvent.getTimestamp();
                    tag.setTimestamp(audioTs);
                }

                IoBuffer data = ((IStreamData) rtmpEvent).getData().asReadOnlyBuffer();
                tag.setBodySize(data.limit());
                tag.setBody(data);
                try {

                    writer.writeTag(tag);

                }
                catch (Exception e) {
                    throw new RuntimeException(e);
                }
                System.out.println("writting....");



            }
            catch (Exception e) {//IOException
                e.printStackTrace();
            }
        }

    }
}