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

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

我需要获取图像作为用户加载的视频的预览,它不需要是一个很好的缩略图,因为它只是用于聊天应用程序,所以我想到当用户发送包含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>

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

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

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;
    }
java javafx video-processing
1个回答
1
投票

您需要 JavaFX 媒体才能使用 JavaFX Media。

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

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

  1. 将 MediaView 节点放置在场景中。
  2. 使用媒体 API 跳至 视频中的位置
  3. 从那里播放视频
  4. 监控状态 媒体
  5. 当它切换到在 Platform.runLater 中播放时,执行后续步骤。

runLater 中的步骤:

  1. 拍摄媒体节点的快照
  2. 然后关闭媒体播放器
  3. 并 dispose() 它。
  4. 拍摄快照后,将其转换为缓冲图像 使用 javafx-swing 模块。
    • 与 javafx-media 类似地添加到您的项目中。
  5. 将缓冲图像写入适当的格式,例如使用 ImageIO api 生成 jpg 或 png。

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

  • javafx.media
  • javafx.swing
  • java.desktop

参考文献

替代品

  • 作为 JavaFX 的替代 vlcj 也可以拍摄视频快照
    • 但这需要安装 vlc,并且使用起来比 JavaFX 媒体更复杂。
  • ffmpeg 也可以用于拍摄快照,我相信可能有 Java 绑定(我不确定)或者可以从 Java 进程 API 调用本机进程
    • 但这还需要本机 ffmpeg 运行时可用。
© www.soinside.com 2019 - 2024. All rights reserved.