I want to get a frame sample (jpeg) from a video file (mov) with java. Is there an easy way to do this. When I search in google all I can find is to make mov from multiple jpgs. I dont know maybe I cannot find the right keywords.
-
1Probably I am asking the question in a wrong way. I do not play the video file (on screen). I just want to read and process it as a file and get a sample frame from it and save this sample frame as a jpeg – Nuri Tasdemir Mar 31 '13 at 23:40
-
Here's a [similar question](http://stackoverflow.com/questions/11808815/how-to-get-the-the-single-images-of-an-mp4-movie-in-java) that doesn't look like it got a complete answer but might get you started. – rhashimoto Mar 31 '13 at 23:59
-
2I did it using Xoggler. I gave the link for the code in the answer section – Nuri Tasdemir Apr 01 '13 at 01:33
6 Answers
I know that the original question is solved, nevertheless, I am posting this answer in case anyone else got stuck like I did.
Since yesterday, I have tried everything, and I mean everything to do this. All available Java libraries are either out of date, not maintained anymore or lack any kind of usable documentation (seriously??!?!)
I tried JFM (old and useless), JCodec (no documentation whatsoever), JJMpeg (looks promising but is very difficult and cumbersome to use due to lack of Java-class documentation), OpenCV auto-Java builds and a few bunch of other libraries that I cannot remember.
Finally, I decided to take a look at JavaCV's (Github link) classes and voila! It contains FFMPEG bindings with detailed documentations.
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.0</version>
</dependency>
Turns out there is a very easy way to extract video frames from a video file to a BufferedImage
and by extension a JPEG file. The class FFmpegFrameGrabber could be easily used for grabbing individual frames and converting them to BufferedImage
. A code sample is as follows:
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();
Basically, this code dumps the first 50 frames of the video and saves them as a PNG file. The good thing is that the internal seek function, works on actual frames not keyframes (a problem that I had with JCodec)
You can refer to the JavaCV's homepage to find out more about other classes that can be used for capturing frames from WebCams etc. Hope this answer helps :-)

- 28
- 4

- 3,295
- 3
- 33
- 49
-
Just a couple of questions.. 1) Why do you grab so many frames for the image? Is there any way to check that number so we don't get an arrayoutofboundsexception? – oberger Feb 05 '15 at 04:20
-
@oberger I believe there is a method in the library to obtain the total number of frames in the file. Can't remember off the top of my head right now – Maghoumi May 09 '15 at 15:27
-
5As of release 0.11 (the stable as of June 2015), `grab()` now returns a `Frame`, which has no method `getBufferedImage()`. It is also [bugged](https://github.com/bytedeco/javacv/issues/116). If you need `FFmpegFrameGrabber`, use [release 0.10](http://search.maven.org/remotecontent?filepath=org/bytedeco/javacv/0.10/javacv-0.10-bin.zip) for the time being. – Aprel Jun 24 '15 at 23:10
-
@Aprel The current version includes a new `FrameConverter` class which allows converting from `Frame` to `BufferedImage` or other image formats. – RealSkeptic Aug 03 '15 at 14:03
-
@M2X Thanks for your reply. Can you please give me some example or link. – sandipchandanshive Jan 13 '16 at 18:26
-
8@retiremonk create `new org.bytedeco.javacv.Java2DFrameConverter` and call `getBufferedImage` on it. – 0__ May 24 '16 at 22:37
-
1@0__ Under the current version: `Java2DFrameConverter c = new Java2DFrameConverter; c.convert(g.grab());` Two things I've also found particularly useful: 1. Instead of `g.grab();` you can use `g.grabKeyFrame();` if you prefer to get a couple of representative frames and not each one. 2. @oberger `grab();` or `grabKeyFrame();` will return `null` if you've reached the end of the video. Just use an `if` statement and `break` the loop if `null` is returned. (Make sure to save the result of `grab()` in a variable, otherwise you'd skip a frame.) – Alexander Jank Jun 25 '18 at 14:40
-
Get BufferedImage from Frame: Java2DFrameUtils.toBufferedImage(g.grab() – Casey Murray Mar 09 '19 at 20:55
-
Thank you, the library is awesome! Also I want to say that the `grabber.grabKeyFrame()` method is more handy and safe than `grabber.grab()`, because it grabs only not null frames (I use the `1.5.1` version of the library). – Yamashiro Rion Oct 18 '19 at 10:48
-
Also it's cool that the library allows to choose a position to grab a frame, like: `grabber.setVideoFrameNumber((grabber.lengthInVideoFrames / 2f).roundToInt())`. – Yamashiro Rion Oct 18 '19 at 10:52
-
@Maghoumi Does it only work with .mp4 files? What about some other video formats such as .mov maybe? – Mikheil Zhghenti Jul 17 '22 at 22:57
Xuggler does the job. They even give a sample code which does exactly what I need. Link is below
And I've modified the code in this link such that it saves only the first frame of the video.
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;
}
}
}

- 9,720
- 3
- 42
- 67
-
We only worked with mov files (recorded with iPhone). I did not try the code with avi. And unfortunately I do not have an easy way to try. – Nuri Tasdemir Jan 29 '16 at 12:05
-
What can you suggest me , if I need to get a single frame (in order to create a thumbnail of that video) from avi video(always in java)? – user2556079 Jan 29 '16 at 13:32
-
1I cannot help you with that matter. Now I am working on something completely different. My suggestion is check SO for that specific question, and if there is no such question then ask it as a new question. – Nuri Tasdemir Jan 29 '16 at 15:22
-
4This is no longer the correct solution. The library is no longer supported. – Aleksandr Movsesyan Aug 02 '17 at 20:31
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import org.bytedeco.javacpp.opencv_core.IplImage;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FrameGrabber.Exception;
public class Read{
public static void main(String []args) throws IOException, Exception
{
FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber("C:/Users/Digilog/Downloads/Test.mp4");
frameGrabber.start();
IplImage i;
try {
i = frameGrabber.grab();
BufferedImage bi = i.getBufferedImage();
ImageIO.write(bi,"png", new File("D:/Img.png"));
frameGrabber.stop();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

- 71
- 2
-
This Program will Generate the 1st Frame of Your Video. I have used mp4 format for example . – kousik Mridha Mar 18 '15 at 04:21
-
2Thanks, but it would be helpful to include what 3rd party libraries are required for this. – Smig Jul 07 '17 at 01:26
Here's how with BoofCV:
String fileName = UtilIO.pathExample("tracking/chipmunk.mjpeg");
MediaManager media = DefaultMediaManager.INSTANCE;
ConfigBackgroundBasic configBasic = new ConfigBackgroundBasic(30, 0.005f);
ImageType imageType = ImageType.single(GrayF32.class);
BackgroundModelMoving background = FactoryBackgroundModel.movingBasic(configBasic, new PointTransformHomography_F32(), imageType);
SimpleImageSequence video = media.openVideo(fileName, background.getImageType());
ImageBase nextFrame;
while(video.hasNext()) {
nextFrame = video.next();
// Now do something with it...
}

- 27,777
- 57
- 250
- 447
maybe this will help you:
Buffer buf = frameGrabber.grabFrame();
// Convert frame to an buffered image so it can be processed and saved
Image img = (new BufferToImage((VideoFormat) buf.getFormat()).createImage(buf));
buffImg = new BufferedImage(img.getWidth(this), img.getHeight(this), BufferedImage.TYPE_INT_RGB);
//TODO saving the buffImg
for more informations:

- 1
- 1

- 1,892
- 3
- 26
- 40
-
-
2Unfortunately the link given in the "How to take single snapshots from a webcam?" is dead. On the other hand i found this link which had an answer http://osdir.com/ml/java.imagej/2005-01/msg00242.html However it requires Quicktime for Java which Apple does not provide anymore :( – Nuri Tasdemir Apr 01 '13 at 00:23
Below it is shown the essential code to request frames from media files.
For the complete source code and video demo:
"Media File Processing" example using Marvin Framework..
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();
}
}

- 4,547
- 2
- 34
- 41