日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android 视频录制工具类VideoRecordUtil

發(fā)布時(shí)間:2023/12/20 Android 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android 视频录制工具类VideoRecordUtil 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一 錄制視頻工具類

import android.content.Context; import android.graphics.Bitmap; import android.hardware.Camera; import android.media.CamcorderProfile; import android.media.MediaMetadataRetriever; import android.media.MediaRecorder; import android.os.Environment; import android.os.StatFs; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.widget.Toast;import java.io.File; import java.io.IOException; import java.text.DecimalFormat; import java.util.HashMap; import java.util.Timer; import java.util.TimerTask;import mwteck.ettda.Utils.AppToast;/*** CreateTime 2017/10/16 15:00* Author LiuShiHua* Description:錄制視頻* <p>* 1.在Activity的oncreate方法中初始化* 2.在onstart中調(diào)用RecordVideoUtil的startPreview方法生成預(yù)覽界面* 3.在onstop中調(diào)用RecordVideoUtil的stopRecord和stotPreview方法終止錄制、預(yù)覽界面* <p>* duration 默認(rèn)錄制時(shí)間*/public class RecordVideoUtil {/*** 默認(rèn)錄制時(shí)間是30秒*/private int duration = 30;private SurfaceHolder mSurfaceHolder;private Context context;private boolean mIsSufaceCreated = false;private Camera mCamera;private final static int CAMERA_ID = 0;private boolean isRecording = false;private final String TAG = "------------>錄像";private MediaRecorder mRecorder;private long start, end;private String savePath;private static int cameraPosition = 1;//0代表前置攝像頭,1代表后置攝像頭private boolean isView = true;private boolean highQuality = false;//是否錄制高質(zhì)量音頻public RecordVideoUtil(Context context, SurfaceView mCameraPreview) {this.context = context;mSurfaceHolder = mCameraPreview.getHolder();mSurfaceHolder.addCallback(mSurfaceCallback);mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);}private SurfaceHolder.Callback mSurfaceCallback = new SurfaceHolder.Callback() {@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {mIsSufaceCreated = false;}@Overridepublic void surfaceCreated(SurfaceHolder holder) {mIsSufaceCreated = true;}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {startPreview();}};//啟動(dòng)預(yù)覽public boolean startPreview() {//保證只有一個(gè)Camera對象if (mCamera != null || !mIsSufaceCreated) {Log.d(TAG, "startPreview will return");return true;}try {mCamera = Camera.open(CAMERA_ID);} catch (Exception e) {//未授權(quán)相機(jī)權(quán)限,這里會(huì)拋出異常AppToast.makeToast("打開相機(jī)失敗");e.printStackTrace();return false;}Camera.Parameters parameters = mCamera.getParameters(); // Camera.Size size = getBestPreviewSize(, CameraUtils.PREVIEW_HEIGHT, parameters); // if (size != null) { // parameters.setPreviewSize(size.width, size.height); // }parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);parameters.setPreviewFrameRate(20);//設(shè)置相機(jī)預(yù)覽方向mCamera.setDisplayOrientation(90);mCamera.setParameters(parameters);try {mCamera.setPreviewDisplay(mSurfaceHolder);} catch (Exception e) {Log.d(TAG, e.getMessage());}mCamera.startPreview();return true;}//打開閃光燈public boolean openLight() {if (cameraPosition == 0) {return false;}return RecordVideoHelper.openFlashlight(mCamera, context);}//關(guān)閉閃光燈public boolean closeLight() {return RecordVideoHelper.closeFlashlight(mCamera);}/*** 外部調(diào)用** @param savePath 存儲(chǔ)路徑* @return 開始是否成功*/public boolean startRecord(String savePath) {this.savePath = savePath;if (isRecording) {return false;}if (!hasSdcard()) {Toast.makeText(context, "請先插入SD卡(存儲(chǔ)卡)", Toast.LENGTH_SHORT).show();return false;}if (!isSDCanUseSize50M()) {Toast.makeText(context, "內(nèi)存已經(jīng)不足50M了,請先清理手機(jī)空間", Toast.LENGTH_SHORT).show();}File file = new File(savePath);if (!file.exists()) {file.getParentFile().mkdirs();try {file.createNewFile();} catch (IOException e) {e.printStackTrace();Toast.makeText(context, "文件創(chuàng)建失敗", Toast.LENGTH_SHORT).show();return false;}}if (mRecorder != null) {mRecorder.stop();mRecorder.release();mRecorder = null;}mRecorder = new MediaRecorder();//實(shí)例化mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());//預(yù)覽mCamera.unlock();setMeadiaRecorder(mRecorder, file.getPath());try {mRecorder.prepare();mRecorder.start();isRecording = true;start = System.currentTimeMillis();} catch (Exception e) {e.printStackTrace();if (mCamera != null) {mCamera.lock();}isRecording = false;mRecorder.release();return false;}return true;}/*** 停止錄制** @return*/public boolean stopRecord() {end = System.currentTimeMillis();Log.d("---------->", "停止錄制");if (!isRecording || mRecorder == null) {return false;}try {mRecorder.stop();} catch (Exception e) {mRecorder = null;mRecorder = new MediaRecorder();}mRecorder.release();mRecorder = null;if (mCamera != null) {mCamera.lock();}isRecording = false;//重啟預(yù)覽if (!startPreview())return false;if (((double) (end - start) / 1000) < 1) {if (savePath != null && new File(savePath).exists()) {new File(savePath).delete();}}return true;}/*** 在activity中的onPause中調(diào)用* <p>* 釋放Camera對象*/public void stopPreview() {if (mCamera != null) {try {mCamera.setPreviewDisplay(null);} catch (Exception e) {Log.d(TAG, e.getMessage());}mCamera.stopPreview();mCamera.release();mCamera = null;isView = false;}}/*** 設(shè)置參數(shù)* ** @param mRecorder* @param filePath 1,花屏主要跟VideoSize有關(guān),將Size調(diào)到640*480以上花屏問題可解決,或者錄制屏幕為正方形。* 2,清晰度和錄制文件大小主要和EncodingBitRate有關(guān),參數(shù)越大越清晰,同時(shí)錄制的文件也越大。* 3,視頻文件的流暢度主要跟VideoFrameRate有關(guān),參數(shù)越大視頻畫面越流暢,但實(shí)際中跟你的攝像頭質(zhì)量有很大關(guān)系。*/private void setMeadiaRecorder(MediaRecorder mRecorder, String filePath) {mRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {@Overridepublic void onError(MediaRecorder mediaRecorder, int i, int i1) {Log.d("-------->", "MediaRecorder.onError");}});mRecorder.setCamera(mCamera); //給Recorder設(shè)置Camera對象,保證錄像跟預(yù)覽的方向保持一致if (cameraPosition == 1) {mRecorder.setOrientationHint(90); //改變保存后的視頻文件播放時(shí)是否橫屏(不加這句,視頻文件播放的時(shí)候角度是反的)} else {mRecorder.setOrientationHint(270); //改變保存后的視頻文件播放時(shí)是否橫屏(不加這句,視頻文件播放的時(shí)候角度是反的)}mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // 設(shè)置從攝像頭采集圖像mRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT); // 設(shè)置從麥克風(fēng)采集聲音CamcorderProfile mProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);// 設(shè)置視頻的輸出格式 為MP4 // mRecorder.setOutputFormat(mProfile.fileFormat);mRecorder.setAudioEncoder(mProfile.audioCodec);// 設(shè)置音頻的編碼格式 // mRecorder.setVideoEncoder(mProfile.videoCodec);mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);// 設(shè)置視頻的編碼格式mRecorder.setOutputFile(filePath); // mRecorder.setVideoSize(mProfile.videoFrameWidth, mProfile.videoFrameHeight);mRecorder.setVideoSize(640, 480);//設(shè)置錄制的視頻幀率,必須放在設(shè)置編碼和格式的后面,否則報(bào)錯(cuò)mRecorder.setVideoFrameRate(mProfile.videoFrameRate);mRecorder.setVideoEncodingBitRate(800 * 1024);//視頻碼率mRecorder.setAudioEncodingBitRate(mProfile.audioBitRate); // mRecorder.setAudioChannels(mProfile.audioChannels);mRecorder.setAudioChannels(1);//設(shè)置錄制的音頻通道數(shù) // mRecorder.setAudioSamplingRate(mProfile.audioSampleRate);mRecorder.setAudioSamplingRate(44100); // mRecorder.setMaxDuration(duration * 1000); //設(shè)置最大錄像時(shí)間為10s}/*** 檢查設(shè)備是否存在SDCard的工具方法*/public static boolean hasSdcard() {String state = Environment.getExternalStorageState();if (state.equals(Environment.MEDIA_MOUNTED)) {// 有存儲(chǔ)的SDCardreturn true;} else {return false;}}/*** 獲得sd卡剩余容量是否有50M,即可用大小** @return*/public static boolean isSDCanUseSize50M() {if (!hasSdcard()) {return false;}File path = Environment.getExternalStorageDirectory();StatFs sf = new StatFs(path.getPath());long size = sf.getBlockSize();//SD卡的單位大小long available = sf.getAvailableBlocks();//可使用的數(shù)量DecimalFormat df = new DecimalFormat();df.setGroupingSize(3);//每3位分為一組if (size * available / 1024 / 1024 < 50) {return false;}return true;}/*** 切換前置/后置攝像頭*/public void changeUseCamera() {if (mCamera == null || mSurfaceHolder == null) return;//切換前后攝像頭if (!isCanChange) return;int cameraCount = 0;Camera.CameraInfo cameraInfo = new Camera.CameraInfo();cameraCount = Camera.getNumberOfCameras();//得到攝像頭的個(gè)數(shù)for (int i = 0; i < cameraCount; i++) {Camera.getCameraInfo(i, cameraInfo);//得到每一個(gè)攝像頭的信息if (cameraPosition == 1) {//現(xiàn)在是后置,變更為前置if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {//代表攝像頭的方位,CAMERA_FACING_FRONT前置 CAMERA_FACING_BACK后置stopPreview();mCamera = Camera.open(i);//打開當(dāng)前選中的攝像頭try {mCamera.setPreviewDisplay(mSurfaceHolder);//通過surfaceview顯示取景畫面} catch (IOException e) {e.printStackTrace();}if (mCamera != null && !isView) {try {mCamera.startPreview();//開始預(yù)覽mCamera.setDisplayOrientation(90);Camera.Parameters parameters = mCamera.getParameters();parameters.setPreviewFrameRate(5);//設(shè)置旋轉(zhuǎn)代碼parameters.setRotation(90);cameraPosition = 0;changeCameraTimer();} catch (Exception e) {e.printStackTrace();}}break;}} else {//現(xiàn)在是前置, 變更為后置if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {//代表攝像頭的方位,CAMERA_FACING_FRONT前置 CAMERA_FACING_BACK后置stopPreview();mCamera = Camera.open(i);//打開當(dāng)前選中的攝像頭try {mCamera.setPreviewDisplay(mSurfaceHolder);//通過surfaceview顯示取景畫面} catch (IOException e) {e.printStackTrace();}if (mCamera != null && !isView) {try {mCamera.startPreview();//開始預(yù)覽mCamera.setDisplayOrientation(90);Camera.Parameters parameters = mCamera.getParameters();parameters.setPreviewFrameRate(5);//設(shè)置旋轉(zhuǎn)代碼parameters.setRotation(90);mCamera.setParameters(parameters);cameraPosition = 1;changeCameraTimer();} catch (Exception e) {e.printStackTrace();}}break;}}}}private boolean isCanChange = true;private void changeCameraTimer() {isCanChange = false;new Timer().schedule(new TimerTask() {@Overridepublic void run() {isCanChange = true;}}, 600);}/*** 獲取本地視頻的第一幀** @param filePath* @return*/public static Bitmap getVideoFirstFrame(String filePath) {MediaMetadataRetriever mmr = new MediaMetadataRetriever();//實(shí)例化MediaMetadataRetriever對象File file = new File(filePath);//實(shí)例化File對象,文件路徑為/storage/sdcard/Movies/music1.mp4if (file.exists()) {mmr.setDataSource(file.getAbsolutePath());//設(shè)置數(shù)據(jù)源為該文件對象指定的絕對路徑Bitmap bitmap = mmr.getFrameAtTime();//獲得視頻第一幀的Bitmap對象return bitmap;}return null;}/*** 獲取網(wǎng)絡(luò)視頻的第一幀** @param videoUrl* @return*/public static Bitmap getVideoFirstFrame_Net(String videoUrl) {Bitmap bitmap = null;MediaMetadataRetriever retriever = new MediaMetadataRetriever();try {//根據(jù)url獲取縮略圖retriever.setDataSource(videoUrl, new HashMap());//獲得第一幀圖片bitmap = retriever.getFrameAtTime();} catch (Exception e) {e.printStackTrace();} finally {retriever.release();}return bitmap;}// 需要將以下方法放在調(diào)用此工具類的Activity/fragment中——解決暫停后無法錄制的問題 // @Override // protected void onStart() { // super.onStart(); // if (videoUtil == null) return; // videoUtil.startPreview(); // } // // @Override // protected void onPause() { // super.onPause(); // if (videoUtil == null) return; // if (isRecordVideo) { // videoUtil.stopRecord(); // } // videoUtil.stopPreview(); // isRecordVideo = false; // } }

二 幫助類

import android.content.Context; import android.content.pm.PackageManager; import android.hardware.Camera; import android.util.Log;import java.util.Collection;/*** CreateTime 2017/12/4 13:59* Author LiuShiHua* Description:打開和關(guān)閉閃光燈*/// <uses-permission android:name="android.permission.FLASHLIGHT" /> // <uses-permission android:name="android.permission.CAMERA"/> // <uses-feature android:name="android.hardware.camera" /> // <uses-feature android:name="android.hardware.autofocus"/>public class RecordVideoHelper {private static boolean isCanUse = false;private static boolean isOpenFrontCamera = false;//打開閃光燈public static boolean openFlashlight(Camera camera, Context context) {if (isCanUseLight(context, camera)) {isCanUse = true;doSetTorch(camera, true);return true;} else {Log.d("------------->", "手機(jī)不支持打開閃光燈");return false;}}//關(guān)閉閃光燈public static boolean closeFlashlight(Camera camera) {if (isCanUse) {doSetTorch(camera, false);}return isCanUse;}//是否可以使用閃光燈private static boolean isCanUseLight(Context context, Camera camera) {return camera != null && context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);}private static void doSetTorch(Camera camera, boolean newSetting) {Camera.Parameters parameters = camera.getParameters();String flashMode;/** 是否支持閃光燈 */if (newSetting) {flashMode = findSettableValue(parameters.getSupportedFlashModes(), Camera.Parameters.FLASH_MODE_TORCH, Camera.Parameters.FLASH_MODE_ON);} else {flashMode = findSettableValue(parameters.getSupportedFlashModes(), Camera.Parameters.FLASH_MODE_OFF);}if (flashMode != null) {parameters.setFlashMode(flashMode);}camera.setParameters(parameters);}private static String findSettableValue(Collection<String> supportedValues, String... desiredValues) {String result = null;if (supportedValues != null) {for (String desiredValue : desiredValues) {if (supportedValues.contains(desiredValue)) {result = desiredValue;break;}}}return result;} }

總結(jié)

以上是生活随笔為你收集整理的Android 视频录制工具类VideoRecordUtil的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。