M2X*_*M2X 58
我知道原来的问题已经解决了,不过,我发布这个答案,万一其他人像我一样陷入困境.
从昨天开始,我已经尝试了所有的东西,我的意思是做到这一点.所有可用的Java库都已过时,不再维护或缺少任何可用的文档(严重?? ??!)
我尝试了JFM(旧的和无用的),JCodec(没有任何文档),JJMpeg(看起来很有前途但由于缺少Java级文档而非常难以使用),OpenCV自动Java构建和一些其他库我不记得了.
最后,我决定看一下JavaCV的(Github链接)类,瞧!它包含带有详细文档的FFMPEG绑定.
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.0</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)
事实证明,有一种非常简单的方法可以将视频帧从视频文件中提取到BufferedImageJPEG文件中.FFmpegFrameGrabber类可以很容易地用于抓取单个帧并将其转换为BufferedImage.代码示例如下:
FFmpegFrameGrabber g = new FFmpegFrameGrabber("textures/video/anim.mp4");
g.start();
for (int i = 0 ; i < 50 ; i++) {
ImageIO.write(g.grab().getBufferedImage(), "png", new File("frame-dump/video-frame-" + System.currentTimeMillis() + ".png"));
}
g.stop();
Run Code Online (Sandbox Code Playgroud)
基本上,此代码转储视频的前50帧并将其保存为PNG文件.好处是内部搜索功能,适用于实际帧而不是关键帧(我遇到的问题是JCodec)
您可以参考JavaCV的主页,以了解有关可用于从WebCams捕获帧的其他类的更多信息.希望此答案有所帮助:-)
Xuggler完成工作。他们甚至给出了完全符合我需要的示例代码。链接在下面
并且我修改了此链接中的代码,使其仅保存视频的第一帧。
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)