Android 视频录制
来源:互联网 发布:手机单机版进销存软件 编辑:程序博客网 时间:2024/06/18 07:03
想到视频录制,肯定又是运用MediaRecorder,这个类实在是方便,但是好用的东西一定要慎重,毕竟没有那么便宜的事,但是基本满足用户要求,但是对于比较苛刻的项目而言,那就很尴尬了,比如:拍摄的视频不聚焦,拍摄像素低,甚至在有些手机上面根本无法进行拍摄录制,这就导致无法很好的使用了。不过我还是提供出工具类。希望高手能修改,并完美运行。
import android.annotation.SuppressLint;import android.app.AlertDialog;import android.app.ProgressDialog;import android.content.Context;import android.content.DialogInterface;import android.graphics.Bitmap;import android.graphics.PixelFormat;import android.hardware.Camera;import android.media.MediaRecorder;import android.media.MediaScannerConnection;import android.net.Uri;import android.os.Bundle;import android.os.Environment;import android.os.PowerManager;import android.os.SystemClock;import android.text.TextUtils;import android.util.Log;import android.view.SurfaceHolder;import android.view.View;import android.view.Window;import android.view.WindowManager;import android.widget.Button;import android.widget.Chronometer;import android.widget.ImageView;import android.widget.RelativeLayout;import android.widget.Toast;import android.widget.VideoView;import com.lvgou.distribution.R;import com.lvgou.distribution.utils.PathUtil;import com.lvgou.distribution.utils.Utils;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.util.Collections;import java.util.List;/** * Created by Administrator on 2017/6/14. */public class MyRecorderVideoActivity extends BaseActivity implements View.OnClickListener, SurfaceHolder.Callback, MediaRecorder.OnInfoListener, MediaRecorder.OnErrorListener { private static final String TAG = "RecorderVideoActivity"; private final static String CLASS_LABEL = "RecordActivity"; private PowerManager.WakeLock mWakeLock; private ImageView btnStart;//开始拍摄 private ImageView btnStop;//停止拍摄 private MediaRecorder mediaRecorder; private VideoView mVideoView;// 显示视频 String localPath = "";// 路径保存录像 private Camera mCamera; private int previewWidth = 480; private int previewHeight = 480; private Chronometer chronometer;//时间 private int frontCamera = 0; // 0是相机,1是前置摄像头 private Button btn_switch;//切换摄像头 Camera.Parameters cameraParameters = null; private SurfaceHolder mSurfaceHolder; int defaultVideoFrameRate = -1; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE);// 无标题 getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);// 全屏幕 // 半透明模式,用于表面的观点 getWindow().setFormat(PixelFormat.TRANSLUCENT); setContentView(R.layout.my_recorder_activity); PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, CLASS_LABEL); mWakeLock.acquire(); initViews(); } private RelativeLayout rl_back; // 初始化控件 private void initViews() { rl_back= (RelativeLayout) findViewById(R.id.rl_back); rl_back.setOnClickListener(this); btn_switch = (Button) findViewById(R.id.switch_btn);//切换摄像头 btn_switch.setOnClickListener(this); btn_switch.setVisibility(View.VISIBLE); mVideoView = (VideoView) findViewById(R.id.mVideoView);//视频控件显示视频 btnStart = (ImageView) findViewById(R.id.recorder_start);//开始拍摄 btnStop = (ImageView) findViewById(R.id.recorder_stop);//停止拍摄 btnStart.setOnClickListener(this); btnStop.setOnClickListener(this); mSurfaceHolder = mVideoView.getHolder(); mSurfaceHolder.addCallback(this); mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); chronometer = (Chronometer) findViewById(R.id.chronometer);//时间 } public void back(View view) { releaseRecorder(); releaseCamera(); finish(); } @Override protected void onResume() { super.onResume(); if (mWakeLock == null) { // 保持唤醒 PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, CLASS_LABEL); mWakeLock.acquire(); } } // 初始化照相机 @SuppressLint("NewApi") private boolean initCamera() { try { if (frontCamera == 0) { mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK); } else { mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT); } Camera.Parameters camParams = mCamera.getParameters(); mCamera.lock(); mSurfaceHolder = mVideoView.getHolder(); mSurfaceHolder.addCallback(this); mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); mCamera.setDisplayOrientation(90); } catch (RuntimeException ex) { return false; } return true; } private void handleSurfaceChanged() { if (mCamera == null) { finish(); return; } boolean hasSupportRate = false; ListsupportedPreviewFrameRates = mCamera.getParameters() .getSupportedPreviewFrameRates(); if (supportedPreviewFrameRates != null && supportedPreviewFrameRates.size() > 0) { Collections.sort(supportedPreviewFrameRates); for (int i = 0; i < supportedPreviewFrameRates.size(); i++) { int supportRate = supportedPreviewFrameRates.get(i); if (supportRate == 15) { hasSupportRate = true; } } if (hasSupportRate) { defaultVideoFrameRate = 15; } else { defaultVideoFrameRate = supportedPreviewFrameRates.get(0); } } // 得到所有相机提供的决议 List resolutionList = Utils.getResolutionList(mCamera); if (resolutionList != null && resolutionList.size() > 0) { Collections.sort(resolutionList, new Utils.ResolutionComparator()); Camera.Size previewSize = null; boolean hasSize = false; // 如果相机支持使用60 * 480 for (int i = 0; i < resolutionList.size(); i++) { Camera.Size size = resolutionList.get(i); if (size != null && size.width == 640 && size.height == 480) { previewSize = size; previewWidth = previewSize.width; previewHeight = previewSize.height; hasSize = true; break; } } // 使用中等分辨率如果相机不支持上述决议 if (!hasSize) { int mediumResolution = resolutionList.size() / 2; if (mediumResolution >= resolutionList.size()) mediumResolution = resolutionList.size() - 1; previewSize = resolutionList.get(mediumResolution); previewWidth = previewSize.width; previewHeight = previewSize.height; } } } @Override protected void onPause() { super.onPause(); if (mWakeLock != null) { mWakeLock.release(); mWakeLock = null; } } @Override public void onClick(View view) { int i = view.getId(); if (i == R.id.switch_btn) { //切换摄像头 switchCamera(); } else if (i == R.id.recorder_start) { // 开始录制 if (!startRecording()) return; Toast.makeText(this, R.string.The_video_to_start, Toast.LENGTH_SHORT).show(); btn_switch.setVisibility(View.INVISIBLE); btnStart.setVisibility(View.INVISIBLE); btnStart.setEnabled(false); btnStop.setVisibility(View.VISIBLE); chronometer.setBase(SystemClock.elapsedRealtime()); chronometer.start(); } else if (i == R.id.recorder_stop) { // 停止录制 btnStop.setEnabled(false); stopRecording(); btn_switch.setVisibility(View.VISIBLE); chronometer.stop(); btnStart.setVisibility(View.VISIBLE); btnStop.setVisibility(View.INVISIBLE); //弹出是否发送对话框 new AlertDialog.Builder(this) .setMessage("是否使用该视频!") .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); //发送视频 sendVideo(null); } }) .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (localPath != null) { File file = new File(localPath); if (file.exists()) file.delete(); } finish(); } }).setCancelable(false).show(); } else if (i==R.id.rl_back){ if (localPath != null) { File file = new File(localPath); if (file.exists()) file.delete(); } finish(); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { mSurfaceHolder = holder; } @Override public void surfaceCreated(SurfaceHolder holder) { if (mCamera == null) { if (!initCamera()) { showFailDialog(); return; } } try { mCamera.setPreviewDisplay(mSurfaceHolder); mCamera.startPreview(); handleSurfaceChanged(); } catch (Exception e1) { showFailDialog(); } } @Override public void surfaceDestroyed(SurfaceHolder arg0) { } public boolean startRecording() { if (mediaRecorder == null) { if (!initRecorder()) return false; } mediaRecorder.setOnInfoListener(this); mediaRecorder.setOnErrorListener(this); mediaRecorder.start(); return true; } public boolean isSdcardExist() { return android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED); } @SuppressLint("NewApi") private boolean initRecorder() { if (!isSdcardExist()) { showNoSDCardDialog(); return false; } if (mCamera == null) { if (!initCamera()) { showFailDialog(); return false; } } mVideoView.setVisibility(View.VISIBLE); mCamera.stopPreview(); mediaRecorder = new MediaRecorder(); mCamera.unlock(); mediaRecorder.setCamera(mCamera); mediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT); mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); if (frontCamera == 1) { mediaRecorder.setOrientationHint(270); } else { mediaRecorder.setOrientationHint(90); } mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); // 设置分辨率,应设置在格式和编码器// mediaRecorder.setVideoSize(previewWidth, previewHeight); mediaRecorder.setVideoEncodingBitRate(384 * 1024); // 设置帧率,应设置在格式和编码器 if (defaultVideoFrameRate != -1) { mediaRecorder.setVideoFrameRate(defaultVideoFrameRate); } // 设置视频文件的路径 localPath = PathUtil.getInstance().getVideoPath() + "/" + System.currentTimeMillis() + ".mp4"; mediaRecorder.setOutputFile(localPath); mediaRecorder.setMaxDuration(30000); mediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface()); Log.i("fdsafasdfsadfasd", "----------initRecorder-------" + localPath); try { mediaRecorder.prepare(); } catch (IllegalStateException e) { e.printStackTrace(); return false; } catch (IOException e) { e.printStackTrace(); return false; } return true; } // 停止录制 public void stopRecording() { if (mediaRecorder != null) { mediaRecorder.setOnErrorListener(null); mediaRecorder.setOnInfoListener(null); try { mediaRecorder.stop(); } catch (Exception e) { } } releaseRecorder(); if (mCamera != null) { mCamera.stopPreview(); releaseCamera(); } } private void releaseRecorder() { if (mediaRecorder != null) { mediaRecorder.release(); mediaRecorder = null; } } protected void releaseCamera() { try { if (mCamera != null) { mCamera.stopPreview(); mCamera.release(); mCamera = null; } } catch (Exception e) { } } // 切换摄像头 @SuppressLint("NewApi") public void switchCamera() { if (mCamera == null) { return; } if (Camera.getNumberOfCameras() >= 2) { btn_switch.setEnabled(false); if (mCamera != null) { mCamera.stopPreview(); mCamera.release(); mCamera = null; } switch (frontCamera) { case 0: mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT); frontCamera = 1; break; case 1: mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK); frontCamera = 0; break; } try { mCamera.lock(); mCamera.setDisplayOrientation(90); mCamera.setPreviewDisplay(mVideoView.getHolder()); mCamera.startPreview(); } catch (IOException e) { mCamera.release(); mCamera = null; } btn_switch.setEnabled(true); } } MediaScannerConnection msc = null; ProgressDialog progressDialog = null; public void sendVideo(View view) { if (TextUtils.isEmpty(localPath)) { return; } if (msc == null) msc = new MediaScannerConnection(this, new MediaScannerConnection.MediaScannerConnectionClient() { @Override public void onScanCompleted(String path, Uri uri) { msc.disconnect(); progressDialog.dismiss(); setResult(RESULT_OK, getIntent().putExtra("uri", uri)); finish(); /* String[] proj = {MediaStore.Images.Media.DATA}; Cursor actualimagecursor = managedQuery(uri, proj, null, null, null); int actual_image_column_index = actualimagecursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); actualimagecursor.moveToFirst(); String img_path = actualimagecursor.getString(actual_image_column_index); ArrayList file_list = new ArrayList<>(); File file = new File(img_path); file_list.add(file); Intent intent = new Intent(); intent.setClass(MyRecorderVideoActivity.this, MovieBuffAddVideoActivity.class); Bundle bundle = new Bundle(); bundle.putSerializable("file_list", file_list); bundle.putString("localPath", localPath); intent.putExtras(bundle); startActivity(intent); onBackPressed();*/ } @Override public void onMediaScannerConnected() { msc.scanFile(localPath, "video/*"); } }); if (progressDialog == null) { progressDialog = new ProgressDialog(this); progressDialog.setMessage("processing..."); progressDialog.setCancelable(false); } progressDialog.show(); msc.connect(); } @Override public void onInfo(MediaRecorder mr, int what, int extra) { if (what == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) { stopRecording(); btn_switch.setVisibility(View.VISIBLE); chronometer.stop(); btnStart.setVisibility(View.VISIBLE); btnStop.setVisibility(View.INVISIBLE); chronometer.stop(); if (localPath == null) { return; } String st3 = getResources().getString(R.string.Whether_to_send); new AlertDialog.Builder(this) .setMessage("是否使用该视频!") .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { arg0.dismiss(); sendVideo(null); } }).setNegativeButton(R.string.cancel, null) .setCancelable(false).show(); } } @Override public void onError(MediaRecorder mr, int what, int extra) { stopRecording(); Toast.makeText(this, "Recording error has occurred. Stopping the recording", Toast.LENGTH_SHORT).show(); } public void saveBitmapFile(Bitmap bitmap) { File file = new File(Environment.getExternalStorageDirectory(), "a.jpg"); try { BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos); bos.flush(); bos.close(); } catch (IOException e) { e.printStackTrace(); } } @Override protected void onDestroy() { super.onDestroy(); releaseCamera(); if (mWakeLock != null) { mWakeLock.release(); mWakeLock = null; } } @Override public void onBackPressed() { back(null); } private void showFailDialog() { new AlertDialog.Builder(this) .setTitle(R.string.prompt) .setMessage(R.string.Open_the_equipment_failure) .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); } }).setCancelable(false).show(); } private void showNoSDCardDialog() { new AlertDialog.Builder(this) .setTitle(R.string.prompt) .setMessage("No sd card!") .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { finish(); } }).setCancelable(false).show(); }}
为此我也在网上找了一些资料,不过大部分demo的原理也是MediaRecorder。但是我看到了我拍摄照片的方式,就调用系统自带的摄像头,然后进行拍摄,获取路径就可以了。因此我就想到了拍摄视频如果使用系统自带的录制那就很好的能解决兼容性问题了。唯一不好的就是拍摄界面无法自己定义,各自手机自带的是什么样子的拍摄就保留怎样的拍摄。其实很简单:
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
//设置视频大小
intent.putExtra(android.provider.MediaStore.EXTRA_SIZE_LIMIT, 768000);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0);
//设置视频时间
intent.putExtra(android.provider.MediaStore.EXTRA_DURATION_LIMIT, 10);
startActivityForResult(intent, REQUEST_CODE_MAP);
然后就是接收了:
Uri uri = data.getData();
// Uri uri = data.getParcelableExtra("uri");
String[] projects = new String[]{MediaStore.Video.Media.DATA,
MediaStore.Video.Media.DURATION};
Cursor cursor = getContentResolver().query(uri,projects, null, null, null);
int duration = 0;
String copyfilepaths="";
String filePath = null;
if (cursor.moveToFirst()) {
// 路径:MediaStore.Audio.Media.DATA
filePath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DATA));
try {
copyfilepaths=PathUtil.getInstance().getVideoPath() + "/" + System.currentTimeMillis() + ".mp4";
copyFileTo(new File(filePath),new File(copyfilepaths));
} catch (IOException e) {
e.printStackTrace();
}
// 总播放时长:MediaStore.Audio.Media.DURATION
duration = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION));
}
if (cursor != null) {
cursor.close();
cursor = null;
}
File file = new File(PathUtil.getInstance().getImagePath(), "thvideo" + System.currentTimeMillis());
FileOutputStream fos = new FileOutputStream(file);
Bitmap ThumbBitmap = ThumbnailUtils.createVideoThumbnail(filePath, 5);
ThumbBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.close();
值得一提的是:必须要将保存下来的文件copy一次
因为在某些手机使用中,上传文件到服务器是不允许被上传的,然后就导致服务器那边就收不到文件,所以我写了一个方法来转换文件,其实也就是复制文件。
boolean copyFileTo(File srcFile, File destFile) throws IOException { if (srcFile.isDirectory() || destFile.isDirectory()) return false;//判断是否是文件 FileInputStream fis = new FileInputStream(srcFile); FileOutputStream fos = new FileOutputStream(destFile); int readLen = 0; byte[] buf = new byte[1024]; while ((readLen = fis.read(buf)) != -1) { fos.write(buf, 0, readLen); } fos.flush(); fos.close(); fis.close(); return true; }
- android视频录制(调用系统视频录制)
- Android 视频录制
- android视频录制
- android 音视频录制
- android视频录制例子
- Android录制视频(五)
- Android录制视频(四)
- Android录制视频(三)
- Android录制视频(二)
- Android录制视频(一)
- Android视频录制
- VLC Android录制视频
- android-音视频录制
- Android MediaRecord视频录制
- android 后台视频录制
- android自定义视频录制
- Android 录制视频
- 120001 Android视频录制
- Ardupilot -- APM源码笔记二(重制)~ Ardupilot 链接库引导
- 389. Find the Difference
- RecyclerView+CheckBox实现列表数据选择操作
- servlet生命周期
- [LeetCode]552. Student Attendance Record II
- Android 视频录制
- JDBC 远程 SQLSERVER 速度很慢的处理方式
- input输入框禁止显示历史记录
- java实现在线预览----poi操作word转html及03、07版本兼容问题
- You-Get——基于Python3的媒体下载工具
- cent7配置nginx(二),nginx负载均衡的5种策略
- mysql提示Packet for query is too large (1142 > 1024)解决方案
- 均值、方差、协方差、协方差矩阵、特征值、特征向量
- php namespace的使用方法