java实现一个录像大师
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实现一个录像大师相关推荐
- 学了编译原理能否用 Java 写一个编译器或解释器?
16 个回答 默认排序 RednaxelaFX JavaScript.编译原理.编程 等 7 个话题的优秀回答者 282 人赞同了该回答 能.我一开始学编译原理的时候就是用Java写了好多小编译器和 ...
- 用java实现一个简易自动提款机
用java实现一个简易自动提款机,且有以下要求 如何实现呢?首先,我们定义一个用户类User,同时根据要求设计好属性(本人部分命名没有使用驼峰命名法,不够规范).因为一个人可能有多个卡,卡号又不能重复 ...
- java编写存钱_用Java编写一个简单的存款
package desposit.money; public class DespositMoney { public static void main(String[] args) { Custom ...
- java里冒泡排序编程案例_java编程题:用Java实现一个冒泡排序算法
/** * java编程题:用Java实现一个冒泡排序算法 */ public class Test12 { public static void main(String[] args) { int[ ...
- 用java写一个简单的区块链(下)
用java写一个简单的区块链(下) 2018年03月29日 21:44:35 java派大星 阅读数:725 标签: 区块链java 更多 个人分类: 区块链 版权声明:本文为博主原创文章,转载请标明 ...
- java怎样开关语句随机数 不重复_怎样用java产生一个指定范围而且不重复的随机数?...
题目: 怎样用java产生一个指定范围而且不重复的随机数? 解答: package test; import java.util.Random; public class RandomBirth { ...
- java把一个list_java中将一个List等分成n个list的工具方法(推荐)
实例如下: /** * 将一个list均分成n个list,主要通过偏移量来实现的 * @param source * @return */ public static List> average ...
- 如何复制java卡,使用java做一个简单的集卡程序
使用java做一个简单的集卡程序 本次设想的是要集齐4张卡,每张卡的概率都是25%,如果每个用户集齐需要多少次才能集合完毕 public class Test { public static void ...
- java使用d3_[Java教程]一个初学者的指南,使用D3做数据绑定
[Java教程]一个初学者的指南,使用D3做数据绑定 0 2016-07-03 13:00:09 一个初学者的指南,使用D3做数据绑定 D3.js 是个强大的数据可视化库,可以做出惊艳的图表.比如:气 ...
- java写一个搜索引擎_搜索引擎—-Java实现一个简单的网络爬虫
Java实现一个简单的爬虫程序. package SearchCrawler;import java.util.*;import java.net.*;import java.io.*;import ...
最新文章
- hdu 1754 I Hate It(线段树之 单点更新+区间最值)
- 老男孩教育50期左婷婷-day03-xhell连接服务器-远程连接排错-基础命令
- 【图像超分辨率】MSAN:Scene-Adaptive RS Img SR a Multiscale Attention
- 注解@resource的作用_Bean基于Annotation(注解)的装配方式
- ELK 日志处理开发指南
- android支付宝支付开发过程
- 对方服务器未响应,重新投递中 postfix手心,我配置的Postfix邮件服务器邮件发不出去,在mail.log里显示如下~请求帮助...
- Mybatis下面的MapperScannerConfigurer 扫描器
- 江苏专转本计算机考试模拟试卷,江苏专转本计算机模拟试题 11
- java笑话_[转]爆笑程序员的笑话集锦
- 正交性的好处和实现方法
- CentOS7 建立静态 IP(eth0)
- winhex常用快捷键
- python判断可逆素数_可逆素数 - 寂寞暴走伤的个人空间 - OSCHINA - 中文开源技术交流社区...
- 【开源】技术宅硬核跨年,DIY墨水屏日历:自动刷新位置、天气,随机播放2000多条「毒鸡汤」...
- WindowsServer修改用户密码
- 计算机电缆线对成缆系数,电线电缆的成缆系数是什么含义?
- Spring实训 个人博客二 详情页
- configure详解
- tpshop是什么?
热门文章
- 网站后台操作手册(模板)
- 苹果id登录_LOL手游公测!苹果/安卓下载登录详细教程
- SVN下载 1.11.0版本 win7 32位 安装文件及中文语言包
- PHP第一季视频教程.李炎恢.学习笔记(三)(第2章 基本语法(2))
- 华侨大学计算机等级,全国计算机等级考试报名系统-华侨大学.doc
- 彻底格式化系统启动U盘(基于win10)
- Android ActivityManager类
- python壁纸推荐_python爬虫项目-一见倾心壁纸
- 华为鸿蒙p9刷机包,华为P9原版rom系统刷机包_华为P9最新版升级包更新下载
- iPXE部署Ubuntu无盘系统