轉載:裁剪正方形視頻

轉自: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() +""http://視頻存儲路徑? ? ? ? ? ? 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等等的格式轉換類似的功能可以考慮使用

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容