VUE3+javaCV realizes long-term video recording

Table of Contents

need

accomplish

The front-end plays the picture of Hikvision camera

Record video

Method 1: HTMLVideoElement (obsolete)

Method 2: HTMLCanvasElement (obsolete)

Method three: javaCV

code

question

Requirement

The front end receives the hls stream converted from rtsp by webrtc-streamer

Click the start button to start recording for a while

Click the Stop button to stop recording

Click Upload to save the video to the server

implementation

Front-end playback of Hikvision camera images

Since surveillance equipment mostly uses rtsp streaming to transmit video, H5 cannot receive this type of video stream, so webrtc-streamer is used for streaming and playback.

Record video
Method 1: HTMLVideoElement (obsolete)

1. Use the caputure of HTMLVideoElement to capture the video stream being played in the video component.

2. Put the video stream into the list

3. Convert the list to blob data type

4. Use axios to transfer the stored blob data to the backend

5. The backend receives the blob data and stores it on the disk, and stores the path in the database.

Disadvantages: Traditional HTML can be implemented, but the HTMLElement in ts format adapted to vue3 does not yet provide the HTMLVideoElement.captureStreamer method.

Method 2: HTMLCanvasElement (obsolete)

1. Use the video component to play videos

2. Draw video to canvas

3. Capture canvas media stream

4. Use axios to transfer the stored blob data to the backend

5. The backend receives the blob data and stores it on the disk, and stores the path in the database.

Disadvantages: Draw the video to the canvas, and then capture the media stream of the canvas, suitable for second-level recording

Method 3: javaCV

1. The front-end obtains the timestamp and task information and transmits them to the back-end

2. The backend uses javaCV to pull the rtsp stream, read the frame, and record the angle frame according to the timestamp.

Benefits: Suitable for long-term video storage

code

public class SceneService {
    private volatile boolean stopFlag = false;
    private volatile String videoPath;
    private final SceneMapper sceneMapper;
    private FFmpegFrameGrabber grabber;
    private FFmpegFrameRecorder videoWriter;
    private Thread videoThread;
    @Autowired
    public SceneService(SceneMapper sceneMapper){
        this.sceneMapper = sceneMapper;
    }
    public void recordVideo(String taskName){
        //Set rtsp stream address
        String rtspUrl = "rtsp://your username:your [email protected]:8554/stream";
        //Set the save path
        String rootDir = "E:\ProgramSoftware\java\AIDetectCloudPlatform\recordVideo";
        String fileName = taskName + ".mp4";
        this.videoPath = Paths.get(rootDir, fileName).toString();
        // Use the FFmpegFrameGrabber class to pull the rtsp stream
        try {
            grabber = FFmpegFrameGrabber.createDefault(rtspUrl);
            // disable audio
            grabber.setOption("rtsp_transport", "tcp");
            grabber.start();

            System.out.println("Start streaming");
            // Set up video reader
            int width = grabber.getImageWidth();
            int height = grabber.getImageHeight();
            videoWriter = new FFmpegFrameRecorder(this.videoPath, width, height);
            videoWriter.setFormat("mp4");
            videoWriter.setAudioChannels(2);
            videoWriter.start();
            System.out.println("Start recording");
            //Create a new thread to handle the loop
            this.videoThread = new Thread(() -> {
                try {
                    while (!this.videoThread.isInterrupted() & amp; & amp; !this.stopFlag) {
                        Frame frame = grabber.grab();
                        if (frame == null) {
                            System.out.println("End of record");
                            break;
                        }
                        long currentTimestamp = frame.timestamp;
                        System.out.printf("frame timeStamp %s \
", currentTimestamp);
                        // Store to target address
                        videoWriter.record(frame);
                    }
                    videoWriter.stop();
                    grabber.stop();
                    this.stopFlag = false;
                }catch (Exception e){
                    e.printStackTrace();
                }
            });
            this.videoThread.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void stopRecordVideo(String taskId) {
        this.stopFlag = true;
        // Close the thread
        if ( this.videoThread != null & amp; & amp; this.videoThread.isAlive()) {
            System.out.println("End of record");
            this.videoThread.interrupt();
        }
        //Associate the video with the task
        sceneMapper.collectTaskVideo(taskId, this.videoPath);
    }
}

Question

1. Traditional HTML provides the media stream captureStream method for the video component. The HTMLELEMNT adapted to the ts used by vue3 does not yet provide a method for directly extracting the media stream from the video component.

2. Redraw the video to the canvas. HTMLELEMENT provides a method to obtain the media stream of the canvas, but it is only suitable for short-term recording.

3. Error: java.lang.UnsatisfiedLinkError: Could not find jniavutil in class, module, and library paths.

Only javacv dependency is introduced, and ffmepg-platform needs to be introduced.

4. Error: No audio output stream (Is audioChannels > 0 and has start() been called?)

setAudioChannels is not set for instance object of FFmpegFrameRecorder class