java 如何从 .mp4 视频中获取图像?

Oli*_*erg 3 java javafx video-processing

我需要获取图像作为用户加载的视频的预览,它不需要是一个很棒的缩略图,因为它只是用于聊天应用程序,所以我想到当用户发送包含 mp4 的消息时我处理它并保存一个随机帧。

我用谷歌搜索了一下,每个人都在使用 ffmpeg,但这是一个外部软件,你只能用 java 与它交互,我的项目需要独立,我不希望它依赖于服务器安装了 ffmpeg 的事实,所以我回到过去并找到了 JavaFX,但所有在线片段都没有指定他们正在使用的版本,而且 chatGPT 一如既往地毫无用处,你们能告诉我如何做到这一点,或者至少向我解释一下它是如何工作的吗?我可以自己编码吗?我正在使用这个依赖项

   <dependency>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-controls</artifactId>
        <version>16</version> <!-- the version chatGPT wrote but you can change that -->
    </dependency>
Run Code Online (Sandbox Code Playgroud)

如果您有完全不同的解决方案,那也很棒,我只关心在指定路径上使用指定名称保存视频中的随机帧,提前致谢

我尝试了这种方法,但它给出了很多错误,可能是因为版本不匹配

private byte[] getFrameFromVideo(String videoFilePath, int targetTimeSeconds) throws IOException {
        try {
            Media media = new Media(new File(videoFilePath).toURI().toString());
            MediaPlayer mediaPlayer = new MediaPlayer(media);

            CountDownLatch latch = new CountDownLatch(1);

            mediaPlayer.setOnReady(() -> {
                mediaPlayer.pause();
                mediaPlayer.setStartTime(mediaPlayer.getTotalDuration().multiply(targetTimeSeconds * 1.0 / media.getDuration().toSeconds()));
                mediaPlayer.setStopTime(mediaPlayer.getStartTime().add(mediaPlayer.getTotalDuration().multiply(1.0 / media.getDuration().toSeconds())));
                latch.countDown(); 
            });

            mediaPlayer.setOnEndOfMedia(() -> {
                BufferedImage bufferedImage = new BufferedImage(mediaPlayer.getMedia().getWidth(), mediaPlayer.getMedia().getHeight(), BufferedImage.TYPE_3BYTE_BGR);
                FXImage fxImage = mediaPlayer.snapshot(null);
                fxImage.pixelReaderProperty().get().getPixels(0, 0, (int) fxImage.getWidth(), (int) fxImage.getHeight(), javafx.scene.image.PixelFormat.getByteRgbInstance(), bufferedImage.getRaster().getDataBuffer());

                try {
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    ImageIO.write(bufferedImage, "png", baos);
                    mediaPlayer.dispose();
                    latch.countDown(); 
                    return baos.toByteArray();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });

            mediaPlayer.play();

            latch.await();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
Run Code Online (Sandbox Code Playgroud)

jew*_*sea 5

当您使用 Maven 时,要使用 JavaFX Media,您需要 JavaFX Media 作为 Maven 依赖项,并将其添加到您的 Java 模块系统中。

\n\n

您需要启动JavaFX运行时才能正确使用媒体系统。

\n\n

对媒体的 JavaFX API 调用应在 JavaFX 应用程序线程上进行。JavaFX 应用程序线程永远不应该休眠或锁定。

\n

要播放媒体并确保它已准备好在选定位置拍摄快照:

\n
    \n
  1. MediaView节点放在scene.
  2. \n
  3. 如果需要,实施媒体错误处理。
  4. \n
  5. mute媒体播放器。
  6. \n
  7. 使用媒体 API 跳至使用seekAPI 的\n视频中的某个位置。
  8. \n
  9. 监视status媒体播放器的\n。
  10. \n
  11. play来自所寻找点的视频。
  12. \n
\n

状态切换到播放状态后,使用Platform.runLater, 给系统时间渲染所需的帧。并在runLater通话中执行以下步骤:

\n
    \n
  1. 节点snapshotMediaViewa 。
  2. \n
  3. 那么stop.MediaPlayer
  4. \n
  5. dispose玩家的。
  6. \n
\n

您的快照为您提供了一个 JavaFX,image您可以直接在 JavaFX 中显示ImageView

\n

如果您需要将快照图像保存到磁盘:

\n
    \n
  1. 拍摄快照后,使用该模块将 JavaFX 转换ImageBufferedImage\ javafx-swingn。\n
      \n
    • 添加到您的项目中的方式与javafx-media.
    • \n
    \n
  2. \n
  3. 将缓冲图像写入适当的格式,例如jpgpng使用ImageIOapi。\n
      \n
    • 如果您选择保存为 jpg 而不是 png,您可能需要删除 alpha 通道,因为 jpg 可以\xe2\x80\x99t 处理 alpha。
    • \n
    \n
  4. \n
\n

如果您的应用程序是模块化的,则在您的模块信息中包含使其工作所需的所有模块依赖项:

\n
    \n
  • javafx.media
  • \n
  • javafx.swing
  • \n
  • java.desktop
  • \n
\n

推荐分布

\n

为了向最终用户提供您的应用程序功能,建议:

\n
    \n
  • 使用,为您的目标平台maven-javafx-plugin创建应用的jlinked zip ,\n
      \n
    • 用户可以通过解压缩 zip 并通过调用 . 创建的 shell 脚本来执行应用程序来使用您的应用程序jlink
    • \n
    \n
  • \n
\n

或者

\n
    \n
  • jpackage如果您的应用不是模块化的,请使用系统为您的应用创建安装程序。\n
      \n
    • 用户可以通过启动安装程序在其系统上安装应用程序来使用您的应用程序,他们可以像运行系统的任何其他本机应用程序一样运行该应用程序。
    • \n
    • 用于jpackage打包非模块化应用程序并为各种平台创建安装程序比为模块化应用程序创建 jlink zip 发行版更复杂。
    • \n
    \n
  • \n
\n

对于上述任一方法,用户通常无需在目标计算机上安装任何其他软件即可使用您的应用程序。

\n

参考

\n
    \n
  • Oracle JavaFX 媒体教程。\n
      \n
    • 有点过时,但仍然大部分相关。
    • \n
    \n
  • \n
  • OpenJFX 入门。\n
      \n
    • 在尝试执行此答案中的步骤之前,请确保您可以从开始运行 hello, world 应用程序。
    • \n
    \n
  • \n
\n

备择方案

\n\n