編輯:關於Android編程
到目前為止 Android 中還不能直接錄制正方形的視頻, 雖然不能直接錄但是我們也有一些方式來處理錄制後的視頻, 之前我寫過一篇文章 Android 自定義Camera(一), 可以先了解一下如何做一個簡單的自定義相機demo, 那錄制視頻也要開啟相機預覽, 有以下幾個步驟和需要注意的地方:
1. 獲取相機實例
/** * 獲取Camera實例 * * @return */ private Camera getCamera(int id) { Camera camera = null; try { camera = Camera.open(id); } catch (Exception e) { } return camera; }
2. 開啟預覽
要注意, 開啟預覽要在 Activity 的 onResume 方法裡面開啟, 然後在 onPause 方法裡面釋放相機資源, 舉一個簡單的例子, 如果你在預覽的時候按下了home鍵, 此時再次打開程序, 如果你是在 Oncreate 方法裡面開啟相機, 那麼再次打開預覽界面應該會卡住。
/** * 預覽相機 */ private void startPreview(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(); } } /** * 設置 */ private void setupCamera(Camera camera) { if (camera != null) { Camera.Parameters parameters = camera.getParameters(); ListfocusModes = 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) { //拿到一個預覽寬度最小為720像素的預覽值 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); } //這裡第三個參數為最小尺寸 getPropPreviewSize方法會對從最小尺寸開始升序排列 取出所有支持尺寸的最小尺寸 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 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_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.AAC; profile.audioChannels = 1; profile.audioSampleRate = 16000; profile.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 = 0; i < PROGRESS_MAX; i++) { try { Thread.currentThread().sleep(20); Message message = new Message(); message.what = 1; message.obj = i; handler.sendMessage(message); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } catch (Exception e) { e.printStackTrace(); } }4. 錄制成功後接下來的重點來了
使用 ffmpeg 對視頻進行裁剪正方形, ffmpeg 使用Shell命令的方式進行視頻操作, 執行效率也是非常好, 那首先你要集成FFmpeg 到Android 項目裡面, 這裡我下載好了一個library, 直接引入到項目即可, 感興趣的伙伴可以自己編譯一個庫, 這裡我把命令貼出來解釋一下,
ffmpeg -threads 4 -y -i /storage/emulated/0/CustomCamera/temp/1476598263062.mp4 -metadata:s:v rotate="0" -vf transpose=1, crop=width:height:x:y -preset ultrafast -tune zerolatency -r 25 -vcodec libx264 -acodec copy /storage/emulated/0/CustomCamera/VIDEO/1476598263062.mp4-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 Flipcrop=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, new ShellUtils.ShellCallback() { @Override public void shellOut(String shellLine) { } @Override public void processComplete(int exitValue) { 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等等的格式轉換類似的功能可以考慮使用
如果你對這樣的功能感興趣可以詳細查看源碼:
github 地址
https://github.com/jinguangyue/Android-CustomCamera
前提:手機已經root; 1.手機連接電腦,打開Cmd,運行命令adb shell;//因為android用的Linux內核,很多linux的命令,在Android也可以
手機百度浏覽器怎麼清除地址欄輸入歷史教程。我們在使用手機百度浏覽器的時候,之前輸入很多地址。都被保存下來。可我想清除這手機百度浏覽器的地址欄輸入歷史,不想它
Spinner控件是一個下拉列表 1.實現Spinner的系統默認設置 2.實現自定義設置: 3.使用的監聽器接口是:OnItemSelectedListener系統默認
1.初識ViewRoot和DecorViewViewRoot對應於ViewRootImpl類,它是連接WindowManager和DecorView的紐帶,View的三大