孟夏草木长 2020-05-22 14:52 采纳率: 0%
浏览 3154

FFmpegFrameRecorder录制视频的问题?

# 现在遇到的问题就是:在使用FFmpegFrameRecorder录制桌面的时候,如果设置的格式是 AV_CODEC_ID_MPEG4 就能生成一个视频,如果格式设置为AV_CODEC_ID_H264 格式就会出现

这样的异常,并且生成的文件为0KB,

想要的效果就是能给输出一个 h264编码格式的视频文件

org.bytedeco.javacv.FrameRecorder$Exception: avcodec_encode_video2() error -542398533: Could not encode video packet.
at org.bytedeco.javacv.FFmpegFrameRecorder.recordImage(FFmpegFrameRecorder.java:946)
at org.bytedeco.javacv.FFmpegFrameRecorder.record(FFmpegFrameRecorder.java:855)
at org.bytedeco.javacv.FFmpegFrameRecorder.record(FFmpegFrameRecorder.java:848)
at com.media.cqrcb.util.VideoRecode$1.run(VideoRecode.java:134)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
[libx264 @ 1671ec00] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
[libx264 @ 1671ec00] profile High, level 5.0
[libx264 @ 1671ec00] 264 - core 152 - H.264/MPEG-4 AVC codec - Copyleft 2003-2017 - http://www.videolan.org/x264.html - options: cabac=1 ref=5 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=8 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=2 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=12 lookahead_threads=2 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=3 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=50 rc=abr mbtree=1 bitrate=100 ratetol=1.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
Output #0, mp4, to 'video/2020-05-22 144200.mp4':
Metadata:
encoder : Lavf57.83.100
Stream #0:0: Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p, 1920x1080, q=2-31, 100 kb/s, 15360 tbn
Stream #0:1: Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 64 kb/s
[libx264 @ 1671ec00] lookahead thread is already stopped
[libx264 @ 1671ec00] internal error (MV out of thread range)
[libx264 @ 1671ec00] recovering by using intra mode
[libx264 @ 1671ec00] internal error (MV out of thread range)
[libx264 @ 1671ec00] recovering by using intra mode
[libx264 @ 1671ec00] internal error (MV out of thread range)
[libx264 @ 1671ec00] recovering by using intra mode
[libx264 @ 1671ec00] internal error (MV out of thread range)
[libx264 @ 1671ec00] recovering by using intra mode
[libx264 @ 1671ec00] internal error (MV out of thread range)
[libx264 @ 1671ec00] recovering by using intra mode
[libx264 @ 1671ec00] internal error (MV out of thread range)
[libx264 @ 1671ec00] recovering by using intra mode


org.bytedeco
javacv-platform
1.4


package com.media.cqrcb.util;


import org.bytedeco.javacpp.avcodec;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameRecorder.Exception;
import org.bytedeco.javacv.Java2DFrameConverter;

import javax.imageio.ImageIO;
import javax.sound.sampled.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ShortBuffer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 使用javacv进行录屏
 */
public class VideoRecode {
    //线程池 screenTimer
    private ScheduledThreadPoolExecutor screenTimer;
    //获取屏幕尺寸
    private Rectangle rectangle;
    //视频类 FFmpegFrameRecorder
    private FFmpegFrameRecorder recorder;
    private Robot robot;
    //线程池 exec
    private ScheduledThreadPoolExecutor exec;
    private TargetDataLine line;
    private AudioFormat audioFormat;
    private DataLine.Info dataLineInfo;
    private boolean isHaveDevice = true;
    private long startTime = 0;
    private long videoTS = 0;
    private long pauseTime = 0;
    private double frameRate = 24;

    /**
     *
     * @param fileName  文件储存路径
     * @param isHaveDevice 传入一个 true
     */
    public VideoRecode(String fileName, boolean isHaveDevice) {

        rectangle = new Rectangle(Helper.screenSizeWidth(), Helper.screenSizeHeight());

        recorder = new FFmpegFrameRecorder(fileName + ".mp4", Helper.screenSizeWidth(), Helper.screenSizeHeight());
       // recorder.setVideoCodec(avcodec.AV_CODEC_ID_AV1); // 13
       // recorder.setVideoCodec(avcodec.AV_CODEC_ID_MPEG4); // 13
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
        recorder.setFormat("mp4");
      //  recorder.setSampleRate(44100);
      //  recorder.setFrameRate(frameRate);
      //  recorder.setVideoQuality(0);
       // recorder.setVideoOption("crf", "23");
        recorder.setVideoBitrate(100000);
        recorder.setVideoOption("preset", "slow");
        recorder.setPixelFormat(0); // yuv420p = 0
        recorder.setAudioChannels(2);
        recorder.setAudioOption("crf", "0");
        // Highest quality
        recorder.setAudioQuality(0);
        recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
        try {
            robot = new Robot();
        } catch (AWTException e) {
            e.printStackTrace();
        }
        try {
            recorder.start();
        } catch (Exception e) {
            System.out.print("*******************************");
        }
        this.isHaveDevice = isHaveDevice;
    }

    /**
     * 开始录制
     */
    public void start() {

        if (startTime == 0) {
            startTime = System.currentTimeMillis();
        }
        if (pauseTime == 0) {
            pauseTime = System.currentTimeMillis();
        }
        //不录声音了
        // 如果有录音设备则启动录音线程
//        if (isHaveDevice) {
//            new Thread(new Runnable() {
//                public void run() {
//                    caputre();
//                }
//            }).start();
//        }
        // 录屏
        screenTimer = new ScheduledThreadPoolExecutor(1);
        screenTimer.scheduleAtFixedRate(new Runnable() {

            public void run() {
                BufferedImage screenCapture = robot.createScreenCapture(rectangle); // 截屏

                BufferedImage videoImg = new BufferedImage((int) rectangle.getWidth(), (int) rectangle.getHeight(),
                        BufferedImage.TYPE_3BYTE_BGR); // 声明一个BufferedImage用重绘截图
                Graphics2D videoGraphics = videoImg.createGraphics();// 创建videoImg的Graphics2D
                videoGraphics.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
                videoGraphics.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING,
                        RenderingHints.VALUE_COLOR_RENDER_SPEED);
                videoGraphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
                videoGraphics.drawImage(screenCapture, 0, 0, null); // 重绘截图

                //BufferedImage bi = robot.createScreenCapture(new Rectangle(Helper.screenSizeWidth(), Helper.screenSizeHeight()));

                Java2DFrameConverter java2dConverter = new Java2DFrameConverter();
                Frame frame = java2dConverter.convert(videoImg);
                try {
                    videoTS = 1000L
                            * (System.currentTimeMillis() - startTime - (System.currentTimeMillis() - pauseTime));
                    // 检查偏移量
                    if (videoTS > recorder.getTimestamp()) {
                        recorder.setTimestamp(videoTS);
                    }
                    recorder.record(frame); // 录制视频
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } finally {
                    // 释放资源
                    videoGraphics.dispose();
                    videoGraphics = null;
                    videoImg.flush();
                    videoImg = null;
                    java2dConverter = null;
                    screenCapture.flush();
                    screenCapture = null;
                }

            }
        }, (int) (1000 / frameRate), (int) (1000 / frameRate), TimeUnit.MILLISECONDS);
    }

    /**
     * 抓取声音
     */
    public void caputre() {
        audioFormat = new AudioFormat(44100.0F, 16, 2, true, false);
        dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
        try {
            line = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
        } catch (LineUnavailableException e1) {
            // TODO Auto-generated catch block
            System.out.println("#################");
        }
        try {
            line.open(audioFormat);
        } catch (LineUnavailableException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        line.start();

        final int sampleRate = (int) audioFormat.getSampleRate();
        final int numChannels = audioFormat.getChannels();

        int audioBufferSize = sampleRate * numChannels;
        final byte[] audioBytes = new byte[audioBufferSize];

        exec = new ScheduledThreadPoolExecutor(1);
        exec.scheduleAtFixedRate(new Runnable() {

            public void run() {
                try {
                    int nBytesRead = line.read(audioBytes, 0, line.available());
                    int nSamplesRead = nBytesRead / 2;
                    short[] samples = new short[nSamplesRead];

                    // Let's wrap our short[] into a ShortBuffer and
                    // pass it to recordSamples
                    ByteBuffer.wrap(audioBytes).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer().get(samples);
                    ShortBuffer sBuff = ShortBuffer.wrap(samples, 0, nSamplesRead);

                    // recorder is instance of
                    // org.bytedeco.javacv.FFmpegFrameRecorder
                    recorder.recordSamples(sampleRate, numChannels, sBuff);
                    // System.gc();
                } catch (org.bytedeco.javacv.FrameRecorder.Exception e) {
                    System.out.println(e);
                }
            }
        }, (int) (1000 / frameRate), (int) (1000 / frameRate), TimeUnit.MILLISECONDS);
    }

    /**
     * 停止
     */
    public void stop() {
        if (null != screenTimer) {
            screenTimer.shutdownNow();
        }
        try {
            recorder.stop();
            recorder.release();
            recorder.close();
            screenTimer = null;
            // screenCapture = null;
            if (isHaveDevice) {
                if (null != exec) {
                    exec.shutdownNow();
                }
                if (null != line) {
                    line.stop();
                    line.close();
                }
                dataLineInfo = null;
                audioFormat = null;
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    /**
     * 暂停
     *
     * @throws Exception
     */
    public void pause() throws Exception {
        screenTimer.shutdownNow();
        screenTimer = null;
        if (isHaveDevice) {
            exec.shutdownNow();
            exec = null;
            line.stop();
            line.close();
            dataLineInfo = null;
            audioFormat = null;
            line = null;
        }
        pauseTime = System.currentTimeMillis();
    }

    /**
     * 截屏
     */
    public static List<File> screenshot() {
        List<File> list = new ArrayList<>();
        try {

            //把抓取到的内容写到一个jpg文件中
            File file = new File("video/new/");
            if (!file.exists()) {
                file.mkdir();
            }
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HHmmss");
            String date = sdf.format(new Date());
            //一秒钟24张图片
            System.out.println("开始截屏");
            for (int a = 0; a <= 100; a++) {
                try {
                    //休眠40毫秒截屏一次,一秒钟25张图
                    Thread.sleep(100);
                } catch (java.lang.Exception e) {

                }
                Robot robot = new Robot();
                //根据指定的区域抓取屏幕的指定区域,1300是长度,800是宽度。
                BufferedImage bi = robot.createScreenCapture(new Rectangle(Helper.screenSizeWidth(), Helper.screenSizeHeight()));
                File f = new File("video/new/" + date + "--" + a + ".jpg");
                ImageIO.write(bi, "jpg", f);
                list.add(f);
            }
            System.out.println("截屏结束");
        } catch (AWTException e) {
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

        return list;
    }


}

  • 写回答

1条回答 默认 最新

  • XuQinkun 2020-07-02 21:50
    关注

    兄弟,AV_CODEC_ID_H264编码要将视频格式设置为flv,recorder.setFormat("flv");

    评论

报告相同问题?

悬赏问题

  • ¥15 NAO机器人的录音程序保存问题
  • ¥15 C#读写EXCEL文件,不同编译
  • ¥15 如何提取csv文件中需要的列,将其整合为一篇完整文档,并进行jieba分词(语言-python)
  • ¥15 MapReduce结果输出到HBase,一直连接不上MySQL
  • ¥15 扩散模型sd.webui使用时报错“Nonetype”
  • ¥15 stm32流水灯+呼吸灯+外部中断按键
  • ¥15 将二维数组,按照假设的规定,如0/1/0 == "4",把对应列位置写成一个字符并打印输出该字符
  • ¥15 NX MCD仿真与博途通讯不了啥情况
  • ¥15 win11家庭中文版安装docker遇到Hyper-V启用失败解决办法整理
  • ¥15 gradio的web端页面格式不对的问题