我正在尝试使用最新的 MonteMedia ScreenRecorder 在 Java 中录制屏幕:
<dependency>
<groupId>ch.randelshofer</groupId>
<artifactId>org.monte.media</artifactId>
<version>17.1</version>
</dependency>
我的代码与我可以找到的库的使用示例类似 - 但是旧版本,因为我没有找到新版本的示例 - 所以包是不同的:
import org.monte.media.math.Rational;
import org.monte.media.screenrecorder.ScreenRecorder;
import org.monte.media.av.Format;
import org.monte.media.av.FormatKeys.MediaType;
import static org.monte.media.av.codec.video.VideoFormatKeys.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;
public class Screencorder {
private Screencorder() {}
public static ScreenRecorder startRecording(String fileName) throws IOException, AWTException {
GraphicsConfiguration gc = GraphicsEnvironment
.getLocalGraphicsEnvironment()
.getDefaultScreenDevice()
.getDefaultConfiguration();
Format fileFormat = new Format(MediaTypeKey, MediaType.FILE, MimeTypeKey, MIME_AVI);
Format screenFormat = new Format(MediaTypeKey, MediaType.VIDEO, EncodingKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE,
CompressorNameKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE, DepthKey, 24, FrameRateKey,
Rational.valueOf(15), QualityKey, 1.0f, KeyFrameIntervalKey, (15 * 60));
Format mouseFormat = new Format(MediaTypeKey, MediaType.VIDEO, EncodingKey, ScreenRecorder.ENCODING_BLACK_CURSOR, FrameRateKey, Rational.valueOf(30));
ScreenRecorder screenRecorder = new ScreenRecorder(gc, null,
fileFormat, screenFormat, mouseFormat,
null, new File(fileName));
screenRecorder.start();
return screenRecorder;
}
public static void stopRecording(ScreenRecorder screenRecorder) throws IOException {
screenRecorder.stop();
}
}
运行测试:
import org.junit.jupiter.api.Test;
import org.monte.media.screenrecorder.ScreenRecorder;
import java.time.Duration;
import static org.awaitility.Awaitility.await;
class ScreenRecordingTest {
@Test
void recordingTest() throws Exception {
ScreenRecorder recorder = Screencorder.startRecording("/tmp/");
Thread.sleep(2000)
Screencorder.stopRecording(recorder);
}
}
给我:
java.io.IOException: Error no writer found for file format: Format{mimeType:video/avi,mediaType:FILE}.
我尝试了各种 JDK - 17、20 - 但没有成功。
尝试将目录更改为文件,同样的错误。
尝试了不同的 MIME 类型 - 不管怎样,都是同样的错误。
有人可以帮助如何运行它,以便它记录一个
.avi
吗?或其他类似电影的格式。
我希望我犯了一些明显的错误。
添加
module-info.java
并按照此处所述彻底清理 IntelliJ,使其正常工作。 here 显示了一个简单的工作示例。
总结:
您的机器上需要 Java >= 17
maven 模块的
pom.xml
有 3 个主要的 MonteMedia 依赖项:
<dependencies>
<dependency>
<groupId>ch.randelshofer</groupId>
<artifactId>org.monte.media.screenrecorder</artifactId>
<version>17.1</version>
</dependency>
<dependency>
<groupId>ch.randelshofer</groupId>
<artifactId>org.monte.media</artifactId>
<version>17.1</version>
</dependency>
<dependency>
<groupId>ch.randelshofer</groupId>
<artifactId>org.monte.media.swing</artifactId>
<version>17.1</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
</dependencies>
src/main/java
需要一个module.info
,其中包含这些依赖项以及它们所需的一些附加依赖项+导出以在测试中使用该模块:module com.your.path.util.screen { //<= this is the maven module name too
requires java.desktop;
requires java.prefs;
requires org.monte.media;
requires org.monte.media.swing;
requires org.monte.media.screenrecorder;
exports com.your.path.util.screen;
}
com.your.path.util.screen
中有一个类Screencorder
,它将录制电影,其中包含在start
和stop
方法中开始全屏录制所需的一切:package com.your.path.util.screen;
import org.monte.media.av.Format;
import org.monte.media.math.Rational;
import org.monte.media.screenrecorder.ScreenRecorder;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.time.Duration;
import static org.monte.media.av.FormatKeys.*;
import static org.monte.media.av.codec.video.VideoFormatKeys.*;
public class Screencorder {
private ScreenRecorder screenRecorder;
public final String movieFolder;
public void start() throws IOException, AWTException {
GraphicsConfiguration gc = GraphicsEnvironment
.getLocalGraphicsEnvironment()
.getDefaultScreenDevice()
.getDefaultConfiguration();
Format fileFormat = new Format(MediaTypeKey, MediaType.FILE,
MimeTypeKey, MIME_AVI);
Format screenFormat = new Format(MediaTypeKey, MediaType.VIDEO,
EncodingKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE,
CompressorNameKey, ENCODING_AVI_TECHSMITH_SCREEN_CAPTURE,
DepthKey, 24,
FrameRateKey, Rational.valueOf(15),
QualityKey, 1.0f,
KeyFrameIntervalKey, (15 * 60));
Format mouseFormat = new Format(MediaTypeKey, MediaType.VIDEO,
EncodingKey, ScreenRecorder.ENCODING_BLACK_CURSOR,
FrameRateKey, Rational.valueOf(30));
screenRecorder = new ScreenRecorder(gc, null,
fileFormat, screenFormat, mouseFormat,
null, new File(movieFolder));
screenRecorder.start();
}
public void stop() throws IOException {
screenRecorder.stop();
}
public static void main(String[] args) throws IOException, AWTException, InterruptedException {
Screencorder recorder = new Screencorder();
recorder.start();
Thread.sleep(Duration.ofSeconds(7).toMillis());
recorder.stop();
}
public Screencorder() {
if (System.getProperty("os.name").toLowerCase().startsWith("windows")) {
movieFolder = System.getProperty("user.home") + File.separator + "Videos";
} else {
movieFolder = System.getProperty("user.home") + File.separator + "Movies";
}
File movieDir = new File(movieFolder);
if (!movieDir.exists()) {
movieDir.mkdirs();
}
}
public String getMovieFolder() {
return movieFolder;
}
}
src/test/java
也需要一个module.info
- 它将需要上述模块和测试库+它将打开自身以反射到junit
:module com.your.path.util.screen.test {
requires com.your.path.util.screen;
requires org.junit.jupiter.api;
requires hamcrest.all;
opens com.your.path.util.screen.test to org.junit.platform.commons;
}
测试包需要与主代码不同,例如
com.your.path.util.screen.test
,测试类放在这里
如果 IntelliJ 出现问题:按照上述方式进行清理后,模块
com.your.path.util.screen
需要在 模块设置 > com.your.path.util.screen > 依赖项 > check 3 MonteMedia 依赖项中选择 MonteMedia 依赖项(与pom.xml
)相同
现在您可以在 IntelliJ 中运行
main()
方法以及测试。
如果需要的话,有一个非模块化的解决方案:手动编写服务文件。例如在 gradle 中:
tasks {
compileJava {
doLast {
val servicesDir = File(destinationDirectory.get().asFile, "META-INF/services")
servicesDir.mkdirs()
File(servicesDir, "org.monte.media.av.MovieWriterSpi").apply {
writeText(listOf(
"org.monte.media.avi.AVIWriterSpi",
"org.monte.media.quicktime.QuickTimeWriterSpi"
).joinToString("") { "$it\n"})
}
File(servicesDir, "org.monte.media.av.CodecSpi").apply {
writeText(listOf(
"org.monte.media.avi.codec.audio.AVIPCMAudioCodecSpi",
"org.monte.media.av.codec.video.TechSmithCodecSpi"
).joinToString("") { "$it\n"})
}
}
}
}
提供商可能需要更新以满足您的需求。