最近公司在APP内部嵌了视频交友功能,由于之前没怎么接触过视频功能,自然就想到了用第三方sdk,结果用了云信的sdk全家桶,包括直播,音视频播放,上传等,但是用下来发现有巨坑.....
在视频播放时他们的播放器sdk并没有兼容带有旋转信息的视频,原本想着用github上的开源库,试了很多start很高的播放器,无奈兼容都有问题,毕竟源视频是云信自己处理的,用他们播放器sdk兼容肯定会好点,所以,只能自己改代码解决这个问题了!
第一步,怎么把视频旋转回正常的角度:
查看代码发现他们是用SurfaceView作为容器播放视频,便想着能不能把SurfaceView旋转一定角度来解决这个问题,便尝试设置
SurfaceView。setRotation(90)发现然并卵,后通过查资料发现可以从Canvas 里面着手,便用
Canvas canvas = SurfaceHolder.lockCanvas();// 锁定画布,一般在锁定后就可以通过其返回的画布对象Canvas,在其上面画图等操作
canvas.rotate(90)发现视频变形了,变的不居中了,变的.....最重要的是视频还是没被纠正旋转角度!发现SurfaceView不好旋转后便想着能不能换一种视频容器,一查资料,还真有,这时TextureView映入眼帘,我眼前一亮,赶忙试了试,由原先的
mMediaPlayer.setDisplay(mSurfaceHolder);改成了TextureView.setRotation(90);
mMediaPlayer.setSurface(new Surface(surfaceTexture));
沃德天,居然有效,我仿佛看到了希望!
第二步,怎么获取视频的旋转角度:
百度了各种资料,各个论坛,貌似都没有好的解决方案,看来要使出终极武器了(哒哒哒,能冒蓝火的那种),随即我拿出了谷歌大法,最后终于找到了解决方案:
public int getVideoRoration(String mUri) { int roration = 0; android.media.MediaMetadataRetriever mmr = new android.media.MediaMetadataRetriever(); try { if (mUri != null) { HashMap headers = null; if (headers == null) { headers = new HashMap (); headers.put("User-Agent", "Mozilla/5.0 (Linux; U; Android 4.4.2; zh-CN; MW-KW-001 Build/JRO03C) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 UCBrowser/1.0.0.001 U4/0.8.0 Mobile Safari/533.1"); } if (mUri.startsWith("http")) { mmr.setDataSource(mUri, headers); } else { mmr.setDataSource(mUri); } } String duration = mmr.extractMetadata(android.media.MediaMetadataRetriever.METADATA_KEY_DURATION);//时长(毫秒) String width = mmr.extractMetadata(android.media.MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);//宽 String height = mmr.extractMetadata(android.media.MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);//高 String rotationStr = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION); // 视频旋转方向 if (!StringUtil.isEmpty(rotationStr)) { return Integer.parseInt(rotationStr); } Log.e("TAG", "rotation" + rotationStr); } catch (Exception ex) { Log.e("TAG", "MediaMetadataRetriever exception " + ex); ex.printStackTrace(); } finally { mmr.release(); } return roration; }
但是官方说明这种方法最低支持api10,不过在我们的项目的支付版本内;(API 10 之前有 不对外开放 -不过可以反射获取)运行,测试,no perfect,视频能正常播放了;但是发现视频的宽高比不正常,这个嘛,小意思,根据视频的旋转角度重置下视频的宽高就是了直接上代码:@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int videoWidth = getDefaultSize(mVideoWidth, widthMeasureSpec); int videoHeight = getDefaultSize(mVideoHeight, heightMeasureSpec); int width = getDefaultSize(videoWidth, widthMeasureSpec); int height = getDefaultSize(videoHeight, heightMeasureSpec); int widthS = getDefaultSize(videoWidth, widthMeasureSpec); int heightS = getDefaultSize(videoHeight, heightMeasureSpec); if (originW == 0 || originH == 0) { originW = widthS; originH = heightS; } if (videoWidth > 0 && videoHeight > 0) { int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec); int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); if (widthSpecMode == MeasureSpec.EXACTLY && heightSpecMode == MeasureSpec.EXACTLY) { width = widthSpecSize; height = heightSpecSize; if (videoWidth * height < width * videoHeight) { width = height * videoWidth / videoHeight; } else if (videoWidth * height > width * videoHeight) { height = width * videoHeight / videoWidth; } } else if (widthSpecMode == MeasureSpec.EXACTLY) { width = widthSpecSize; height = width * videoHeight / videoWidth; if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) { height = heightSpecSize; } } else if (heightSpecMode == MeasureSpec.EXACTLY) { height = heightSpecSize; width = height * videoWidth / videoHeight; if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) { width = widthSpecSize; } } else { width = videoWidth; height = videoHeight; if (heightSpecMode == MeasureSpec.AT_MOST && height > heightSpecSize) { height = heightSpecSize; width = height * videoWidth / videoHeight; } if (widthSpecMode == MeasureSpec.AT_MOST && width > widthSpecSize) { width = widthSpecSize; height = width * videoHeight / videoWidth; } } } else { // no size yet, just adopt the given spec sizes } boolean rotate = (getRotation() != 0 && getRotation() % 90 == 0 && Math.abs(getRotation()) != 180); if (rotate) { if (widthS < heightS) { if (width > height) { width = (int) (width * (float) widthS / height); height = widthS; } else { height = (int) (height * (float) width / widthS); width = widthS; } } else { if (width > height) { height = (int) (height * (float) width / widthS); width = widthS; } else { width = (int) (width * (float) widthS / height); height = widthS; } } } //全屏 if (rotate && getRotation() != 0) { if (width > height) { if (height < originW) { width = (int) (width * ((float) originW / height)); height = originW; } else if (width < originH) { height = (int) (height * ((float) originH / width)); width = originH; } } else { if (width < originH) { height = (int) (height * ((float) originH / width)); width = originH; } else if (height < originW) { width = (int) (width * ((float) originW / height)); height = originW; } } } else { if (height > width) { if (width < widthS) { height = (int) (height * ((float) widthS / width)); width = widthS; } else { width = (int) (width * ((float) heightS / height)); height = heightS; } } else { if (height < heightS) { width = (int) (width * ((float) heightS / height)); height = heightS; } else { height = (int) (height * ((float) widthS / width)); width = widthS; } } } setMeasuredDimension(width, height); }
运行,测试,perfect,总算告一段落了。
后来整理资料发现有一个第三方库可以获取更完善的视频信息,并且可以兼容到api7,大家有兴趣的可以试试:https://github.com/wseemann/FFmpegMediaMetadataRetriever;
再回头看看,我去,我TM都写了些什么啊,上张福利图给大家,别打我脸!