라이브러리 대화 상자로 비디오 녹화 응용 프로그램을 만들었습니다. 라이브러리 대화 상자에는 각 항목이 아이콘, 비디오 제목, 태그 및 위치 정보로 구성된 녹화 된 비디오 목록이 다음과 같은 방식으로 표시됩니다.
아이콘을 비디오 섬네일 (단일 프레임 미리보기)로 대체 할 수 있는지 아는 사람이 있습니까?
감사!
답변
API 2.0 이상을 사용하는 경우 작동합니다.
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);
답변
커서를 통과하지 않거나 이동할 수없고 경로 또는 File 객체 만있는 경우 API 레벨 8 (2.2) 공용 정적 비트 맵 createVideoThumbnail (String filePath, int kind)부터 사용할 수 있습니다.
다음 코드는 완벽하게 실행됩니다.
Bitmap bMap = ThumbnailUtils.createVideoThumbnail(file.getAbsolutePath(), MediaStore.Video.Thumbnails.MICRO_KIND);
답변
수업 사용 :
import android.provider.MediaStore.Video.Thumbnails;
비디오에서 두 가지 미리보기 썸네일 크기를 얻을 수 있습니다.
Thumbnails.MICRO_KIND
96 x 96 용
Thumbnails.MINI_KIND
512 x 384 픽셀 용
다음은 코드 예입니다.
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);
답변
현재 다음 코드를 사용합니다.
Bitmap bMap = ThumbnailUtils.createVideoThumbnail(file.getAbsolutePath(), MediaStore.Video.Thumbnails.MICRO_KIND);
그러나 다음 코드 로 Glide 라이브러리로 더 나은 솔루션을 찾았습니다 (또한 이미지를 캐시하고 이전 접근 방식보다 더 나은 성능을 제공합니다)
Glide.with(context)
.load(uri)
.placeholder(R.drawable.ic_video_place_holder)
.into(imageView);
답변
Glide 라이브러리 를 사용하는 것이 좋습니다 . 로컬 비디오 파일에 대한 비디오 썸네일을 생성하고 표시하는 가장 효율적인 방법 중 하나입니다.
gradle 파일에 다음 줄을 추가하십시오.
compile 'com.github.bumptech.glide:glide:3.7.0'
그리고 그것은 다음과 같이 간단해질 것입니다.
String filePath = "/storage/emulated/0/Pictures/example_video.mp4";
Glide
.with( context )
.load( Uri.fromFile( new File( filePath ) ) )
.into( imageViewGifAsBitmap );
여기에서 더 많은 정보를 찾을 수 있습니다 : https://futurestud.io/blog/glide-displaying-gifs-and-videos
건배!
답변
이 솔루션은 모든 버전의 Android에서 작동합니다. 1.5 및 2.2에서 작동하는 것으로 입증되었습니다. 이것은 또 다른 “This is for Android 2.0+”솔루션이 아닙니다. 이메일 게시판 컬렉션 페이지를 통해 찾았는데 원본 링크를 찾을 수 없습니다. 모든 크레딧은 원래 포스터에 있습니다.
앱에서 다음을 호출하여이를 사용합니다.
Bitmap bm = getVideoFrame(VideoStringUri);
자체 기능 (OnCreate 외) 어딘가에 다음이 필요합니다.
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 폴더에이 함수를 사용할 수있는 클래스 (안드로이드 소스 자체에서 복사)를 저장할 새 하위 디렉토리 android / media가 필요합니다. 이 부분은 변경하거나 이름을 바꾸거나 다른 곳에 배치해서는 안됩니다. 이 모든 것이 작동하려면 MediaMetadataRetriever.java가 소스 폴더의 android.media 아래에 있어야합니다.
/*
* 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...
}
답변
나를 위해 일하는 이것을 시도하십시오
RequestOptions requestOptions = new RequestOptions();
Glide.with(getContext())
.load("video_url")
.apply(requestOptions)
.thumbnail(Glide.with(getContext()).load("video_url"))
.into("yourimageview");