javaCV开发详解补充篇:windows下通过vfwcap抓取摄像头画面以及几种摄像头和屏幕画面采集实现截屏录屏比较

已标记关键词 清除标记
## # 现在遇到的问题就是:在使用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 <dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv-platform</artifactId> <version>1.4</version> </dependency> ``` 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; } } ``` ``` ```
©️2020 CSDN 皮肤主题: 博客之星2020 设计师:CY__0809 返回首页
实付 29.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值