15

Question:

How do you get a video thumbnail for an application-private file? Specifically, is there a way to extract video frames from an .mpeg file directly?

Background:

  1. My application includes a camera that can record video.
  2. For product reasons, the video file is initially created and written in private mode in the application's private data directory, making it private to the application. This is done using: Context#openFileOutput(fileName, Context.MODE_PRIVATE) - a typical file path looks like this: /data/data/[package.name]/files/[fileName].mp4 -- FYI I already tried using Context.MODE_WORLD_READABLE instead of Context.MODE_PRIVATE but it didn't help.
  3. Even though the video may eventually end up in external storage (by moving the file to Environment#getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)), the thumbnail must be displayed while the video is in application-private storage.
  4. It seems like ThumbnailUtils.createVideoThumbnail(String, int) works fine for the file after it is moved to the public directory (regardless of adding it to the MediaStore), but silently fails (returns null) when the file is in internal storage.

    • Note: as long as the video file is in application-private storage, it is not added to the MediaStore (the image/video content provider on the device Gallery feeds on). Only once the video is moved to external storage do I add it the MediaStore. This is a product-related decision which I cannot circumnavigate; unless there's a way to add the video the media store without it being visible to other apps... I wonder if videos in application-private storage can be added to the media store and would remain application-private but gain all the free "services" provided by the media store such as thumbnail generation.
Warlax
  • 2,459
  • 5
  • 30
  • 41
  • The following code runs perfectly: Bitmap bMap = ThumbnailUtils.createVideoThumbnail(file.getAbsolutePath(), MediaStore.Video.Thumbnails.MICRO_KIND); – Padma Kumar Dec 29 '11 at 10:54
  • Thank you @PadmaKumar, not good enough. Please read point #4 in my question. – Warlax Dec 31 '11 at 01:55
  • Sorry its too late but I am facing same issue what was the solution you have used further. Thanks. – Rajnish Mishra Jul 30 '14 at 07:25
  • I ended up putting the video in a public location, getting the thumbnail, and moving the video to my private location (see marked answer). – Warlax Jul 30 '14 at 13:38

4 Answers4

3

Of course, you can't use MediaStore stuff for private media. I would use a image process library if it is possible at all. I know OpenCV can do that easily by extracting/resizing a frame. - please look at middle section of page 2.

Tae-Sung Shin
  • 20,215
  • 33
  • 138
  • 240
2

Most of media APIs are just binder client of media server which runs in its own process. You may try to make the file public temporary.

pinxue
  • 1,736
  • 12
  • 17
  • Ended up doing the obvious and exposing the file externally for just enough time to get the thumbnail before moving it back to app-private storage. – Warlax Feb 02 '12 at 21:08
1

have you tried with the below API,

MediaMetadataRetriever::getFrameAtTime() , refer to Android-developer-page-MediaMetadataRetriever

sample code:

MediaMetadataRetriever retriever = new MediaMetadataRetriever();
try {
retriever.setDataSource(filePath);
bitmap = retriever.getFrameAtTime(0, MediaMetadataRetriever.OPTION_CLOSEST);
} catch (IllegalArgumentException ex) {
// Assume this is a corrupt video file
} catch (RuntimeException ex) {
// Assume this is a corrupt video file. }

The above piece of code worked for me!! but my file is accessible in the public folders.

Vamsi
  • 5,853
  • 6
  • 29
  • 36
  • I was having high hopes for this answer, but unfortunately it did not work. the setDataSource(String) method produces a RuntimeException claiming it failed... sorry :) – Warlax Feb 02 '12 at 20:46
0

This works on Gingerbread and up:

try {
    Uri location = Uri.fromFile(context.getFileStreamPath(filePath));
    MediaMetadataRetriever media = new MediaMetadataRetriever();
    ParcelFileDescriptor parcel = ParcelFileDescriptor.open(new File(location.getPath()),ParcelFileDescriptor.MODE_READ_ONLY);
    media.setDataSource(parcel.getFileDescriptor());
    Bitmap thumb = media.getFrameAtTime(0 , MediaMetadataRetriever.OPTION_CLOSEST );
    thumbnail.setImageBitmap(thumb);
} catch (FileNotFoundException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
Will Poitras
  • 404
  • 3
  • 7