bytedeco / javacv

Java interface to OpenCV, FFmpeg, and more
Other
7.39k stars 1.56k forks source link

I really have no choice but to ask everyone #2233

Closed whr2349 closed 1 month ago

whr2349 commented 1 month ago

What's wrong with my code? Unable to push to srs server: public void toSrsPush(String cameraId) {

    String rtmpUrl = "rtmp://localhost/live/livestream";
    System.out.println("Starting streaming for " + cameraId);
    try (FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(cameraId);
         FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(rtmpUrl, grabber.getImageWidth(),grabber.getImageHeight(),grabber.getAudioChannels())) {
        grabber.setOption("rtsp_transport", "tcp");
        grabber.start();
        System.out.println(grabber.getFrameRate());
        System.out.println(grabber.getImageWidth());
        System.out.println(grabber.getImageHeight());
        System.out.println(grabber.getAudioChannels());
        recorder.setVideoOption("preset", "ultrafast");
        recorder.setVideoOption("tune", "zerolatency");

        // // 判断源是否为HEVC并需要重新编码
        // boolean isHEVC = grabber.getVideoCodec() == avcodec.AV_CODEC_ID_HEVC;
        //
        // // 如果源是HEVC,将录制器编解码器设置为H.264
        // if (isHEVC) {
        //     recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
        //     System.out.println("正在将HEVC重新编码为H.264");
        // }

        // 设置默认帧率
        double frameRate = 20;
        if (grabber.getFrameRate() > 0) {
            frameRate = grabber.getFrameRate();
        }

        // 设置默认视频比特率
        int videoBitrate = 4000000; // 默认为 4 Mbps
        if (grabber.getVideoBitrate() > 0) {
            videoBitrate = grabber.getVideoBitrate();
        }

        if (grabber.getAudioChannels() > 0) {
            recorder.setAudioChannels(grabber.getAudioChannels());
            recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);// 设置音频编解码器
            recorder.setSampleRate(grabber.getSampleRate());// 设置采样率
            recorder.setAudioBitrate(grabber.getAudioBitrate()); // 或使用 grabber.getAudioBitrate() 如果它返回有效值
        } else {
            recorder.setAudioChannels(0); // 设置为0表示没有音频
        }

        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
        // recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
        recorder.setFormat("flv");
        recorder.setFrameRate(frameRate);// 设置帧率
        // recorder.setSampleRate(grabber.getSampleRate());
        // recorder.setAudioBitrate(grabber.getAudioBitrate());
        recorder.setVideoBitrate(videoBitrate);

        System.out.println("Frame rate: " + frameRate);
        System.out.println("Video bitrate: " + videoBitrate);
        System.out.println("Audio channels: " + grabber.getAudioChannels());
        System.out.println("Sample rate: " + grabber.getSampleRate());
        System.out.println("Audio bitrate: " + grabber.getAudioBitrate());

        recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P); // 确保与RTMP兼容

        recorder.start(); // 启动录制器

        Frame frame;
        while ((frame = grabber.grab()) != null) {
            System.out.println("Frame grabbed: " + frame);
            recorder.record(frame); // 将捕获的帧录制到RTMP流中
        }

        recorder.stop(); // 停止录制
        grabber.stop();
        System.out.println("对 " + cameraId + " 的流媒体传输已完成");
    } catch (FrameGrabber.Exception | FrameRecorder.Exception e) {
        System.err.println("流媒体传输过程中出现错误: " + e.getMessage());
        e.printStackTrace();
    }
    // this.executeFFmpegCommand(cameraId, rtmpUrl);
}

I directly use ffmpeg push can be, the original stream is rtsp: public void executeFFmpegCommand(String rtspUrl, String rtmpUrl) { String command = "ffmpeg -rtsp_transport tcp -re -i " + rtspUrl + " -vcodec libx264 -acodec aac -f flv " + rtmpUrl; try { Process process = Runtime.getRuntime().exec(command); new Thread(() -> { BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String line; try { while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } }).start(); process.waitFor(); System.out.println("FFmpeg process exited with status " + process.exitValue()); } catch (InterruptedException | IOException e) { e.printStackTrace(); } } This is ok.

whr2349 commented 1 month ago

console: rtsp://admin:zy123456@192.168.0.7:554 Starting streaming for rtsp://admin:zy123456@192.168.0.7:554 Error: [hevc @ 000001be6d3e43c0] VPS 0 does not exist

Error: [hevc @ 000001be6d3e43c0] VPS 0 does not exist

Info: Input #0, rtsp, from 'rtsp://admin:zy123456@192.168.0.7:554':

Info: Metadata:

Info: title : Info: Media Presentation Info:

Info: Duration: Info: N/A Info: , start: Info: 0.040000 Info: , bitrate: Info: N/A Info:

Info: Stream #0:0 Info: : Video: hevc (Main), yuv420p(tv), 1920x1080 Info: , Info: 20 fps, Info: 25 tbr, Info: 90k tbn Info:

Error: [hevc @ 000001be6f8cdb40] VPS 0 does not exist

Original Frame Rate: 20.0 Image Width: 1920 Image Height: 1080 Audio Channels: 0 Adjusted Frame Rate: 20.0 Video Bitrate: 4000000 Audio Sample Rate: 0 Audio Bitrate: 0 Error: [flv @ 000001be702ea8c0] No streams to mux were specified

Error during streaming: avformat_write_header error() error -22: Could not write header to 'rtmp://localhost/live/livestream' (For more details, make sure FFmpegLogCallback.set() has been called.) org.bytedeco.javacv.FFmpegFrameRecorder$Exception: avformat_write_header error() error -22: Could not write header to 'rtmp://localhost/live/livestream' (For more details, make sure FFmpegLogCallback.set() has been called.) at org.bytedeco.javacv.FFmpegFrameRecorder.startUnsafe(FFmpegFrameRecorder.java:969) at org.bytedeco.javacv.FFmpegFrameRecorder.start(FFmpegFrameRecorder.java:437) at com.zydq.video.service.VideoStreamService.toSrsPush(VideoStreamService.java:192) at com.zydq.video.service.VideoStreamService.lambda$startRtspToSrsPushAsync$0(VideoStreamService.java:41) at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) at java.base/java.lang.Thread.run(Thread.java:842)

saudet commented 1 month ago

Duplicate of #2232