describe

Spring Boot introduced JavaCV to do video image processing, of course the preferred FFmpeg, heart broken read, open source things is easy to use. So para para coding for a whole day, to achieve RTMP streaming media push, every interval capture frame pictures, streaming media transferred to MP4 for playback after saving three main functions.

After finishing the Jar package, the size of 560M, god!! Exclusions for a while.

Crumble crumble crumble!!

Run it, two RTSP streams, very easy! CPU usage is less than 10%, and 1.1G of memory is acceptable.

So, send it to the server and start… Two RTSP streams, CPU decisively up to 260%… Screwed!!

So began to tune, video decoding really consume resources, helpless……

The JVM looks for problems & tuning

Online all kinds of this article, here do not do more introduction, is generally two steps, first look for CPU high thread; Then go to the thread’s record and see what’s wrong.

Found the problem

JavaCV parses streaming media, which is resource-intensive and unsolvable.

The best solution, then, is not to parse the video. FFmpeg supports codec copy, while JavaCV can also be implemented via AVPacket.

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.bytedeco.javacv.*;

import org.bytedeco.ffmpeg.avcodec.AVPacket;

public class PacketRecorderTest {

    private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMdd__hhmmSSS");

    private static final int RECORD_LENGTH = 5000;

    private static final boolean AUDIO_ENABLED = false;

    public static void main(String[] args) throws FrameRecorder.Exception, FrameGrabber.Exception {

        String inputFile = "/home/usr/videos/VIDEO_FILE_NAME.mp4";

        // Decodes-encodes
        String outputFile = "/tmp/" + DATE_FORMAT.format(new Date()) + "_frameRecord.mp4";
        PacketRecorderTest.frameRecord(inputFile, outputFile);

        // copies codec (no need to re-encode)
        outputFile = "/tmp/" + DATE_FORMAT.format(new Date()) + "_packetRecord.mp4";
        PacketRecorderTest.packetRecord(inputFile, outputFile);

    }

    public static void frameRecord(String inputFile, String outputFile) throws FrameGrabber.Exception, FrameRecorder.Exception {

        int audioChannel = AUDIO_ENABLED ? 1 : 0;

        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile);
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFile, 1280.720, audioChannel);

        grabber.start();
        recorder.start();

        Frame frame;
        long t1 = System.currentTimeMillis();
        while ((frame = grabber.grabFrame(AUDIO_ENABLED, true.true.false)) != null) {
            recorder.record(frame);
            if ((System.currentTimeMillis() - t1) > RECORD_LENGTH) {
                break;
            }
        }
        recorder.stop();
        grabber.stop();
    }

    public static void packetRecord(String inputFile, String outputFile) throws FrameGrabber.Exception, FrameRecorder.Exception {

        int audioChannel = AUDIO_ENABLED ? 1 : 0;

        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputFile);
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputFile, 1280.720, audioChannel);

        grabber.start();
        recorder.start(grabber.getFormatContext());

        AVPacket packet;
        long t1 = System.currentTimeMillis();
        while((packet = grabber.grabPacket()) ! =null) {
            recorder.recordPacket(packet);
            if ((System.currentTimeMillis() - t1) > RECORD_LENGTH) {
                break; } } recorder.stop(); grabber.stop(); }}Copy the code

Feel it. It still works. However, when streaming media conversion, there are always various problems.

The final solution

Crumble crumble crumble!!

Instead, call FFmpeg directly using Process.

import org.bytedeco.javacpp.Loader;

import java.io.IOException;

public class CommondTest {

    public static void main(String[] args) throws IOException, InterruptedException {
        String ffmpeg = Loader.load(org.bytedeco.ffmpeg.ffmpeg.class);
        String from = "rtsp://*************";
        String to = "rtmp://********************";
        ProcessBuilder pb = new ProcessBuilder(ffmpeg,
            "-i", from, "-codec"."copy"."-f"."flv"."-y", to); Process process = pb.inheritIO().start(); process.waitFor(); }}Copy the code

After testing it, it still works, so we can start our transformation!

Learn the FFmpeg command

The best way to learn knowledge is always the official website, for authoritative FFMPEG Documentation

When calling in Java, set up the output so that the output stream from the command line does not get clogged because it is not read!

Set the loglevel to -loglevel quiet

The CPU down

Down at last!

After the technical problem is solved, the remaining screenshots call the fault identification interface of a certain cloud and give a real-time alarm…

Crumble crumble crumble!! A certain cloud provides 5 interfaces for image fault recognition, and each screenshot has to call 5 interfaces respectively…… It seems inevitable to use asynchrony…

Server Information (4-core 8G/ 2.4ghz)

Basic information: the server CPU cat/proc/cpuinfo | grep name | the cut – f2 – d: | uniq -c

4  Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GHz
Copy the code

Basic server memory information: cat /proc/meminfo

MemTotal:        8008500 kB
Copy the code

Physical cpus: a cat/proc/cpuinfo | grep “physical id” | sort | uniq | wc -l

1
Copy the code

Auditing: cat/proc/cpuinfo | grep “CPU cores” | uniq

cpu cores	: 2
Copy the code

The number of logical CPU: cat/proc/cpuinfo | grep “processor” | wc -l

4
Copy the code

Resource consumption: CPU consumption 20.3%, memory consumption 1.3g

Top-18:14:33 Up 17 days, 7 min, 1 user, load Average: 1.03, 0.92, 0.80 Tasks: 105 total, 1 running, 104 sleeping, 0 stopped, 0 zombie %Cpu(s): 20.3US, 0.6sy, 0.0Ni, 78.7 ID, 0.0wa, 0.0hi, 0.3Si, 0.1st KiB Mem: 8008500 total, 120588 free, 1940580 used, 5947332 buff/cache KiB Swap: 0 total, 0 free, 0 Used.5368844 Avail Mem PID USER PR NI VIRT RES SHR S %CPU % Mem TIME+ COMMAND 28360 root 20 0 6307744 1.3g 24644s 83.4 16.4 42:04. 91 JavaCopy the code

View nic traffic: watch – n 1 “/ sbin/ifconfig eth0 | grep bytes.” “

        RX packets 234768965  bytes 315037366631 (293.4 GiB)
        TX packets 224227493  bytes 113722298707 (105.9 GiB)
Copy the code