Android: Video küçük resimlerini görüntülemek mümkün mü?


94

Kitaplık diyaloglu bir video kayıt uygulaması oluşturdum. Kitaplık iletişim kutusu, her bir öğenin aşağıdaki şekilde simge, video başlığı, etiketler ve konum bilgilerinden oluştuğu kayıtlı videoların listesini görüntüler:

alternatif metin

Simgeleri video küçük resimleriyle (tek kare önizleme) değiştirmenin mümkün olup olmadığını bilen var mı?

Teşekkürler!


Yanıtlar:


71

API 2.0 veya daha yenisini kullanıyorsanız bu işe yarayacaktır.

int id = **"The Video's ID"**
ImageView iv = (ImageView ) convertView.findViewById(R.id.imagePreview);
ContentResolver crThumb = getContentResolver();
BitmapFactory.Options options=new BitmapFactory.Options();
options.inSampleSize = 1;
Bitmap curThumb = MediaStore.Video.Thumbnails.getThumbnail(crThumb, id, MediaStore.Video.Thumbnails.MICRO_KIND, options);
iv.setImageBitmap(curThumb);

9
Peki tam olarak nedir id?
phunehehe

1
Telefondaki Videolar için MediaStore'da sorgulama yapabilirsiniz. "Kimlik", sorguladığınız bilgilerden yalnızca biridir. Daha fazla Mediastore hakkında bakın developer.android.com/reference/android/provider/...
Greg Zimmers

4
Herkesin bunu çalıştırması şaşırtıcı görünüyor. Bunu denedim ama curThumb boşa çıkıyor.
BlueVoodoo

7
bir URL'den videoya ne dersiniz?
jayellos


92

İmleçten geçmezseniz veya geçemezseniz ve yalnızca yollarınız veya Dosya nesneleriniz varsa, API seviyesi 8 (2.2) genel statik Bitmap createVideoThumbnail (String filePath, int tür)

Android belgeleri

Aşağıdaki kod mükemmel çalışır:

Bitmap bMap = ThumbnailUtils.createVideoThumbnail(file.getAbsolutePath(), MediaStore.Video.Thumbnails.MICRO_KIND);

7
bir küçük resim oluşturmaya çalıştığımda boş alıyorum. Yolum belki iyi değil mi? myPath = "/ external / video / media / 14180"
haythem souissi

Sihir gibi çalışır. I don bile t have my video ID. For better quality use MediaStore.Video.Thumbnails.FULL_SCREEN_KIND`
Sami Eltamawy

Garip de çalışmıyor ;-( video veritabanında mevcut, adı / boyutu alabilirim, ancak küçük resmi alamıyorum
Thomas Decaux

haythem souussi çünkü bu bir yol değil, bu Uri, onu yola çevirmen gerekiyor.
Nadir Novruzov

Bu çalışır ancak videonun yanlış kısmından bir resim döndürür. İlk kareyi istiyorum ama 5-6 saniye gibi mi oluyor? Herhangi bir fikir?
speedynomads

39

Sınıfı kullanma:

import android.provider.MediaStore.Video.Thumbnails;

Videodan iki önizleme küçük resmi alabiliriz:

Thumbnails.MICRO_KIND 96 x 96 için

Thumbnails.MINI_KIND 512 x 384 piksel için

Bu bir kod örneğidir:

String filePath = "/sdcard/DCIM/Camera/my_video.mp4"; //change the location of your file!

ImageView imageview_mini = (ImageView)findViewById(R.id.thumbnail_mini);
ImageView imageview_micro = (ImageView)findViewById(R.id.thumbnail_micro);

Bitmap bmThumbnail;

//MICRO_KIND, size: 96 x 96 thumbnail
bmThumbnail = ThumbnailUtils.createVideoThumbnail(filePath, Thumbnails.MICRO_KIND);
imageview_micro.setImageBitmap(bmThumbnail);
     
// MINI_KIND, size: 512 x 384 thumbnail 
bmThumbnail = ThumbnailUtils.createVideoThumbnail(filePath, Thumbnails.MINI_KIND);
imageview_mini.setImageBitmap(bmThumbnail);

Eğer dosya yolu için böyle bir bağlantım varsa, bu işe yaramaz, çünkü onu bir görüntü görünümüne ayarlamaya çalışıyorum ve hiçbir şey göstermiyor ... bu "http: / /unknown.com/v3- dosya yolu" Açıkçası 1aox9d1 .mp4 "gerçek bir etki alanı, ama bu yol küçük resim yapamaz mı?
Lion789

ThumbnailUtils sınıfını kullanmak için, şu yöntemi kullanarak dosyayı diske kaydetmeniz gerekir: ThumbnailUtils.createVideoThumbnail ()
Jorgesys

Teşekkürler, daha sonra oluşturma başparmağı için yeni dosya yolunu nasıl edinebilirim?
Lion789

Doz Neden Android 4 Ve Üstünde Çalışmıyor?
Criss

1
Merhaba Cris, 3 cihazım var 4.1 4.2.2 ve 5.0 ve sorunsuz çalışıyor, sorununuzla ve bazı kodlarla ilgili bir soru gönderin ve size yardımcı olabilirim.
Jorgesys

22

Şu anda aşağıdaki kodu kullanıyorum:

Bitmap bMap = ThumbnailUtils.createVideoThumbnail(file.getAbsolutePath(), MediaStore.Video.Thumbnails.MICRO_KIND);

Ama daha iyi bir çözüm buldum aşağıdaki kodla Glide kitaplığı ile (Ayrıca görüntünüzü önbelleğe alıyor ve önceki yaklaşıma göre daha iyi performansa sahip)

Glide.with(context)
                .load(uri)
                .placeholder(R.drawable.ic_video_place_holder)
                .into(imageView);

20

Glide'ı kullanmanızı gerçekten öneririm kütüphanesini . Yerel bir video dosyası için bir video küçük resmi oluşturmanın ve görüntülemenin en etkili yollarından biridir.

Bu satırı gradle dosyanıza eklemeniz yeterlidir:

compile 'com.github.bumptech.glide:glide:3.7.0'

Ve şu kadar basitleşecek:

String filePath = "/storage/emulated/0/Pictures/example_video.mp4";

Glide  
    .with( context )
    .load( Uri.fromFile( new File( filePath ) ) )
    .into( imageViewGifAsBitmap );

Daha fazla bilgiyi burada bulabilirsiniz: https://futurestud.io/blog/glide-displaying-gifs-and-videos

Şerefe!


4
Glide yalnızca yerel videolarla çalışır, URL videoları ile değil, bunun basit bir yolu yok
Lutaaya Huzaifah Idris

Bazı cihazlar yerel videolar için küçük resim göstermiyor
Sathish Gadde

7

Bunu dene, benim için çalışıyor

RequestOptions requestOptions = new RequestOptions();
 Glide.with(getContext())
      .load("video_url")
      .apply(requestOptions)
      .thumbnail(Glide.with(getContext()).load("video_url"))
      .into("yourimageview");

6

Bu çözüm, Android'in herhangi bir sürümü için çalışacaktır. 1.5 ve 2.2'de çalıştığı kanıtlanmıştır. Bu başka bir "Bu Android 2.0+ içindir" çözümü değildir. Bunu bir e-posta mesaj panosu toplama sayfasında buldum ve orijinal bağlantıyı bulamıyorum. Tüm kredi orijinal gönderene gider.

Uygulamanızda bunu arayarak kullanabilirsiniz:

Bitmap bm = getVideoFrame(VideoStringUri);

Kendi işlevinin bir yerinde (OnCreate dışında, vb.), İhtiyacınız olacak:

private Bitmap getVideoFrame(String uri) {
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        try {
            retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY);
            retriever.setDataSource(uri);
            return retriever.captureFrame();
        } catch (IllegalArgumentException ex) {
            ex.printStackTrace();
        } catch (RuntimeException ex) {
            ex.printStackTrace();
        } finally {
            try {
                retriever.release();
            } catch (RuntimeException ex) {
            }
        }
        return null;
    }

Src klasörünüzde, bu işlevi kullanmanıza izin veren (android kaynağın kendisinden kopyalanmış) sınıfı barındıracak yeni bir android / media alt dizinine ihtiyacınız var. Bu bölüm değiştirilmemeli, yeniden adlandırılmamalı veya başka bir yere yerleştirilmemelidir. Tüm bunların çalışması için MediaMetadataRetriever.java'nın kaynak klasörünüzde android.media altında olması gerekir.

/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.media;

import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;

import android.content.ContentResolver;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.net.Uri;

/**
 * MediaMetadataRetriever class provides a unified interface for retrieving
 * frame and meta data from an input media file. {@hide}
 */
public class MediaMetadataRetriever {
    static {
        System.loadLibrary("media_jni");
        native_init();
    }

    // The field below is accessed by native methods
    private int mNativeContext;

    public MediaMetadataRetriever() {
        native_setup();
    }

    /**
     * Call this method before setDataSource() so that the mode becomes
     * effective for subsequent operations. This method can be called only once
     * at the beginning if the intended mode of operation for a
     * MediaMetadataRetriever object remains the same for its whole lifetime,
     * and thus it is unnecessary to call this method each time setDataSource()
     * is called. If this is not never called (which is allowed), by default the
     * intended mode of operation is to both capture frame and retrieve meta
     * data (i.e., MODE_GET_METADATA_ONLY | MODE_CAPTURE_FRAME_ONLY). Often,
     * this may not be what one wants, since doing this has negative performance
     * impact on execution time of a call to setDataSource(), since both types
     * of operations may be time consuming.
     * 
     * @param mode
     *            The intended mode of operation. Can be any combination of
     *            MODE_GET_METADATA_ONLY and MODE_CAPTURE_FRAME_ONLY: 1.
     *            MODE_GET_METADATA_ONLY & MODE_CAPTURE_FRAME_ONLY: For neither
     *            frame capture nor meta data retrieval 2.
     *            MODE_GET_METADATA_ONLY: For meta data retrieval only 3.
     *            MODE_CAPTURE_FRAME_ONLY: For frame capture only 4.
     *            MODE_GET_METADATA_ONLY | MODE_CAPTURE_FRAME_ONLY: For both
     *            frame capture and meta data retrieval
     */
    public native void setMode(int mode);

    /**
     * @return the current mode of operation. A negative return value indicates
     *         some runtime error has occurred.
     */
    public native int getMode();

    /**
     * Sets the data source (file pathname) to use. Call this method before the
     * rest of the methods in this class. This method may be time-consuming.
     * 
     * @param path
     *            The path of the input media file.
     * @throws IllegalArgumentException
     *             If the path is invalid.
     */
    public native void setDataSource(String path)
            throws IllegalArgumentException;

    /**
     * Sets the data source (FileDescriptor) to use. It is the caller's
     * responsibility to close the file descriptor. It is safe to do so as soon
     * as this call returns. Call this method before the rest of the methods in
     * this class. This method may be time-consuming.
     * 
     * @param fd
     *            the FileDescriptor for the file you want to play
     * @param offset
     *            the offset into the file where the data to be played starts,
     *            in bytes. It must be non-negative
     * @param length
     *            the length in bytes of the data to be played. It must be
     *            non-negative.
     * @throws IllegalArgumentException
     *             if the arguments are invalid
     */
    public native void setDataSource(FileDescriptor fd, long offset, long length)
            throws IllegalArgumentException;

    /**
     * Sets the data source (FileDescriptor) to use. It is the caller's
     * responsibility to close the file descriptor. It is safe to do so as soon
     * as this call returns. Call this method before the rest of the methods in
     * this class. This method may be time-consuming.
     * 
     * @param fd
     *            the FileDescriptor for the file you want to play
     * @throws IllegalArgumentException
     *             if the FileDescriptor is invalid
     */
    public void setDataSource(FileDescriptor fd)
            throws IllegalArgumentException {
        // intentionally less than LONG_MAX
        setDataSource(fd, 0, 0x7ffffffffffffffL);
    }

    /**
     * Sets the data source as a content Uri. Call this method before the rest
     * of the methods in this class. This method may be time-consuming.
     * 
     * @param context
     *            the Context to use when resolving the Uri
     * @param uri
     *            the Content URI of the data you want to play
     * @throws IllegalArgumentException
     *             if the Uri is invalid
     * @throws SecurityException
     *             if the Uri cannot be used due to lack of permission.
     */
    public void setDataSource(Context context, Uri uri)
            throws IllegalArgumentException, SecurityException {
        if (uri == null) {
            throw new IllegalArgumentException();
        }

        String scheme = uri.getScheme();
        if (scheme == null || scheme.equals("file")) {
            setDataSource(uri.getPath());
            return;
        }

        AssetFileDescriptor fd = null;
        try {
            ContentResolver resolver = context.getContentResolver();
            try {
                fd = resolver.openAssetFileDescriptor(uri, "r");
            } catch (FileNotFoundException e) {
                throw new IllegalArgumentException();
            }
            if (fd == null) {
                throw new IllegalArgumentException();
            }
            FileDescriptor descriptor = fd.getFileDescriptor();
            if (!descriptor.valid()) {
                throw new IllegalArgumentException();
            }
            // Note: using getDeclaredLength so that our behavior is the same
            // as previous versions when the content provider is returning
            // a full file.
            if (fd.getDeclaredLength() < 0) {
                setDataSource(descriptor);
            } else {
                setDataSource(descriptor, fd.getStartOffset(),
                        fd.getDeclaredLength());
            }
            return;
        } catch (SecurityException ex) {
        } finally {
            try {
                if (fd != null) {
                    fd.close();
                }
            } catch (IOException ioEx) {
            }
        }
        setDataSource(uri.toString());
    }

    /**
     * Call this method after setDataSource(). This method retrieves the meta
     * data value associated with the keyCode.
     * 
     * The keyCode currently supported is listed below as METADATA_XXX
     * constants. With any other value, it returns a null pointer.
     * 
     * @param keyCode
     *            One of the constants listed below at the end of the class.
     * @return The meta data value associate with the given keyCode on success;
     *         null on failure.
     */
    public native String extractMetadata(int keyCode);

    /**
     * Call this method after setDataSource(). This method finds a
     * representative frame if successful and returns it as a bitmap. This is
     * useful for generating a thumbnail for an input media source.
     * 
     * @return A Bitmap containing a representative video frame, which can be
     *         null, if such a frame cannot be retrieved.
     */
    public native Bitmap captureFrame();

    /**
     * Call this method after setDataSource(). This method finds the optional
     * graphic or album art associated (embedded or external url linked) the
     * related data source.
     * 
     * @return null if no such graphic is found.
     */
    public native byte[] extractAlbumArt();

    /**
     * Call it when one is done with the object. This method releases the memory
     * allocated internally.
     */
    public native void release();

    private native void native_setup();

    private static native void native_init();

    private native final void native_finalize();

    @Override
    protected void finalize() throws Throwable {
        try {
            native_finalize();
        } finally {
            super.finalize();
        }
    }

    public static final int MODE_GET_METADATA_ONLY = 0x01;
    public static final int MODE_CAPTURE_FRAME_ONLY = 0x02;

    /*
     * Do not change these values without updating their counterparts in
     * include/media/mediametadataretriever.h!
     */
    public static final int METADATA_KEY_CD_TRACK_NUMBER = 0;
    public static final int METADATA_KEY_ALBUM = 1;
    public static final int METADATA_KEY_ARTIST = 2;
    public static final int METADATA_KEY_AUTHOR = 3;
    public static final int METADATA_KEY_COMPOSER = 4;
    public static final int METADATA_KEY_DATE = 5;
    public static final int METADATA_KEY_GENRE = 6;
    public static final int METADATA_KEY_TITLE = 7;
    public static final int METADATA_KEY_YEAR = 8;
    public static final int METADATA_KEY_DURATION = 9;
    public static final int METADATA_KEY_NUM_TRACKS = 10;
    public static final int METADATA_KEY_IS_DRM_CRIPPLED = 11;
    public static final int METADATA_KEY_CODEC = 12;
    public static final int METADATA_KEY_RATING = 13;
    public static final int METADATA_KEY_COMMENT = 14;
    public static final int METADATA_KEY_COPYRIGHT = 15;
    public static final int METADATA_KEY_BIT_RATE = 16;
    public static final int METADATA_KEY_FRAME_RATE = 17;
    public static final int METADATA_KEY_VIDEO_FORMAT = 18;
    public static final int METADATA_KEY_VIDEO_HEIGHT = 19;
    public static final int METADATA_KEY_VIDEO_WIDTH = 20;
    public static final int METADATA_KEY_WRITER = 21;
    public static final int METADATA_KEY_MIMETYPE = 22;
    public static final int METADATA_KEY_DISCNUMBER = 23;
    public static final int METADATA_KEY_ALBUMARTIST = 24;
    // Add more here...
}

Bu benim için çalışmıyor .. System.loadLibrary'de hata ("media_jni");
DArkO

1
Bunun işe yaramadığını teyit edebilirim. Bu yeteneğe de ihtiyacım vardı. Normal bir uygulamanın kullanma iznine sahip olmadığı yerel sistem çağrılarını kullandığı için çalışmaz.
Andy

MediaMetadataRetrieverAPI seviyesi 10'dan desteklenmektedir
Asahi

MediaMetadataRetriever, ikinci kod bloğudur. 10'dan önceki API'lerin (yazarken mevcut olmayan) koda sistem yerine uygulamadan erişmesine izin vermek için mevcuttur. Yerel sistem çağrıları mümkündür, ancak bunları kullanmak için sistemi kabaca anlamanız gerekir. Görünüşe göre sorunun çoğu sağlanan kaynağı yanlış bir şekilde uygulamaktan kaynaklanıyor.
Terkedilmiş Kart

@LoungeKatt, aynı videonun birden fazla görüntüsünü birden çok kez çekmesine izin vermek mümkün mü?
android geliştiricisi

5

Android 1.5 ve 1.6 bu küçük resimleri sunmaz, ancak 2.0 resmi sürüm notlarında görüldüğü gibi sunar :

Medya

  • MediaScanner artık MediaStore'a eklendiklerinde tüm görüntüler için küçük resimler oluşturuyor.
  • Talep üzerine görüntü ve video küçük resimlerini almak için yeni Küçük Resim API'si.

3

Bu soruyu geç cevaplıyorum ama umarım diğer adayın aynı problemle karşılaşmasına yardımcı olur.

İlk video listesi için küçük resim yüklemek için iki yöntem kullandım

    Bitmap bmThumbnail;
    bmThumbnail = ThumbnailUtils.createVideoThumbnail(FILE_PATH
                    + videoList.get(position),
            MediaStore.Video.Thumbnails.MINI_KIND);

    if (bmThumbnail != null) {
        Log.d("VideoAdapter","video thumbnail found");
        holder.imgVideo.setImageBitmap(bmThumbnail);
    } else {
        Log.d("VideoAdapter","video thumbnail not found");
    }

iyi görünüyor ancak bu çözümle ilgili bir sorun vardı çünkü video listesini kaydırdığımda büyük işlemesi nedeniyle bir süre donacak.

Bundan sonra Glide Library kullanarak mükemmel çalışan başka bir çözüm buldum.

 Glide
            .with( mContext )
            .load( Uri.fromFile( new File( FILE_PATH+videoList.get(position) ) ) )
            .into( holder.imgVideo );

Video listesiyle birlikte küçük resim göstermek için sonraki çözümü önerdim. Teşekkürler


-4

Bu, canlı Video küçük resmi kodudur.

public class LoadVideoThumbnail extends AsyncTask<Object, Object, Bitmap>{

        @Override
        protected Bitmap doInBackground(Object... params) {try {

            String mMediaPath = "http://commonsware.com/misc/test2.3gp";
            Log.e("TEST Chirag","<< thumbnail doInBackground"+ mMediaPath);
            FileOutputStream out;
            File land=new File(Environment.getExternalStorageDirectory().getAbsoluteFile()
                            +"/portland.jpg");

                Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(mMediaPath, MediaStore.Video.Thumbnails.MICRO_KIND);
                        ByteArrayOutputStream stream = new ByteArrayOutputStream();
                        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
                        byte[] byteArray = stream.toByteArray();

                        out=new  FileOutputStream(land.getPath());
                        out.write(byteArray);
                        out.close();
                 return bitmap;

            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        return null;
            }
        @Override
        protected void onPostExecute(Bitmap result) {
            // TODO Auto-generated method stub
            super.onPostExecute(result);
            if(result != null){
                 ((ImageView)findViewById(R.id.imageView1)).setImageBitmap(result);
            }
            Log.e("TEST Chirag","====> End");
        }

    }

2
i de null adlı olsun Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(mMediaPath, MediaStore.Video.Thumbnails.MICRO_KIND);tüm parametresinin tanımlanması ayarlandığını Not
Chulo

1
Bitmap'te boş değer bitmap = ThumbnailUtils.createVideoThumbnail (mMediaPath, MediaStore.Video.Thumbnails.MICRO_KIND);
Prasad
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.