ImageIO.write () зависает после ~ 540 итераций - PullRequest
0 голосов
/ 14 октября 2019

В настоящее время я пытаюсь написать простой аудио-визуализатор (не в реальном времени), но столкнулся с очень странной проблемой.

После примерно 515-545 итераций ImageIO.write () программа зависает;без исключений, программа не аварийно завершает работу, просто ничего.

Прежде чем читать код, приведенный ниже, приведем его краткое изложение, чтобы его было легче понять:
1. Загрузка данных изпрограммные аргументы.
2. Запустите ffmpeg с его входом, установленным в stdin.
3. В цикле;Постоянно визуализируйте изображение, затем отправьте его в ffmpeg с помощью ImageIO.write ().

Другая информация:
Я подтвердил, что ImageIO.write () действительно является проблемой, помещая печать до и после оператора try / catch.
Моей первой мыслью была утечка памяти, нопохоже, что это не так, по крайней мере, в соответствии с Runtime.getRuntime (). freeMemory ();
Итерации, необходимые для остановки программы, противоречивы, хотя всегда находились в диапазоне 515-540.
Рендеринг видео с меньшим количеством кадров работает безупречно.
Моим предыдущим решением было записать все изображения в папку, а затем запустить ffmpeg для них всех сразу. Это работало нормально на любом количестве кадров, но использовало более гигабайта дискового пространства для довольно небольшого тестового видео, что недопустимо для небольшой программы, которую я пытаюсь создать.

В заключение я понимаю, чтокод, вероятно, имеет массу проблем оптимизации / общих проблем, у меня не было времени, чтобы попытаться заставить его работать хорошо, поскольку он еще даже не работает полностью.
С учетом вышесказанного, если вы видите какие-либо очевидные проблемыНе стесняйтесь включать их в свой ответ, если у вас есть время, это, безусловно, спасет меня.

Спасибо

public class Run {

    public static BufferedImage render = new BufferedImage(1920, 1080, BufferedImage.TYPE_INT_RGB);

    public static Graphics buffer = render.getGraphics();

    public static int frame = 0;

    public static double[] bins = new double[3200];
    public static double[] previousBins = new double[3200];

    public static File audio;

    public static BufferedImage background;

    public static OutputStream output;

    public static void main(String[] args) {
        try {
            String command = "cd /Users/admin/Desktop/render ; ffmpeg -r 60 -blocksize 150000 -i pipe:0 -i " + args[1].replaceAll(" ", "\\\\ ") + " final.mp4";

            System.out.println(command);

            ProcessBuilder processBuilder = new ProcessBuilder("bash", "-c", command);

            Process process = processBuilder.start();

            output = process.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            background = ImageIO.read(new File(args[0]));
        } catch (IOException e) {
            System.out.println("File not found");
        }

        audio = new File(args[1]);

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        BufferedInputStream in = null;

        try { in = new BufferedInputStream(new FileInputStream(audio));
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        }

        try {
            out.flush();

            int read;

            byte[] buff = new byte[3200];

            while ((read = in .read(buff)) > 0) {
                out.write(buff, 0, read);
            }
        } catch (IOException e1) {
            e1.printStackTrace();
        }

        byte[] audioBytes = out.toByteArray();

        System.out.println("Calculating length");

        int frames = 600;

        System.out.println("Rendering images");

        int[] data = new int[3200];

        int index = 0;

        while (frame < frames) {
            for (int i = 0; i < 3200; i++) {
                data[i] = (short)(audioBytes[index + 2] << 16 | audioBytes[index + 1] << 8 | audioBytes[index] & 0xff);

                index += 3;
            }

            index -= 4800;

            fourier(data, bins);

            renderImage();

            try {
                ImageIO.write(render, "jpg", output);
            } catch (IOException e) {
                e.printStackTrace();
            }

            frame++;

            if (frame % 20 == 0) {
                System.out.println(frame + "/" + frames + " frames completed");
            }
        }

        System.out.println("Render completed");

        System.out.println("Optimizing file size");

        System.out.println("Optimization complete");

        System.out.println("Program complete");

        System.exit(0);
    }

    public static void renderImage() {
        buffer.drawImage(background, 0, 0, null);

        for (int i = 0; i < 110; i++) {
            int height = (int)((bins[i] + previousBins[i]) / Short.MAX_VALUE);

            buffer.fillRect(15 * i + 20, 800 - height, 10, (int)(height * 1.2));
        }

        System.arraycopy(bins, 0, previousBins, 0, 3200);
    }

    public static void fourier(int[] inReal, double[] out) {
        for (int k = 0; k < inReal.length; k++) {
            double real = 0.0;
            double imaginary = 0.0;

            for (int t = 0; t < inReal.length; t++) {
                real += inReal[t] * Math.cos(2 * Math.PI * t * k / inReal.length);
                imaginary -= inReal[t] * Math.sin(2 * Math.PI * t * k / inReal.length);
            }

            out[k] = Math.sqrt(Math.pow(real, 2) + Math.pow(imaginary, 2));
        }
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...