问题 VideoView getDrawingCache返回黑色


所以我试图做一个VideoView的屏幕截图。我认为最简单的方法是:

videoView.setDrawingCacheEnabled(true);

然后我需要截取屏幕截图:

Bitmap screenshot = videoView.getDrawingCache();

但由于某种原因,我回来的位图每次都是黑色的。任何人都有这个成功吗?我也尝试过:

Bitmap bitmap = Bitmap.createBitmap(videoView.getWidth(), videoView.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
videoView.draw(canvas);

但是再次,这给我一个黑色的图像。我可以看到VideoView几乎没有在Android javadocs中记录。有帮助吗?


12094
2018-03-11 21:44


起源

这让我想起曾经尝试在WMP中使用Print screen和paint截取视频截图的过去。我认为这是一个问题,表面视图只是窗口中的透明层,因此无法像您尝试的那样进行快照。 - deed02392


答案:


来自文档 查看#setDrawingCacheEnabled

启用绘图缓存类似   在硬件上设置图层   加速度已关闭。什么时候   硬件加速已打开,   启用绘图缓存没有   因为系统对渲染的影响   使用不同的机制   忽略旗帜的加速度。   如果你想使用Bitmap   查看,即使硬件加速   已启用,请参阅setLayerType(int,   android.graphics.Paint)for   有关如何启用软件的信息   和硬件层。

VideoView可能通过硬件加速运行并绕过缓存机制。一个好的潜水源潜水可能会有所启发。

编辑  - 这个帖子 似乎清除了一些事情:

抱歉,SurfaceView本身就是这样   不在普通视图层次结构中绘制   更新系统,因此不会被绘制   那。

(VideoView是SurfaceView的孩子)


13
2018-03-11 22:10



嗯。我可以看到一个视图在javadocs中有setLayerType,但是我的VideoView没有setLayerType,View也没有显示它使用的常量(将它设置为View.LAYER_TYPE_SOFTWARE)。这是一个奇怪的类。它还在javadocs中说VideoView有一个resume()方法,但是我没有显示其中的一个?我会继续四处寻找并可能潜入源头。 - Brayden
您应该将SurfaceView视为硬件魔术。您的代码显然无法在移动到屏幕时触摸这些位。 - Matthew Willis
是的,我意识到了这一点。所以基本上。我不能从VideoView截取屏幕截图? - Brayden
不幸的是,我认为你不能。 - Matthew Willis
SurfaceView是窗口内的“洞”,因此无法在位图内缓存。我们知道这个限制,我们希望得到更好的东西,但现在没有任何计划。 - Romain Guy


从API 10开始,您就可以使用了 MediaMetadataRetriever 在给定时间检索框架(在 微秒)。这是一个示例代码:

public Bitmap videoFrame(String uri, long msec) {       
    MediaMetadataRetriever retriever = new MediaMetadataRetriever();
    try {                       
        retriever.setDataSource(uri);            
        return retriever.getFrameAtTime(msec);
    } catch (IllegalArgumentException ex) {
        ex.printStackTrace();
    } catch (RuntimeException ex) {
        ex.printStackTrace();
    } finally {
        try {
            retriever.release();
        } catch (RuntimeException ex) {
        }
    }
    return null;
}

0
2017-10-28 09:48



我很长一段时间没有重访过这个,但是很高兴知道,谢谢。但是,这对我的实例没有任何帮助,因为我想要截图的是流媒体视频。 - Brayden
@Arbi谢谢,我能够通过手机本地存储的视频来做到这一点。但是,当视频在VideoView中流式传输时,我似乎无法捕获视频帧。你知不知道怎么? - codeshark
你需要得到流媒体视频的uri - bachr
嗨@Arbi。我放了一个样本“test.com/myVideo.mp4";进入uri参数但不成功。似乎上面的函数videoFrame()仅在视频下载到设备上时才有效 - codeshark
你没有提供协议(我想知道你是否能够播放视频)。尝试类似的东西 new URL("you_full_url").toExternalForm() 确保你提供了一个正确的网址,否则你会看到一个例外。 - bachr