java实现一个录像大师

javacv从入门到入土系列,发现了个好玩的东西,视频处理,于是我想搞了个屏幕录屏大师,这里我使用javafx进行页面显示。

依赖

        <!-- 需要注意,javacv主要是一组API为主,还需要加入对应的实现 --><dependency><groupId>org.bytedeco</groupId><artifactId>javacv</artifactId><version>1.5.6</version></dependency><!-- 用到了 ffmpeg 需要把 ffmpeg 的平台实现依赖引入 --><dependency><groupId>org.bytedeco</groupId><artifactId>ffmpeg-platform</artifactId><version>4.4-1.5.6</version></dependency><!--所有平台实现,依赖非常大,几百MB吧--><!--<dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId><version>1.5.6</version></dependency>-->

实现

package top.lingkang.test.gui;import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import org.bytedeco.ffmpeg.avcodec.AVPacket;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.*;import javax.sound.sampled.*;
import java.io.File;
import java.util.Timer;
import java.util.TimerTask;/*** @author lingkang* Created by 2022/5/10*/
public class DesktopRecording extends Application {private static final int frameRate = 10;// 录制的帧率private static boolean isStop = false;private static TargetDataLine line;private static File audioFile, videoFile;private static ImageView imageVideo;private static boolean isStart;@Overridepublic void start(Stage primaryStage) throws Exception {primaryStage.setTitle("lingkang-桌面录屏emm...");imageVideo = new ImageView();imageVideo.setFitWidth(800);imageVideo.setFitHeight(600);Button button = new Button("停止录制");button.setOnAction(new EventHandler<ActionEvent>() {@Overridepublic void handle(ActionEvent event) {isStop = true;Alert alert = new Alert(Alert.AlertType.INFORMATION);alert.setTitle("info");alert.setHeaderText("已经停止录制");alert.setOnCloseRequest(event1 -> alert.hide());alert.showAndWait();}});VBox box = new VBox();box.getChildren().addAll(button, imageVideo);primaryStage.setScene(new Scene(box));primaryStage.setHeight(600);primaryStage.setWidth(800);primaryStage.show();primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>() {@Overridepublic void handle(WindowEvent event) {isStop = true;System.exit(0);}});// window 建议使用 FFmpegFrameGrabber("desktop") 进行屏幕捕捉FrameGrabber grabber = new FFmpegFrameGrabber("desktop");grabber.setFormat("gdigrab");grabber.setFrameRate(frameRate);// 捕获指定区域,不设置则为全屏grabber.setImageHeight(600);grabber.setImageWidth(800);//grabber.setOption("offset_x", "200");grabber.setOption("offset_y", "200");//必须设置了大小才能指定区域起点,参数可参考 FFmpeg 入参grabber.start();videoFile = File.createTempFile("lingkang", ".avi");// 用于存储视频 , 先调用stop,在释放,就会在指定位置输出文件,,这里我保存到D盘FFmpegFrameRecorder recorder = FFmpegFrameRecorder.createDefault(videoFile, grabber.getImageWidth(), grabber.getImageHeight());recorder.setVideoOption("tune", "zerolatency");recorder.setFrameRate(frameRate);recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);// 编码,使用编码能让视频占用内存更小,根据实际自行选择recorder.start();Timer timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {if (isStop) {try {// 停止recorder.stop();grabber.stop();// 释放内存,我们都知道c/c++需要手动释放资源recorder.release();grabber.release();} catch (Exception e) {e.printStackTrace();}new Thread(new Runnable() {@Overridepublic void run() {try {composeVideo();} catch (Exception e) {e.printStackTrace();}}}).start();timer.cancel();return;}if (!isStart) {isStart = true;// 录制声音startAudio();}try {// 获取屏幕捕捉的一帧Frame frame = grabber.grabFrame();// 将这帧放到记录recorder.record(frame);// 观察可以怎么实现的Image convert = new JavaFXFrameConverter().convert(frame);// 更新imageVideo.setImage(convert);} catch (Exception e) {e.printStackTrace();}}}, 2000, 1000 / frameRate);}/*** 音视频合并为一个视频*/private void composeVideo() throws Exception {// 合成视频FFmpegFrameGrabber imageGrabber = new FFmpegFrameGrabber(videoFile);imageGrabber.start();FFmpegFrameGrabber audioGrabber = new FFmpegFrameGrabber(audioFile);audioGrabber.start();File file = new File("D://video666666.avi");if (file.exists())file.delete();// 流媒体输出地址,分辨率(长,高),是否录制音频(0:单声道/1:立体声)FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(file, imageGrabber.getImageWidth(),imageGrabber.getImageHeight(), 1);recorder.setInterleaved(true);recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);recorder.start(imageGrabber.getFormatContext());long videoTime = imageGrabber.getLengthInTime();AVPacket packet = null;for (; (packet = imageGrabber.grabPacket()) != null; ) {recorder.recordPacket(packet);}Frame sampleFrame = null;while ((sampleFrame = audioGrabber.grabSamples()) != null) {recorder.record(sampleFrame);if (audioGrabber.getTimestamp() >= videoTime) {break;}}recorder.close();audioGrabber.close();imageGrabber.close();System.out.println("视频合成完毕!");}private void startAudio() {// 录音new Thread(new Runnable() {@Overridepublic void run() {try {AudioFormat audioFormat = new AudioFormat(44100.0F, 16, 2, true, false);DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat);// 可以捕捉不同声道line = (TargetDataLine) AudioSystem.getLine(dataLineInfo);line.open(audioFormat);line.start();audioFile = File.createTempFile(String.valueOf(System.currentTimeMillis()), ".wav");AudioInputStream ais = new AudioInputStream(line);// start recordingAudioSystem.write(ais, AudioFileFormat.Type.WAVE, audioFile);} catch (Exception e) {e.printStackTrace();}}}).start();}public static void main(String[] args) throws Exception {launch(args);}
}

java实现一个录像大师相关推荐

  1. 学了编译原理能否用 Java 写一个编译器或解释器?

    16 个回答 默认排序​ RednaxelaFX JavaScript.编译原理.编程 等 7 个话题的优秀回答者 282 人赞同了该回答 能.我一开始学编译原理的时候就是用Java写了好多小编译器和 ...

  2. 用java实现一个简易自动提款机

    用java实现一个简易自动提款机,且有以下要求 如何实现呢?首先,我们定义一个用户类User,同时根据要求设计好属性(本人部分命名没有使用驼峰命名法,不够规范).因为一个人可能有多个卡,卡号又不能重复 ...

  3. java编写存钱_用Java编写一个简单的存款

    package desposit.money; public class DespositMoney { public static void main(String[] args) { Custom ...

  4. java里冒泡排序编程案例_java编程题:用Java实现一个冒泡排序算法

    /** * java编程题:用Java实现一个冒泡排序算法 */ public class Test12 { public static void main(String[] args) { int[ ...

  5. 用java写一个简单的区块链(下)

    用java写一个简单的区块链(下) 2018年03月29日 21:44:35 java派大星 阅读数:725 标签: 区块链java 更多 个人分类: 区块链 版权声明:本文为博主原创文章,转载请标明 ...

  6. java怎样开关语句随机数 不重复_怎样用java产生一个指定范围而且不重复的随机数?...

    题目: 怎样用java产生一个指定范围而且不重复的随机数? 解答: package test; import java.util.Random; public class RandomBirth { ...

  7. java把一个list_java中将一个List等分成n个list的工具方法(推荐)

    实例如下: /** * 将一个list均分成n个list,主要通过偏移量来实现的 * @param source * @return */ public static List> average ...

  8. 如何复制java卡,使用java做一个简单的集卡程序

    使用java做一个简单的集卡程序 本次设想的是要集齐4张卡,每张卡的概率都是25%,如果每个用户集齐需要多少次才能集合完毕 public class Test { public static void ...

  9. java使用d3_[Java教程]一个初学者的指南,使用D3做数据绑定

    [Java教程]一个初学者的指南,使用D3做数据绑定 0 2016-07-03 13:00:09 一个初学者的指南,使用D3做数据绑定 D3.js 是个强大的数据可视化库,可以做出惊艳的图表.比如:气 ...

  10. java写一个搜索引擎_搜索引擎—-Java实现一个简单的网络爬虫

    Java实现一个简单的爬虫程序. package SearchCrawler;import java.util.*;import java.net.*;import java.io.*;import ...

最新文章

  1. hdu 1754 I Hate It(线段树之 单点更新+区间最值)
  2. 老男孩教育50期左婷婷-day03-xhell连接服务器-远程连接排错-基础命令
  3. 【图像超分辨率】MSAN:Scene-Adaptive RS Img SR a Multiscale Attention
  4. 注解@resource的作用_Bean基于Annotation(注解)的装配方式
  5. ELK 日志处理开发指南
  6. android支付宝支付开发过程
  7. 对方服务器未响应,重新投递中 postfix手心,我配置的Postfix邮件服务器邮件发不出去,在mail.log里显示如下~请求帮助...
  8. Mybatis下面的MapperScannerConfigurer 扫描器
  9. 江苏专转本计算机考试模拟试卷,江苏专转本计算机模拟试题 11
  10. java笑话_[转]爆笑程序员的笑话集锦
  11. 正交性的好处和实现方法
  12. CentOS7 建立静态 IP(eth0)
  13. winhex常用快捷键
  14. python判断可逆素数_可逆素数 - 寂寞暴走伤的个人空间 - OSCHINA - 中文开源技术交流社区...
  15. 【开源】技术宅硬核跨年,DIY墨水屏日历:自动刷新位置、天气,随机播放2000多条「毒鸡汤」...
  16. WindowsServer修改用户密码
  17. 计算机电缆线对成缆系数,电线电缆的成缆系数是什么含义?
  18. Spring实训 个人博客二 详情页
  19. configure详解
  20. tpshop是什么?

热门文章

  1. 网站后台操作手册(模板)
  2. 苹果id登录_LOL手游公测!苹果/安卓下载登录详细教程
  3. SVN下载 1.11.0版本 win7 32位 安装文件及中文语言包
  4. PHP第一季视频教程.李炎恢.学习笔记(三)(第2章 基本语法(2))
  5. 华侨大学计算机等级,全国计算机等级考试报名系统-华侨大学.doc
  6. 彻底格式化系统启动U盘(基于win10)
  7. Android ActivityManager类
  8. python壁纸推荐_python爬虫项目-一见倾心壁纸
  9. 华为鸿蒙p9刷机包,华为P9原版rom系统刷机包_华为P9最新版升级包更新下载
  10. iPXE部署Ubuntu无盘系统