rtsp视频流存储


对rtsp视频流存储


import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author lbx
 * @date 2023/2/23 - 16:11
 **/

public class VideoRecorderService {
    static SimpleDateFormat DataFormat = new java.text.SimpleDateFormat("yyyy-MM-dd");
    static  SimpleDateFormat TimeFormat = new java.text.SimpleDateFormat("HH-mm-ss");
    private String inputFile = Constants.LBXINPUT;
    //根据当前日期+时间命名
    private String outputFile =  Constants.VIDEOOUTPUTPATH + "\\%Y-%m-%d_%H-%M-%S.mp4";

    public void startRecordVideo()
            throws Exception {

        String url = "D:\\项目\\AIO\\recorder\\" +(new java.text.SimpleDateFormat("yyyy-MM-dd")).format(new Date()) ;
        File localPath = new File(url);
        if (!localPath.exists()) {  // 获得文件目录,判断目录是否存在,不存在就新建一个
            localPath.mkdirs();
        }

        // %03d表示长度为3位,缺位的补零
        frameRecord(inputFile, outputFile,1);
    }

    /**
     * 按帧录制视频
     * @param inputFile-该地址可以是网络直播/录播地址,也可以是远程/本地文件路径
     * @param outputFile-文件地址
     * @param audioChannel
     * @throws Exception
     * @throws org.bytedeco.javacv.FrameRecorder.Exception
     */
    public void frameRecord(String inputFile, String outputFile, int audioChannel)
            throws Exception, org.bytedeco.javacv.FrameRecorder.Exception {

        boolean isStart=true;//该变量建议设置为全局控制变量,用于控制录制结束
        // 获取视频源
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile);
        // 如果不设置成tcp连接时,默认使用UDP,丢包现象比较严重
        grabber.setOption("rtsp_transport", "tcp"); // 设置成tcp以后比较稳定
        //socket网络超时时间
        grabber.setOption("stimeout","3000000");

        grabber.setImageWidth(1280);
        grabber.setImageHeight(720);
        grabber.setImageScalingFlags(0);
//        grabber.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
        // 一般来说摄像头的帧率是25
        grabber.setFrameRate(25);
        // 流媒体输出地址,分辨率(长,高),是否录制音频(0:不录制/1:录制)
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFile, 1280,720, audioChannel);
        // 设置视频编码H264
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
        //设置音频编码
        recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
        // 2000 kb/s, reasonable "sane" area for 720
//        recorder.setVideoBitrate(4000000);
//        recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
//        recorder.setPixelFormat(0);
        //过滤掉日志
        avutil.av_log_set_level(avutil.AV_LOG_ERROR);

        recorder.setOption("strftime", "1"); //根据日期生成文件名

        recorder.setFormat("segment");
        //十秒钟一切
        recorder.setOption("segment_time", "10");
        recorder.setOption("segment_filename", "10");
        //生成模式:live(实时生成)、cache(边缓存边生成,只支持m3u8清单文件缓存)
        recorder.setOption("segment_list_flags", "live");
        //强制锁定切片时长
        recorder.setOption("segment_atclocktime", "1");
        //使得每段视频都是从零开始计时
        recorder.setOption("reset_timestamps", "1");
        //设置帧率
        recorder.setFrameRate(25);

        //因为是直播,如果需要保证最小延迟,gop最好设置成帧率相同或者帧率*2
        //一个gop表示关键帧间隔,假设25帧/秒视频,gop是50,
        //则每隔两秒有一个关键帧,播放器必须加载到关键帧才能开始解码播放,就是说直播流最多两秒延迟
        recorder.setGopSize(50);//设置gop
        recorder.setVideoQuality(0.8);//视频质量
        recorder.setVideoBitrate(2000000);//码率,10kb/s

        // 在视频质量和编码速度之间选择适合自己的方案,包括这些选项:
        // ultrafast,superfast, veryfast, faster, fast, medium, slow, slower, veryslow
        // ultrafast offers us the least amount of compression (lower encoder CPU) at the cost of a larger stream size
        // at the other end, veryslow provides the best compression (high encoder CPU) while lowering the stream size
        // (see: https://trac.ffmpeg.org/wiki/Encode/H.264)
        // ultrafast对CPU消耗最低
        // recorder.setVideoOption("preset", "veryslow");

        // 开始取视频源
        recordByFrame(grabber, recorder, isStart);
    }

    private void recordByFrame(FFmpegFrameGrabber grabber, FFmpegFrameRecorder recorder, Boolean status)
            throws Exception, org.bytedeco.javacv.FrameRecorder.Exception {
        try {//建议在线程中使用该方法
            grabber.start();
            recorder.start();

            Frame frame = null;
            while (status&& (frame = grabber.grabFrame()) != null) {
                recorder.record(frame);
                //1.用线程sleep
                //2.获取当前时间,做时间差
                //3.@Scheduled

            }
            recorder.stop();
            grabber.stop();
        } catch (org.bytedeco.javacv.FrameRecorder.Exception e) {
            try {
                e.printStackTrace();
                System.out.println("录制器启动失败,正在重新启动...");
                if (recorder != null) {
                    System.out.println("尝试关闭录制器");
                    recorder.stop();
                    grabber.stop();
                    System.out.println("尝试重新开启录制器");
//                    recorder.start();
                    frameRecord(inputFile,outputFile,1);
                }
            } catch (org.bytedeco.javacv.FrameRecorder.Exception e1) {
                throw e;
            }
        }finally {
            if (grabber != null) {
                grabber.stop();
            }
        }
    }



}


文章作者: Luan-bx
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Luan-bx !
  目录