Java 如何逐帧读取视频?

Java 如何逐帧读取视频?,java,video,image-processing,Java,Video,Image Processing,我想逐帧读取java8-64位格式的Mp4文件,并将每个帧作为jpg写入硬盘。我的第一次尝试是使用JavaFX2.2媒体播放器来播放文件 在视图组件上。我想可能会有一个选项,在每次加载新帧并准备在组件表面上绘制时注册一个观察者以获取事件,但似乎没有这样的方法。 只抓取在组件上绘制的帧/像素就足够了 这可以通过使用媒体播放器来完成吗?我使用媒体播放器的原因是bcs,这是我得到的最简单的解决方案。我尝试了vlcj,仅32位,和gstreamer,但没有运气:( 到目前为止,我得到的是: public

我想逐帧读取java8-64位格式的Mp4文件,并将每个帧作为jpg写入硬盘。我的第一次尝试是使用JavaFX2.2媒体播放器来播放文件 在视图组件上。我想可能会有一个选项,在每次加载新帧并准备在组件表面上绘制时注册一个观察者以获取事件,但似乎没有这样的方法。 只抓取在组件上绘制的帧/像素就足够了

这可以通过使用媒体播放器来完成吗?我使用媒体播放器的原因是bcs,这是我得到的最简单的解决方案。我尝试了vlcj,仅32位,和gstreamer,但没有运气:(

到目前为止,我得到的是:

public class VideoGrabber extends extends JFrame { 

// code for scene setup omitted

final MediaView view = createMediaView(...)

// some other stuff happens here

// now start the video
view.getMediaPlayer().seek(Duration.ZERO);
view.getMediaPlayer().play();
view.getMediaPlayer().setOnEndOfMedia(new Runnable()
{ // save image when done
  BufferedImage img = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_BGR 
  view.paint(img.getGraphics());
  ImageIO.write(img, "JPEG", new File("pic-"+System.currentTimeMillis()+".jpg"));
});

// somewhere else to create 
private MediaView createMediaView(String url)
{
  final Media clip = new Media(url);
  final MediaPlayer player = new MediaPlayer(clip);
  final MediaView view = new MediaView(player);
  view.setFitWidth(VID_WIDTH);
  view.setFitHeight(VID_HEIGHT);
  return view;
}
是否有办法做到以下几点:

player.setOnNextFrameReady(final Event evt) { writeImage(evt.getFrame()) };
谢谢!

像这样的框架随命令行工具一起提供,可以将视频分割为单独的帧(即文件夹中的图像)

见这个问题:

答案包含到包装ffmpeg的Java框架的链接。

提供了逐帧处理媒体文件的方法。下面显示了一个简单的视频处理示例,突出显示了斯诺克球的路径

在左侧,视频逐帧播放,帧与帧之间的间隔为30ms。在右侧,视频逐帧播放,但通过简单的图像处理方法保留白球的所有位置

源代码可以检查和视频

下面是使用Marvin请求媒体文件帧的基本源代码:

public class MediaFileExample implements Runnable{

    private MarvinVideoInterface    videoAdapter;
    private MarvinImage             videoFrame;

    public MediaFileExample(){
        try{
            // Create the VideoAdapter used to load the video file
            videoAdapter = new MarvinJavaCVAdapter();
            videoAdapter.loadResource("./res/snooker.wmv");

            // Start the thread for requesting the video frames 
            new Thread(this).start();
        }
        catch(MarvinVideoInterfaceException e){e.printStackTrace();}
    }

    @Override
    public void run() {
        try{
            while(true){
                // Request a video frame
                videoFrame = videoAdapter.getFrame();
            }
        }catch(MarvinVideoInterfaceException e){e.printStackTrace();}
    }

    public static void main(String[] args) {
        MediaFileExample m = new MediaFileExample();
    }
}
您可以使用MediaView的快照()。 首先将mediaPlayer连接到MediaView组件,然后使用mediaPlayer.seek()查找视频位置。然后可以使用以下代码提取图像帧:

    int width = mediaPlayer.getMedia().getWidth();
    int height = mediaPlayer.getMedia().getHeight();
    WritableImage wim = new WritableImage(width, height);
    MediaView mv = new MediaView();
    mv.setFitWidth(width);
    mv.setFitHeight(height);
    mv.setMediaPlayer(mediaPlayer);
    mv.snapshot(null, wim);
    try {
        ImageIO.write(SwingFXUtils.fromFXImage(wim, null), "png", new File("/test.png"));
    } catch (Exception s) {
        System.out.println(s);
    }

感谢您的回复。在我用java从视频中获取帧后,我想按需进行进一步处理,然后最终保存。ffmpeg是否可以创建一个图像流,我可以在jave中打开以进行处理,而无需将所有数据写入光盘?您可以尝试
https://code.google.com/p/jjmpeg/
。我不建议使用t他使用命令行将一帧一帧地提取到管道中,因为视频流中的搜索成本太高。再次感谢。不幸的是,使用jjmpeg将意味着我必须花费更多时间进行反向工程,以了解如何使用它(根本没有可用的数据计算)而不是把时间花在我必须执行的实际任务上。也许会弹出一些有趣的解决方案。但是thx!项目的源代码中有一个示例。请参阅我的编辑。jjmpeg的链接已失效:/非常好,我将尝试一下。链接已断开,项目是否已失效,或者只是网站已关闭?从searc判断h在sourceforge,项目已死亡。上一次更新是2016年。项目未死亡。由于sourceforge维护,该网站已关闭。respository已移至Github。您可以在网站上找到所有这些信息。我认为它已死亡或太旧,我无法使用它。答案被低估。谢谢。