热搜: Loading  安卓开发  Android  ios  ShareSDK  开源  Python  生命周期  新手  RecyclerView 
  • 首 页
  •  
     
    当前位置: 首页 » 移动开发 » Android开发 » 正文

    如何进行网络视频截图/获取视频的缩略图

    放大字体  缩小字体 发布日期:2017-02-05  浏览次数:569
    核心提示:小编导读:获取视频的缩略图,截图正在播放的视频某一帧,是在音视频开发中,常遇到的问题。本文是主要用于点播中截图视频,同时还可以获取点播视频的缩略图进行显示,留下一个问题,如下图所示, 如果要获取直播中节目视频缩略图,该怎么做呢?(ps:直播是直

    小编导读:获取视频的缩略图,截图正在播放的视频某一帧,是在音视频开发中,常遇到的问题。本文是主要用于点播中截图视频,同时还可以获取点播视频的缩略图进行显示,留下一个问题,如下图所示, 如果要获取直播中节目视频缩略图,该怎么做呢?(ps:直播是直播流,具有实时性)

    如何进行网络视频截图/获取视频的缩略图

    本文来自HowNoon分享,HowNoon的blog地址为:http://blog.csdn.net/yuehenhn。

    最近博主遇到一个Android电视的开发项目,项目需要电视客户端播放服务器端视频,通过遥控器一键截图,并将截图云推送到手机客户端,于是博主就开始找度神去求助了,毕竟以前没搞过视频,当然要去先搜集下资料再开工啦,正所谓知己知彼,百战百胜嘛,于是,你将看到博主以下两天中的蛋疼经历

    参考内容

    videoview视频播放 http://blog.csdn.net/shenxiaolei507/article/details/41046345

    MediaPlayer+SurfaceView视频播放 http://blog.csdn.net/shenxiaolei507/article/details/41349295

    博主在搜集完资料之后,将两篇文章进行了对比,videoview一切都集成好了,而SurfaceView要设置很多东西,看起来复杂一些,虽然提供了截图方法,但只是用于本地截图,对博主没什么用啊,于是本着省事的原则,果断的选择了videoview。以下是几个走过的坑:

    1

    videoView.getDrawingCache();获取截图

    博主屁颠屁颠的将代码copy下来,先跑跑看,果然执行没问题。好了,那就来找找videoview怎样截图吧,博主回想到以前View截图为调用getDrawingCache(),于是博主机智的先看了看videoview的API文档,发现其中也有这个方法:videoView.getDrawingCache(); 该方法返回值为Bitmap类型,我擦,赶快去使用。结果截到的图片果然不出意外——-黑屏

    2

    videoView.setDrawingCacheEnabled(true); 

    bitmap = videoView.getDrawingCache();获取截图

    既然bitmap = videoView.getDrawingCache();获取不到截图,就该查找原因额,博主又去找度神了,果然好多哥们和博主一样的问题,皆以失败告终。最后碰见一CSDN论坛的朋友回复,知道了其中的缘由,因为view走的是framebuffer,而videoview走的是overlay

    附上各种求救链接

    • http://bbs.csdn.net/topics/390185458

    • http://bbs.csdn.net/topics/390120655

    3

    MediaMetaDataRetreive获取截图

    既然getDrawingCache();方法行不通,看来还是搜集资料不够多,于是博主又找到了MediaMetaDataRetreive这个类

    public static Bitmap getCurrentVideoBitmap(String url,VideoView videoView){
           Bitmap bitmap = null;
           MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
           try {
               mediaMetadataRetriever.setDataSource(url,new HashMap<String, String>());
               Log.e(LOG_STRING,"截图的时间为"+videoView.getCurrentPosition());
               //取得指定时间的Bitmap,即可以实现抓图(缩略图)功能
               bitmap = mediaMetadataRetriever.getFrameAtTime(videoView.getCurrentPosition()*1000,MediaMetadataRetriever.OPTION_CLOSEST);
           } catch (IllegalArgumentException ex) {
               // Assume this is a corrupt video file
           } catch (RuntimeException ex) {
               // Assume this is a corrupt video file.
           } finally {
               try {
                   mediaMetadataRetriever.release();
               } catch (RuntimeException ex) {
                   // Ignore failures while cleaning up.
               }
           }
           if (bitmap == null) {
               return null;
           }
           //bitmap = Bitmap.createScaledBitmap(bitmap, 200, 200, true);
           bitmap = Bitmap.createBitmap(bitmap);
           return bitmap;
    }
    

    getFrameAtTime说明:videoView.getCurrentPosition()得到的为毫秒,不转化为秒的话,截出来的图都是视频第一帧的图像,第二个参数可以传递的值有四个,分别为OPTION_CLOSEST, OPTION_CLOSEST_SYNC, OPTION_NEXT_SYNC, OPTION_PREVIOUS_SYNC

    博主前期用的参数为OPTION_NEXT_SYNC,博主以为问题解决了,去干别的事情了,但等到晚上测试的时候却发现一个问题,这种方案截图是可以,但仅仅做个没播放视频之前的缩略图还算可以,但真的做实时截图还是不妥,这是因为:经博主测试,这种方法截图的画面,和电视截图的画面,存在着1-2秒的误差,也就是说截出的图完全不一样(测试机器三星Note4,华为荣耀6Plus),博主又失败了。

    4

    OPTION_CLOSEST_SYNC参数换为OPTION_CLOSEST

    博主在思考,既然网上好多文章都说这种方法可以实现,会不会是我的参数有问题,于是楼主找到了很多相同的文章介绍

    例如: http://blog.sina.com.cn/s/blog_7bac47070101bys8.html

    http://yashirocc.blog.sohu.com/175636801.html

    同时博主又搜集了一些资料,并仔细查看了getFrameAtTime方法的详细参数

    以下为各参数详解

    如何进行网络视频截图/获取视频的缩略图

    新发现:原来视频文件存在关键帧的问题,通过度神理解,原来是可能getFrameAtTime传入的时间值,在视频的那一刻,并没有关键帧,所以OPTION_CLOSEST_SYNC返回的值为附近的时间截图。根据博主参考API的详情,果断换成了OPTION_CLOSEST。

    参看资料:

    如何进行网络视频截图/获取视频的缩略图

    失败:有些截图是正常了,但是有些时间的截图却直接返回null,尼玛这是在坑爹啊。。。

    5

    寻找第三方框架截图

    虽然前面都失败了,不过博主的资料搜集的又全了些,博主打算开始找第三方框架了,于是博主找到了比较出名的两个框架

    • Vitamio https://www.vitamio.org/ 国人开发的框架

      导入代码测试,这个框架好像将videoview封装了一层,叫mVideoview,据官网介绍,截图方法为getCurrentFrame();不过据博主测试,返回值为空。

      如何进行网络视频截图/获取视频的缩略图
    • vlc for android http://blog.csdn.net/banketree/article/details/39575973

      导入代码进行测试,发现该框架代码里默认为rtps协议视频,并且封装了C++的so文件,使用到了JNI技术,截图什么的还要自己打补丁,看了看各位大神的文章介绍,看起来好复杂,本人水平有限,就默默放弃了。

      6

    TextureView播放视频并截图

    博主在度神上已经实在找不到方法了,博主打算去翻墙google一下,功夫不负有心人,老外也碰到了和博主一样的问题,博主找到了新的一个解决方案,那就是TextureView播放视频并截图,后来搜集了下情报,据说这玩意是2014年google搞出来的玩意。

    附上链接: http://stackoverflow.com/questions/27435985/how-to-capture-screenshot-of-videoview-when-streaming-video-in-android How to capture screenshot of VideoView when streaming video in Android [duplicate]

    附上回答:

    如何进行网络视频截图/获取视频的缩略图

    附上翻译:

    **我已经找到了解决这个问题的办法。看来VideoView不允许因为底层硬件GPU的原因而使用SurfaceView。

    该解决方案是使用一个textureview使用MediaPlayer播放视频里面。该活动将需要实现textureview.surfacetexturelistener。当用这个解决方案的截图,视频冻结了一段时间。同时,该textureview不显示播放进度条默认UI(播放,暂停,快进/ RW,玩的时间,等)。这是一个缺点。如果你有另一个解决方案,请让我知道:)**

    看到这个页面,当然废话不多说了,建工程,copy,测试!

    public class TextureViewActivity extends Activity
       implements TextureView.SurfaceTextureListener,
                   OnBufferingUpdateListener,
                   OnCompletionListener,
                   OnPreparedListener,
                   OnVideoSizeChangedListener {
       private MediaPlayer mp;    private TextureView tv;    public static String MY_VIDEO = "https://www.blahblahblah.com/myVideo.mp4";    public static String TAG = "TextureViewActivity";    @Override
       protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);
           setContentView(R.layout.activity_texture_view);
           tv = (TextureView) findViewById(R.id.textureView1);
           tv.setSurfaceTextureListener(this);
       }    public void getBitmap(TextureView vv)
       {
           String mPath = Environment.getExternalStorageDirectory().toString()
                   + "/Pictures/" + Utilities.getDayTimeString() + ".png";  
           Toast.makeText(getApplicationContext(), "Capturing Screenshot: " + mPath, Toast.LENGTH_SHORT).show();
           Bitmap bm = vv.getBitmap();        if(bm == null)
               Log.e(TAG,"bitmap is null");
           OutputStream fout = null;
           File imageFile = new File(mPath);        try {
               fout = new FileOutputStream(imageFile);
               bm.compress(Bitmap.CompressFormat.PNG, 90, fout);
               fout.flush();
               fout.close();
           } catch (FileNotFoundException e) {
               Log.e(TAG, "FileNotFoundException");
               e.printStackTrace();
           } catch (IOException e) {
               Log.e(TAG, "IOException");
               e.printStackTrace();
           }
       }    @Override
       public boolean onCreateOptionsMenu(Menu menu) {        // Inflate the menu; this adds items to the action bar if it is present.
           getMenuInflater().inflate(R.menu.media_player_video, menu);        return true;
       }    @Override
       public boolean onOptionsItemSelected(MenuItem item) {        // Handle action bar item clicks here. The action bar will
           // automatically handle clicks on the Home/Up button, so long
           // as you specify a parent activity in AndroidManifest.xml.
           int id = item.getItemId();        if (id == R.id.action_settings) {            return true;
           }        return super.onOptionsItemSelected(item);
       }    @Override
       public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height)
       {
           Surface s = new Surface(surface);        try
           {
               mp = new MediaPlayer();
               mp.setDataSource(MY_VIDEO);
               mp.setSurface(s);
               mp.prepare();
               mp.setOnBufferingUpdateListener(this);
               mp.setOnCompletionListener(this);
               mp.setOnPreparedListener(this);
               mp.setOnVideoSizeChangedListener(this);
               mp.setAudioStreamType(AudioManager.STREAM_MUSIC);
               mp.start();
               Button b = (Button) findViewById(R.id.textureViewButton);
               b.setOnClickListener(new OnClickListener(){                @Override
                   public void onClick(View v)
                   {
                       TextureViewActivity.this.getBitmap(tv);
                   }
               });
           }        catch (IllegalArgumentException e) {            // TODO Auto-generated catch block
               e.printStackTrace();
           } catch (SecurityException e) {            // TODO Auto-generated catch block
               e.printStackTrace();
           } catch (IllegalStateException e) {            // TODO Auto-generated catch block
               e.printStackTrace();
           } catch (IOException e) {            // TODO Auto-generated catch block
               e.printStackTrace();
           }  
       }
    

    问题终结

    经过博主反复测试TextureView的getBitmap();方法,完美截图,无任何时差,无返回值为null问题,无截图花屏问题,该问题终于终结了,历时一天半,过程虽然心酸,但收获了许多关于视频方面相关的知识。博主在搜集资料的同时,看到了很多像博主一样对该问题的困扰,故将详细经历总结出来,希望不要再有人步博主后尘了。完毕,收工。

    第一时间获得博客更新提醒,以及更多 android,源码分析,最新开源项目推荐,更多有价值的思考 ,欢迎关注我的微信公众号,扫一扫下方二维码或者长按识别二维码,即可关注。

    如何进行网络视频截图/获取视频的缩略图


    小编为您推荐“如何进行网络视频截图/获取视频的缩略图”相关文章

    Android仿微信菜单(Menu)(使用C#和Java分别实
    这篇文章主要介绍了Android仿微信菜单(Menu)(使用C#和Java分别实现),本文分别给出C#和Java版的运行效果及实现代码,需要的朋友可以参考下

    A09_Spinner(下拉列表)自定义设置
    Spinner控件是一个下拉列表实现自定义设置:使用的监听器接口是:OnItemSelectedListener,自定义实现如下感兴趣的朋友可以参考下哈

    苹果公司推出的新编程语言Swift简介和入门教程
    这篇文章主要介绍了苹果公司推出的新编程语言Swift简介和入门教程,Swift是苹果于WWDC 2014.6.3发布的编程语言,主要用来替代Objective-C,需要的朋友可以参考下

    iOS内存错误EXC_BAD_ACCESS的解决方法
    iOS开发,最郁闷的莫过于程序毫无征兆地就崩溃了,用bt命令打出调用栈,给出的是一堆系统EXC_BAD_ACCESS的信息,根本没办法定位问题出现在哪里

    [译] Android API 指南
    众所周知,Android开发者有中文网站了,API 指南一眼看去最左侧的菜单都是中文,然而点进去内容还是很多是英文,并没有全部翻译,我这里整理了API 指南的目录,便于查看,如果之前还没有通读,现在可以好好看一遍。注意,如果标题带有英文,说明官方还没有翻

     
     
     
    猜你想看
     
    更多..
    与本文有关Bitmap
    • 不得不知道的图片加载框架之Glide
      不得不知道的图片加载框架之Glide
      简介在泰国举行的谷歌开发者论坛上,谷歌为我们介绍了一个名叫 Glide 的图片加载库,作者是bumptech。这个库被广泛的运用在google的开源项目中,包括2014年google I/O大会上发布的官方app。特点(1)使用简单(2)可配置度高,自适应程度高(3)支持常见图片
      02-05 关键词:Bitmap安卓开发
    • 一个实用方便的图片控件SImageView
      一个实用方便的图片控件SImageView
      控件介绍 这是一个简单到 sImageView.setImageUrls(http://img3.cache.netease.com/ent/2009/4/17/20090417104402666a4.jpg); 设置一个网址即可显示图片的控件相对 ImageView 功能的扩展的控件, 但是没有继承 ImageView 直接继承的 View . 比如 QQ群组头像 ,
      12-23 关键词:Bitmap安卓开发
    • Android开发艺术探索学习笔记(三)—Android性能优化之Bitmap导致的内存溢出
      Android开发艺术探索学习笔记(三)—Android性能
      原本计划是按照章节顺序学习《Android开发艺术探索》这本书的,Android性能优化这部分也是本书的最后一章。但是周末的时候,友盟线下反馈的公司项目的一个错误让我不得不提前学习这一块的知识。先看看线下反馈的错误吧:java.lang.OutOfMemoryError:应用程序
      12-06 关键词:Bitmap安卓开发
    • Android图形图像使用总结
      Android图形图像使用总结
      一.图形特效(一)特效的实现方式在Android中,提供了3种方式实现特效,setXXX方法,postXXX和preXXX()方法。1.setXXX方法用于直接设置Matrix的值,每使用一次setXXX()方法,整个的Matrix都会变掉。2.postXXX方法用于采用后乘的方式为Matrix设置值,可以连续多次
      12-01 关键词:Bitmap安卓开发
    • AsyncTask 工作原理(上)
      AsyncTask 是一种轻量级是异步任务类,它可以在线程池中执行后台任何,将执行的进度和最终结果传递给主线程,并在主线程中更新UI。AsyncTask 是一个抽象类,其构造函数//Params:传入doInBackground 中的参数类型//Progress: 后台执行进度的类型,传入onProgre
      11-10 关键词:AsyncTaskBitmap
    • vysor 原理以及 Android 同屏方案
      vysor是一个免root实现电脑控制手机的chrome插件,目前也有几款类似的通过电脑控制手机的软件,不过都需要root权限,并且流畅度并不高。vysor没有多余的功能,流畅度也很高,刚接触到这款插件时我惊讶于它的流畅度以及免root,就一直对它的实现原理很感兴趣。
      10-13 关键词:Bitmap安卓开发
    • 简单实现 Android 图片三级缓存机制
      简单实现 Android 图片三级缓存机制
      用户在使用我们的APP时,通常会重复浏览一些图片,这时如果每一次浏览都需要通过网络获取图片,那么将会非常流量。为了节省用户流量,提高图片加载效率,我们通常使用图片三级缓存策略,即通过网络、本地、内存三级缓存图片,来减少不必要的网络交互,避免浪
      10-13 关键词:Bitmap安卓开发
    • Picasso 解析 (1)- 一张图片是如何加载出来的
      前言Picasso是JakeWharton大神在github上的一个开源图片加载框架,使用起来极其方便,甚至只需要一行代码就可以搞定图片加载:Picasso.with(context).load(http://i.imgur.com/DvpvklR.png).into(imageView);具体如何使用该框架我就不在这里赘述了,大家可以
      10-04 关键词:Bitmap安卓开发
    • 自定义圆形图片、可控位置圆角图片
      自定义圆形图片、可控位置圆角图片
      一.原理1.下面的Xfermode子类可以改变这种行为:AvoidXfermode 指定了一个颜色和容差,强制Paint避免在它上面绘图(或者只在它上面绘图)。PixelXorXfermode 当覆盖已有的颜色时,应用一个简单的像素XOR操作。PorterDuffXfermode 这是一个非常强大的转换模式,
      09-14 关键词:Bitmap安卓开发
    • Android的oom详解
      Android的oom详解
      oom的定义OOM(out of memory)即内存泄露。一个程序中,已经不需要使用某个对象,但是因为仍然有引用指向它垃圾回收器就无法回收它,当该对象占用的内存无法被回收时,就容易造成内存泄露。Android的oom原因1.资源对象没关闭造成的内存泄露,try catch final
      09-12 关键词:BitmapOOM
     
    相关评论
     
    猜你喜欢
     
    网站首页 | 关于我们 | 联系方式 | 使用协议 | 版权隐私 | 网站地图 | 网站留言