如何从视频 (mov) 中获取帧样本 (jpeg)

新手上路,请多包涵

我想用 java 从视频文件 (mov) 中获取帧样本 (jpeg)。是否有捷径可寻。当我在谷歌搜索时,我能找到的是从多个 jpg 制作 mov。我不知道,也许我找不到合适的关键字。

原文由 Nuri Tasdemir 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 748
2 个回答

Xuggler 完成了这项工作。他们甚至提供了一个示例代码,它完全符合我的需要。链接在下面

http://xuggle.googlecode.com/svn/trunk/java/xuggle-xuggler/src/com/xuggle/mediatool/demos/DecodeAndCaptureFrames.java

我修改了此链接中的代码,使其仅保存视频的第一帧。

 import javax.imageio.ImageIO;

import java.io.File;

import java.awt.image.BufferedImage;

import com.xuggle.mediatool.IMediaReader;
import com.xuggle.mediatool.MediaListenerAdapter;
import com.xuggle.mediatool.ToolFactory;
import com.xuggle.mediatool.event.IVideoPictureEvent;
import com.xuggle.xuggler.Global;

/**
 *  * @author aclarke
 *    @author trebor
 */

public class DecodeAndCaptureFrames extends MediaListenerAdapter
{
  private int mVideoStreamIndex = -1;
  private boolean gotFirst = false;
  private String saveFile;
  private Exception e;
  /** Construct a DecodeAndCaptureFrames which reads and captures
   * frames from a video file.
   *
   * @param filename the name of the media file to read
   */

  public DecodeAndCaptureFrames(String videoFile, String saveFile)throws Exception
  {
    // create a media reader for processing video
    this.saveFile = saveFile;
    this.e = null;
     IMediaReader reader = ToolFactory.makeReader(videoFile);

    // stipulate that we want BufferedImages created in BGR 24bit color space
    reader.setBufferedImageTypeToGenerate(BufferedImage.TYPE_3BYTE_BGR);

    // note that DecodeAndCaptureFrames is derived from
    // MediaReader.ListenerAdapter and thus may be added as a listener
    // to the MediaReader. DecodeAndCaptureFrames implements
    // onVideoPicture().

    reader.addListener(this);

    // read out the contents of the media file, note that nothing else
    // happens here.  action happens in the onVideoPicture() method
    // which is called when complete video pictures are extracted from
    // the media source

      while (reader.readPacket() == null && !gotFirst);

      if (e != null)
          throw e;
  }

  /**
   * Called after a video frame has been decoded from a media stream.
   * Optionally a BufferedImage version of the frame may be passed
   * if the calling {@link IMediaReader} instance was configured to
   * create BufferedImages.
   *
   * This method blocks, so return quickly.
   */

  public void onVideoPicture(IVideoPictureEvent event)
  {
    try
    {
      // if the stream index does not match the selected stream index,
      // then have a closer look

      if (event.getStreamIndex() != mVideoStreamIndex)
      {
        // if the selected video stream id is not yet set, go ahead an
        // select this lucky video stream

        if (-1 == mVideoStreamIndex)
          mVideoStreamIndex = event.getStreamIndex();

        // otherwise return, no need to show frames from this video stream

        else
          return;
      }

      ImageIO.write(event.getImage(), "jpg", new File(saveFile));
      gotFirst = true;

    }
    catch (Exception e)
    {
      this.e = e;
    }
  }
}

原文由 Nuri Tasdemir 发布,翻译遵循 CC BY-SA 3.0 许可协议

我知道原来的问题已经解决了,不过,我发布这个答案是为了防止其他人像我一样被卡住。

从昨天开始,我已经尝试了一切,我的意思是要做到这一点。所有可用的 Java 库要么已过时,不再维护,要么缺少任何类型的可用文档(严重吗??!?!)

我尝试了 JFM(陈旧且无用)、JCodec(没有任何文档)、JJMpeg(看起来很有前途,但由于缺乏 Java 类文档而使用起来非常困难和繁琐)、OpenCV 自动 Java 构建和一些其他库我不记得了。

最后,我决定看一下 JavaCV 的( Github 链接)类,瞧!它包含带有详细文档的 FFMPEG 绑定。

 <dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>javacv</artifactId>
    <version>1.0</version>
</dependency>

事实证明,有一种非常简单的方法可以将视频帧从视频文件提取到 BufferedImage 并扩展为 JPEG 文件。 FFmpegFrameGrabber 类可以很容易地用于抓取单个帧并将它们转换为 BufferedImage 。代码示例如下:

 FFmpegFrameGrabber g = new FFmpegFrameGrabber("textures/video/anim.mp4");
g.start();

Java2DFrameConverter converter = new Java2DFrameConverter();

for (int i = 0 ; i < 50 ; i++) {

    Frame frame = g.grabImage(); // It is important to use grabImage() to get a frame that can be turned into a BufferedImage

    BufferedImage bi = converter.convert(frame);

    ImageIO.write(bi, "png", new File("frame-dump/video-frame-" + System.currentTimeMillis() + ".png"));
}

g.stop();

基本上,此代码转储视频的前 50 帧并将它们保存为 PNG 文件。好的是内部搜索功能适用于实际帧而不是关键帧(我在使用 JCodec 时遇到的问题)

您可以参考 JavaCV 的主页以了解更多有关可用于从网络摄像头等捕获帧的其他类的信息。希望这个答案对您有所帮助:-)

原文由 Maghoumi 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题