如何使用最新的MonteMedia ScreenRecorder在Java中录制屏幕?

问题描述 投票:0回答:2

我正在尝试使用最新的 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
吗?或其他类似电影的格式。

我希望我犯了一些明显的错误。

java video avi
2个回答
1
投票

添加

module-info.java
并按照此处所述彻底清理 IntelliJ,使其正常工作。 here 显示了一个简单的工作示例。

总结:

  1. 您的机器上需要 Java >= 17

  2. 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>
  1. 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;
}
  1. 在包
    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;
    }
}
  1. 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;
}
  1. 测试包需要与主代码不同,例如

    com.your.path.util.screen.test
    ,测试类放在这里

  2. 如果 IntelliJ 出现问题:按照上述方式进行清理后,模块

    com.your.path.util.screen
    需要在 模块设置 > com.your.path.util.screen > 依赖项 > check 3 MonteMedia 依赖项中选择 MonteMedia 依赖项(与
    pom.xml
    )相同

现在您可以在 IntelliJ 中运行

main()
方法以及测试。


0
投票

如果需要的话,有一个非模块化的解决方案:手动编写服务文件。例如在 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"})
        }
    }
} 
}

提供商可能需要更新以满足您的需求。

© www.soinside.com 2019 - 2024. All rights reserved.