本文目录导读:

在Java中实现录屏功能,主要有几种不同的技术方案,下面我会详细介绍几种常见的实现方式,并提供完整的代码示例。
使用Robot类 + JavaCV(最常用)
这是最经典的方式,使用java.awt.Robot截取屏幕,配合JavaCV生成视频文件。
Maven依赖
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.9</version>
</dependency>
完整实现代码
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ScreenRecorder {
private FFmpegFrameRecorder recorder;
private volatile boolean recording = false;
private Rectangle screenBounds;
private Robot robot;
private Thread recordingThread;
private String outputPath;
public ScreenRecorder(String outputPath) {
this.outputPath = outputPath;
this.screenBounds = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
try {
this.robot = new Robot();
} catch (AWTException e) {
e.printStackTrace();
}
}
public void startRecording() {
if (recording) return;
recording = true;
recordingThread = new Thread(() -> {
try {
// 初始化录制器
recorder = new FFmpegFrameRecorder(outputPath,
screenBounds.width, screenBounds.height);
recorder.setVideoCodec(org.bytedeco.javacv.FrameRecorder.VideoCodec.H264);
recorder.setFormat("mp4");
recorder.setFrameRate(30);
recorder.setPixelFormat(org.bytedeco.javacv.FrameRecorder.PixelFormat.YUV420P);
recorder.start();
Java2DFrameConverter converter = new Java2DFrameConverter();
while (recording) {
// 截图
BufferedImage screenCapture = robot.createScreenCapture(screenBounds);
BufferedImage image = convertToType(screenCapture, BufferedImage.TYPE_3BYTE_BGR);
// 转换为Frame并录制
Frame frame = converter.convert(image);
recorder.record(frame);
// 控制帧率
Thread.sleep(33); // 约30fps
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (recorder != null) {
recorder.stop();
recorder.release();
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
recordingThread.start();
System.out.println("录屏已开始,输出文件:" + outputPath);
}
public void stopRecording() {
recording = false;
if (recordingThread != null) {
try {
recordingThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("录屏已停止");
}
private BufferedImage convertToType(BufferedImage sourceImage, int targetType) {
BufferedImage image = new BufferedImage(
sourceImage.getWidth(),
sourceImage.getHeight(),
targetType
);
Graphics2D g = image.createGraphics();
g.drawImage(sourceImage, 0, 0, null);
g.dispose();
return image;
}
// 使用示例
public static void main(String[] args) {
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String outputPath = "screen_recording_" + timestamp + ".mp4";
ScreenRecorder recorder = new ScreenRecorder(outputPath);
recorder.startRecording();
// 录制10秒
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
recorder.stopRecording();
}
}
使用JNativeHook实现热键控制
添加全局热键支持,方便开始/停止录制:
<dependency>
<groupId>com.github.kwhat</groupId>
<artifactId>jnativehook</artifactId>
<version>2.2.2</version>
</dependency>
import com.github.kwhat.jnativehook.GlobalScreen;
import com.github.kwhat.jnativehook.keyboard.NativeKeyEvent;
import com.github.kwhat.jnativehook.keyboard.NativeKeyListener;
public class HotkeyRecorder extends ScreenRecorder implements NativeKeyListener {
public HotkeyRecorder(String outputPath) {
super(outputPath);
}
@Override
public void nativeKeyPressed(NativeKeyEvent e) {
// F6 开始录制,F7 停止录制
if (e.getKeyCode() == NativeKeyEvent.VC_F6) {
startRecording();
} else if (e.getKeyCode() == NativeKeyEvent.VC_F7) {
stopRecording();
}
}
@Override
public void nativeKeyReleased(NativeKeyEvent e) {}
@Override
public void nativeKeyTyped(NativeKeyEvent e) {}
public void registerHotkeys() {
try {
GlobalScreen.registerNativeHook();
GlobalScreen.addNativeKeyListener(this);
} catch (Exception e) {
e.printStackTrace();
}
}
public void unregisterHotkeys() {
try {
GlobalScreen.unregisterNativeHook();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
String outputPath = "screen_recording_hotkey.mp4";
HotkeyRecorder recorder = new HotkeyRecorder(outputPath);
recorder.registerHotkeys();
System.out.println("按 F6 开始录制,按 F7 停止录制");
// 防止程序退出
try {
Thread.sleep(Long.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
带GUI的控制界面
提供一个简单的Swing界面控制录制:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ScreenRecorderGUI extends JFrame {
private ScreenRecorder recorder;
private JButton startButton;
private JButton stopButton;
private JLabel statusLabel;
private JTextField fpsField;
public ScreenRecorderGUI() {
setTitle("屏幕录制器");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
// 控制面板
JPanel controlPanel = new JPanel();
startButton = new JButton("开始录制");
stopButton = new JButton("停止录制");
stopButton.setEnabled(false);
statusLabel = new JLabel("就绪");
// FPS设置
controlPanel.add(new JLabel("FPS:"));
fpsField = new JTextField("30", 5);
controlPanel.add(fpsField);
controlPanel.add(startButton);
controlPanel.add(stopButton);
add(controlPanel, BorderLayout.NORTH);
add(statusLabel, BorderLayout.CENTER);
// 事件监听
startButton.addActionListener(e -> startRecording());
stopButton.addActionListener(e -> stopRecording());
pack();
setLocationRelativeTo(null);
}
private void startRecording() {
String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String outputPath = "recording_" + timestamp + ".mp4";
recorder = new ScreenRecorder(outputPath);
recorder.startRecording();
startButton.setEnabled(false);
stopButton.setEnabled(true);
statusLabel.setText("正在录制... " + outputPath);
}
private void stopRecording() {
if (recorder != null) {
recorder.stopRecording();
}
startButton.setEnabled(true);
stopButton.setEnabled(false);
statusLabel.setText("录制完成");
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new ScreenRecorderGUI().setVisible(true);
});
}
}
高性能录屏(使用grabber)
对于更高性能要求的场景,可以使用JavaCV的FrameGrabber:
import org.bytedeco.javacv.*;
import org.bytedeco.javacpp.*;
public class HighPerformanceRecorder {
public static void startRecording(String outputPath, int duration) {
Rectangle screenBounds = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
try {
// 创建截屏抓取器
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber("desktop");
grabber.setFormat("gdigrab"); // Windows下使用gdigrab
grabber.setFrameRate(30);
grabber.setImageWidth(screenBounds.width);
grabber.setImageHeight(screenBounds.height);
grabber.start();
// 创建录制器
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputPath,
screenBounds.width, screenBounds.height);
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
recorder.setFormat("mp4");
recorder.setFrameRate(30);
recorder.start();
long startTime = System.currentTimeMillis();
Frame frame;
while ((frame = grabber.grab()) != null) {
recorder.record(frame);
// 检查是否达到指定时长
if (System.currentTimeMillis() - startTime > duration * 1000) {
break;
}
}
recorder.stop();
grabber.stop();
System.out.println("录制完成");
} catch (Exception e) {
e.printStackTrace();
}
}
}
注意事项
-
性能优化:实际的屏幕录制对性能要求较高,特别是高分辨率下,建议:
- 适当降低帧率(15-30fps)
- 可以降低录制分辨率
- 使用硬件编码加速
-
跨平台问题:
- Windows:使用gdigrab或Robot
- macOS:使用AVFoundation
- Linux:使用X11或KMS
-
权限问题:某些系统可能需要屏幕录制权限
-
内存管理:长时间录屏要注意内存使用,及时清理
-
音频录制:如需同时录制音频,需要额外添加音频捕获功能
方案中,方案一(Robot + JavaCV)是最通用和稳定的选择,你可以根据实际需求选择合适的实现方式,并在此基础上进行功能扩展。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播