Android: как получить миниатюру видеофайла, закрытого для вашего приложения?

Вопрос:

Как получить миниатюру видео для личного файла приложения? В частности, есть ли способ напрямую извлечь видеокадры из файла .mpeg?

Задний план:

  1. Мое приложение включает камеру, которая может записывать видео.
  2. По причинам продукта видеофайл изначально создается и записывается в приватном режиме в каталоге приватных данных приложения, что делает его приватным для приложения. Это делается с помощью: Context#openFileOutput(fileName, Context.MODE_PRIVATE) — типичный путь к файлу выглядит так: /data/data/[package.name]/files/[fileName].mp4 — к вашему сведению, я уже пробовал использовать Context.MODE_WORLD_READABLE вместо Context.MODE_PRIVATE, но это не помогло.
  3. Даже если видео может в конечном итоге оказаться во внешнем хранилище (путем перемещения файла в Environment#getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES)) миниатюра должна отображаться, пока видео находится в личном хранилище приложения.
  4. Похоже на ThumbnailUtils.createVideoThumbnail(String, int) отлично работает с файлом после его перемещения в общедоступный каталог (независимо от добавления его в MediaStore), но молча завершается сбоем (возвращает null), когда файл находится во внутренней памяти.

    • 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.

person Warlax    schedule 21.12.2011    source источник
comment
Следующий код работает идеально: Bitmap bMap = ThumbnailUtils.createVideoThumbnail(file.getAbsolutePath(), MediaStore.Video.Thumbnails.MICRO_KIND);   -  person Padma Kumar    schedule 29.12.2011
comment
Спасибо, @PadmaKumar, недостаточно хорошо. Пожалуйста, прочитайте пункт № 4 в моем вопросе.   -  person Warlax    schedule 31.12.2011
comment
Извините, что слишком поздно, но я столкнулся с той же проблемой, какое решение вы использовали дальше. Спасибо.   -  person Rajnish Mishra    schedule 30.07.2014
comment
В итоге я разместил видео в общедоступном месте, получил миниатюру и переместил видео в свое личное место (см. отмеченный ответ).   -  person Warlax    schedule 30.07.2014


Ответы (4)


Большинство медиа-API являются просто связующим клиентом медиа-сервера, который работает в своем собственном процессе. Вы можете попытаться временно сделать файл общедоступным.

person pinxue    schedule 04.01.2012
comment
В итоге сделал очевидное и выставил файл извне на время, достаточное для получения миниатюры, прежде чем переместить его обратно в личное хранилище приложения. - person Warlax; 03.02.2012

Конечно, вы не можете использовать материалы MediaStore для частных носителей. Я бы использовал библиотеку обработки изображений, если это вообще возможно. Я знаю, что OpenCV может легко сделать это, извлекая/изменяя размер фрейма. - пожалуйста, посмотрите на средний раздел страницы 2.

person Tae-Sung Shin    schedule 02.01.2012

Вы пробовали использовать приведенный ниже API,

MediaMetadataRetriever::getFrameAtTime() , см. Android -developer-page-MediaMetadataRetriever

образец кода:

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. }

Приведенный выше фрагмент кода сработал для меня! но мой файл доступен в общих папках.

person Vamsi    schedule 04.01.2012
comment
Я возлагал большие надежды на этот ответ, но, к сожалению, он не сработал. метод setDataSource(String) создает RuntimeException, утверждая, что это не удалось... извините :) - person Warlax; 03.02.2012

Это работает на Gingerbread и выше:

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();
}
person Will Poitras    schedule 20.04.2014