滑音 - 在特定时间从视频加载单帧?

时间:2015-06-10 20:40:38

标签: android picasso android-glide

我试图使用Glide逐步浏览视频文件中的帧(而不会遇到关键帧寻找Android遭受的问题)。我可以通过以下方式在毕加索做到这一点:

picasso = new Picasso.Builder(MainActivity.this).addRequestHandler(new PicassoVideoFrameRequestHandler()).build();
picasso.load("videoframe://" + Environment.getExternalStorageDirectory().toString() +
                    "/source.mp4#" + frameNumber)
                    .placeholder(drawable)
                    .memoryPolicy(MemoryPolicy.NO_CACHE)
                    .into(imageView);

(frameNumber只是一个int,每次增加50000微秒)。我也有像这样的PicassoVideoFrameRequestHandler:

public class PicassoVideoFrameRequestHandler extends RequestHandler {
public static final String SCHEME = "videoframe";

@Override public boolean canHandleRequest(Request data) {
    return SCHEME.equals(data.uri.getScheme());
}

@Override
public Result load(Request data, int networkPolicy) throws IOException {
    FFmpegMediaMetadataRetriever mediaMetadataRetriever = new FFmpegMediaMetadataRetriever();
    mediaMetadataRetriever.setDataSource(data.uri.getPath());
    String offsetString = data.uri.getFragment();
    long offset = Long.parseLong(offsetString);
    Bitmap bitmap = mediaMetadataRetriever.getFrameAtTime(offset, FFmpegMediaMetadataRetriever.OPTION_CLOSEST);
    return new Result(bitmap, Picasso.LoadedFrom.DISK);
}

}

我想改用Glide,因为它可以更好地处理内存。有没有办法在Glide中使用此功能?

或者,实际上,从视频创建一组帧的任何其他方式我可以单步执行!

谢谢!

3 个答案:

答案 0 :(得分:12)

你需要通过" .override(宽度,高度)"让Sam Judd的方法奏效。否则,您只会获得视频的第一帧,因为我已经测试了几个小时的各种方法。希望它为某人节省时间。

BitmapPool bitmapPool = Glide.get(getApplicationContext()).getBitmapPool();
int microSecond = 6000000;// 6th second as an example
VideoBitmapDecoder videoBitmapDecoder = new VideoBitmapDecoder(microSecond);
FileDescriptorBitmapDecoder fileDescriptorBitmapDecoder = new FileDescriptorBitmapDecoder(videoBitmapDecoder, bitmapPool, DecodeFormat.PREFER_ARGB_8888);
Glide.with(getApplicationContext())
    .load(yourUri)
    .asBitmap()
    .override(50,50)// Example
    .videoDecoder(fileDescriptorBitmapDecoder)
    .into(yourImageView);

答案 1 :(得分:6)

您可以将帧时间(以微秒为单位,请参阅MediaMetadataRetriever docs)传递给VideoBitmapDecoder。这是未经测试的,但它应该有效:

BitmapPool bitmapPool = Glide.get(context).getBitmapPool();
FileDescriptorBitmapDecoder decoder = new FileDescriptorBitmapDecoder(
    new VideoBitmapDecoder(frameTimeMicros),
    bitmapPool,
    DecodeFormat.PREFER_ARGB_8888);

Glide.with(fragment)
    .load(uri)
    .asBitmap()
    .videoDecoder(decoder)
    .into(imageView);

答案 2 :(得分:2)

谢谢,这篇帖子帮助我到达那里。顺便说一句,如果你使用Glide 4.4,他们会改变你得到这个结果的方式。从视频uri加载特定帧。

您只需使用对象RequestOptions,如下所示:

long interval = positionInMillis * 1000;
RequestOptions options = new RequestOptions().frame(interval);
Glide.with(context).asBitmap()
                    .load(videoUri)
                    .apply(options)
                    .into(viewHolder.imgPreview);

其中“positionInMillis”是您想要图像的视频位置的长变量。