转载:裁剪正方形视频

转自:http://blog.csdn.net/coderyue/article/details/52830564 

github:https://github.com/jinguangyue/Android-CustomCamera

1. 获取相机实例

/**    * 获取Camera实例

  *    *@return

*/

privateCameragetCamera(intid) {       

Camera camera =null;

try{           

camera = Camera.open(id);      

}catch(Exception e) {      

}

returncamera;    }

2.  开启预览

要注意, 开启预览要在 Activity 的 onResume 方法里面开启, 然后在 onPause 方法里面释放相机资源, 举一个简单的例子, 如果你在预览的时候按下了home键, 此时再次打开程序, 如果你是在 Oncreate 方法里面开启相机, 那么再次打开预览界面应该会卡住。

/**

* 预览相机

*/

privatevoidstartPreview(Camera camera, SurfaceHolder holder) {

try{          

setupCamera(camera);    

camera.setPreviewDisplay(holder);

recorderRotation = CameraUtil.getInstance().getRecorderRotation(mCameraId);            CameraUtil.getInstance().setCameraDisplayOrientation(this, mCameraId, camera);            camera.startPreview();      

}catch(IOException e) {          

e.printStackTrace();     

  }  

}

/**

* 设置

*/

privatevoidsetupCamera(Camera camera) {

if(camera !=null) {           

Camera.Parameters parameters = camera.getParameters();          

List focusModes = parameters.getSupportedFocusModes();

if(focusModes !=null&& focusModes.size() >0) {

if(focusModes.contains(                        Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {                                        parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);                }        

  }       

    List videoSiezes =null;if(parameters !=null) {                

              videoSiezes = parameters.getSupportedVideoSizes();

for(Camera.Size size : videoSiezes) {       

        }       

    }

if(videoSiezes !=null&& videoSiezes.size() >0) {        

                      Camera.Size videoSize = CameraUtil.getInstance().getPropVideoSize(videoSiezes,720);     

          video_width = videoSize.width;    

          video_height = videoSize.height;      

        LogUtils.i("video_width==="+ video_width);     

          LogUtils.i("video_height==="+ video_height);     

      }           

            Camera.Size previewSize = CameraUtil.getInstance().getPropPreviewSize(parameters.getSupportedPreviewSizes(), video_width);    

      parameters.setPreviewSize(previewSize.width, previewSize.height);      

    Camera.Size pictrueSize = CameraUtil.getInstance().getPropPictureSize(parameters.getSupportedPictureSizes(), video_width);            parameters.setPictureSize(pictrueSize.width, pictrueSize.height);            camera.setParameters(parameters);

/**

* 设置surfaceView的尺寸 因为camera默认是横屏,所以取得支持尺寸也都是横屏的尺寸

* 我们在startPreview方法里面把它矫正了过来,但是这里我们设置设置surfaceView的尺寸的时候要注意 previewSize.height

* previewSize.width才是surfaceView的高度

* 一般相机都是屏幕的宽度 这里设置为屏幕宽度 高度自适应 你也可以设置自己想要的大小

*/

FrameLayout.LayoutParams params =newFrameLayout.LayoutParams(screenWidth, (screenWidth * video_width) / video_height);         

              surfaceView.setLayoutParams(params);    

      RelativeLayout.LayoutParams layoutParams =newRelativeLayout.LayoutParams(screenWidth, screenheight - screenWidth);    

      layoutParams.addRule(RelativeLayout.BELOW, surfaceView.getId());            layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);            bottomLayout.setLayoutParams(layoutParams);  

    } 

  }

3. 开始录制

这里要注意的是 MediaRecorder 的相关方法的调用顺序时候不能乱的, 详细可以看官网api说明

接下来开启录制:

protected void start() {        try {            pathName = System.currentTimeMillis() +""//视频存储路径            file = new File(MyApplication.getInstance().getTempPath() + File.separator+ pathName + AppConfig.MP4)            //如果没有要创建            BitmapUtils.makeDir(file)            //初始化一个MediaRecorder            if (mediaRecorder == null) {                mediaRecorder = new MediaRecorder()            } else {                mediaRecorder.reset()            }            mCamera.unlock()            mediaRecorder.setCamera(mCamera)            //设置视频输出的方向 很多设备在播放的时候需要设个参数 这算是一个文件属性            mediaRecorder.setOrientationHint(recorderRotation)            //视频源类型            mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA)            mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC)            mediaRecorder.setAudioChannels(2)            // 设置视频图像的录入源            // 设置录入媒体的输出格式//            mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)            // 设置音频的编码格式//            mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)            // 设置视频的编码格式//            mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264)            if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_720P)) {                profile = CamcorderProfile.get(CamcorderProfile.QUALITY_720P)            }  else if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_1080P)) {                profile = CamcorderProfile.get(CamcorderProfile.QUALITY_1080P)            } else if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_HIGH)) {                profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)            } else if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_LOW)) {                profile = CamcorderProfile.get(CamcorderProfile.QUALITY_LOW)            }            if (profile != null) {                profile.audioCodec= MediaRecorder.AudioEncoder.AACprofile.audioChannels=1profile.audioSampleRate=16000profile.videoCodec= MediaRecorder.VideoEncoder.H264                mediaRecorder.setProfile(profile)            }            //视频尺寸            mediaRecorder.setVideoSize(video_width, video_height)            //数值越大 视频质量越高            mediaRecorder.setVideoEncodingBitRate(5*1024*1024)            // 设置视频的采样率,每秒帧数//            mediaRecorder.setVideoFrameRate(5)            // 设置录制视频文件的输出路径            mediaRecorder.setOutputFile(file.getAbsolutePath())            mediaRecorder.setMaxDuration(2000)            // 设置捕获视频图像的预览界面            mediaRecorder.setPreviewDisplay(surfaceView.getHolder().getSurface())            mediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {                @Override                public void onError(MediaRecorder mr, int what, int extra) {                    // 发生错误,停止录制                    if (mediaRecorder != null) {                        mediaRecorder.stop()                        mediaRecorder.release()                        mediaRecorder = null                        LogUtils.i("Error")                    }                }            })            mediaRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {                @Override                public void onInfo(MediaRecorder mr, int what, int extra) {                    //录制完成                }            })            // 准备、开始            mediaRecorder.prepare()            mediaRecorder.start()            new Thread(new Runnable() {                @Override                public void run() {                    for (int i =0try {                            Thread.currentThread().sleep(20)                            Message message = new Message()                            message.what=1message.obj= i                            handler.sendMessage(message)                        } catch (InterruptedException e) {                            e.printStackTrace()                        }                    }                }            }).start()        } catch (Exception e) {            e.printStackTrace()        }    }

4. 录制成功后接下来的重点来了

使用

ffmpeg 对视频进行裁剪正方形, ffmpeg 使用Shell命令的方式进行视频操作, 执行效率也是非常好, 那首先你要集成FFmpeg

到Android 项目里面, 这里我下载好了一个library, 直接引入到项目即可, 感兴趣的伙伴可以自己编译一个库,

这里我把命令贴出来解释一下,

ffmpeg-threads4-y-i/storage/emulated/0/CustomCamera/temp/1476598263062.mp4-metadata:s:v rotate="0"-vftranspose=1, crop=width:height:x:y-presetultrafast-tunezerolatency-r25-vcodeclibx264-acodeccopy /storage/emulated/0/CustomCamera/VIDEO/1476598263062.mp4

1

1

-y: 如果文件存在那么覆盖掉

-i: 输入

metadata:s:v rotate=”0” : 重新编码 除去rotate, 因为默认录制出来的是横屏视频, 这里重新编码

transpose=1 :

0 = 90CounterCLockwise and Vertical Flip (default) 逆时针旋转90度并且垂直翻转, 下面类推

1 = 90Clockwise

2 = 90CounterClockwise

3 = 90Clockwise and Vertical Flip

crop=width:height:x:y,其中 width 和 height 表示裁剪后的尺寸,x:y 表示裁剪区域的左上角坐标

-preset ultrafast -tune zerolatency: 加快效率

r 25:帧率

-vcodec libx264 -acodec: 编码方式libx264

如果想知道更多关于ffmpeg的东西可以访问官网https://ffmpeg.org/

再贴一下我的代码调用:

try{                    fc.compress_clipVideo(file.getAbsolutePath(),                            file2.getAbsolutePath(), mCameraId, video_width, video_height,0,0,newShellUtils.ShellCallback() {                                @OverridepublicvoidshellOut(String shellLine) {                                }                                @OverridepublicvoidprocessComplete(intexitValue) {                                    dialog.dismiss();if(exitValue !=0) {                                        ToastFactory.showLongToast(context, getResources().getString(R.string.state_compress_error));                                        mHandler.sendEmptyMessage(R.string.state_compress_error);                                    }else{                                        mHandler.sendEmptyMessage(R.string.state_compress_end);                                    }                                }                            });                }catch(Exception e) {                    e.printStackTrace();                }

FFmpeg编译出来的Android 库还是很大的, 大约15M左右, 无疑增加了apk的大小, 如果你的产品方向是视频图片gif等等的格式转换类似的功能可以考虑使用

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容