Grab Preview image of a video / listFiles() does not work

Asked

Viewed 404 times

4

I have two problems in a super simple project that I am developing in which I did not find a solution in the Forum nor in Google, the project is a video management.

I’ll leave the Github link below for those who are curious, want to improve/refactor the project or wanted a simple example to study.

Github: https://github.com/wilsontamarozzi/movie-list-java

Problems

  1. How to get the Preview (thumbnail) image of a video of any format?! I’ve searched Google but only seen tutorials on how to generate a thumbnail of the video using xuggler, but it will make me have to store this somewhere and it’s not something I wanted to do because I have to control it later.

  2. I have a folder in which the listFiles() does not work, read and write permissions are all OK and nothing. Simply return me null, Does anyone have any idea what it might be?

  • No one has any idea?

  • Question #1 looks like a duplicate of this http://answall.com/questions/95988/pega-imagem-preview-de-um-v%C3%Addeo-listfiles-n%C3%A3o-funciona

3 answers

4


Decode videos

Regarding the problem #1, there is no magic solution to read images of whichever video format.

Each video format needs a specific algorithm to interpret it and hardly a single implementation will cover all formats.

Even if some libraries (or group of libraries) can read several common formats, there are always some proprietary formats or variations that end up causing problems.

Approaches

Two basic solutions for miniatures would be:

Pre-store the thumbnails

Store thumbnails along with video files.

If you have any control over how video files are generated or included in the directory, this would be the best solution.

Use any tool via command line to generate the thumbnail and make your Java program simple and fast.

Generate the thumbnail on demand

This is the possible approach when you have no control over the videos.

Decoding the video from your program may be convenient on the one hand, but keep in mind that it will greatly increase the complexity of the program and potentially affect performance in a very negative way. Think about rendering 500 videos from any folder.

You may need to create a queue to process videos and work with different threads not to crash the program and allow cancellation in case the user does not want to wait for the operation to end.

Xuggler

I don’t understand what’s wrong with keeping the libraries used by xuggler. Many programs and tools accompany different libraries.

The argument of "having to control it later" makes no sense because any dependency added to your project will have to be managed.

What exactly is the difficulty in control if you put libraries together with your program when distributing?

From what I read in documentation, xuggler is a wrapper for native FFMPEG libraries, used in many projects. The advantage of using these libraries is that they already have maturity and are reliable.

Jcodec

Another alternative would be Jcodec, an implementation made purely in Java.

The first page already brings an example of how to extract a frame from the video to an image:

int frameNumber = 150;
BufferedImage frame = FrameGrab.getFrame(new File("arquivo.mp4"), frameNumber);
ImageIO.write(frame, "png", new File("frame_150.png"));

However, as expected from a less used library, it supports few formats: AVC, H.264 in MP4, ISO BMF and Quicktime. I suppose she also has less adherence to variations of these formats.

Although there are recent updates in this library, probably the updates to new or even existing formats will be few or more time consuming, since there doesn’t seem to be much involvement in the project.

Problem with listFiles()

The problem with the listFiles can be caused if the Java process does not have permissions to read from the folder.

It may also be that the directory you passed is invalid. For example, I ran a test by passing ~ (user directory) and did not work. However, passing the absolute path did work.

It would also use the newest Java API. Example:

//extensões aceitas
PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:*.{txt,log}");
//diretório de busca
Path diretorio = Paths.get("/my/dir");
//permite links simbólicos
EnumSet<FileVisitOption> options = EnumSet.of(FileVisitOption.FOLLOW_LINKS);
//navega no diretório
Files.walkFileTree(diretorio, options, 1,
        new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                //verifica se não é um diretório e se tem uma das extensões esperadas
                if (!attrs.isDirectory() && matcher.matches(file.getFileName())) {
                    System.out.println(file.toString());
                }
                return super.visitFile(file, attrs);
            }
        });

See relevant documentation on walkFileTree and on the PathMatcher.

Considerations

Define the best approach to your case and remember that any of them will have their positives and negatives.

  • 1

    Very good recommendation on the walkFileTree, in it is possible to check the files that there were faults, did not know and worked perfectly. The problem I was having with the ListFiles was something about the attributes in the folder I needed to use a command to reset the attributes. About Xuggler had to actually generate the thumbnail but I’m having that error message listed in the friend’s reply above. Thank you so much for the clarification.

3

About the Xuggler and taking into account @utluiz’s placements, it works perfectly, adapted to my needs became perfect (which is very similar to what you’re doing) and also worked perfectly on stackoverflow.com for a user in question:

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;
    }
  }
}
  • Friend, I came to see a class that performs the same process, but both mine and yours is presenting me with this message, you would know to say what this can be? 10:11:04.459 [Finalizer] DEBUG com.xuggle.xuggler - Closing dangling Container (../../../../../../../csrc/com/xuggle/xuggler/Container.cpp:146)&#xA;10:11:04.464 [Finalizer] DEBUG com.xuggle.xuggler - Closing dangling StreamCoder (../../../../../../../csrc/com/xuggle/xuggler/StreamCoder.cpp:96)

  • You are using Tomcat ?

  • If you are adding the variables to the Tomcat startup process (setenv.sh file), from where I am not able to access wiki.xuggle.com, there is a tutorial that teaches you step by step, I think you will have to reinstall Xuggler. Search there on 'Xuggler and Tomcat' you will find what I am talking about (environment variables) and if you can)

1

  1. In the case of Windows (most used system), it creates thumbnails in a file Thumbs.db. If you can access it you can get these thumbnails. The bad thing about this approach is depending on operating system resources (the ue is not recommended).

  2. If you can already generate thumbnails smoothly you can create a hidden folder (or not) along with the videos in question. With a default path and default names you know that the thumbnails will always be there (you can check whether they are there or not and create).

Browser other questions tagged

You are not signed in. Login or sign up in order to post.