一·视频录制界面 SurfaceView 的使用



SurfaceView我们可以把它当作一个容器,它放在所有窗口的下面·提供了一个可见区域,通过SurfaceHolder接口访问这个surface,getHolder()方法可以得到这个接口,它相当于SurfaceView 的控制器 然后通过调用addCallback();方法就可以进入它的生命周期开始使用




二·Camera的使用



1.在 Android Manifest.xml 中声明相机权限


2. 打开相机设备


3. 配置相机参数


4. 设置相机预览方向


5. ~~使用


6. 释放相机设备



三·视频录制控件MediaRecorder的使用


 对MediaRecorder的总结(干货)





Android vlc 录制视频 androidsurfaceview录制_android





权限


< uses-permission android :name= "android.permission.CAMERA" />


< uses-permission android :name= "android.permission.RECORD_AUDIO" />


< uses-permission android :name= "android.permission.WRITE_EXTERNAL_STORAGE" />



1:设置SurfaceView:



SurfaceView surfaceView = (SurfaceView) findViewById(R.id.record_surfaceView);


拿到SurfaceView的控制器



mSurfaceHolder = surfaceView.getHolder();



设置类型


mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);



四种SurfaceView的类型


SURFACE_TYPE_NORMAL:用RAM缓存原生数据的普通Surface


SURFACE_TYPE_HARDWARE:适用于DMA(Direct memory access )引擎和硬件加速的Surface


SURFACE_TYPE_GPU:适用于GPU加速的Surface


SURFACE_TYPE_PUSH_BUFFERS:表明该Surface不包含原生数据,Surface用到的数据由其他对象提供,在Camera图像预览中就使用该类型的Surface,有Camera负责提供给预览Surface数据,这样图像预览会比较流畅。如果设置这种类型则就不能调用lockCanvas来获取Canvas对象了。



设置分辨率


mSurfaceHolder.setFixedSize(320, 280);



设置该组件不会让屏幕自动关闭


mSurfaceHolder.setKeepScreenOn(true);



实现CallBack初始化SurfaceHolder进入生命周期


mSurfaceHolder.addCallback(mCallBack);



private SurfaceHolder.Callback mCallBack = new SurfaceHolder.Callback() {


@Override


public void surfaceCreated(SurfaceHolder surfaceHolder) {


初始化相机


initCamera();


}



@Override


public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {


if (mSurfaceHolder.getSurface() == null) {


return;


}


}



@Override


public void surfaceDestroyed(SurfaceHolder surfaceHolder) {


关闭相机


stopCamera();


}


};



2·初始化相机并且配置


private void initCamera() {


if (mCamera != null) {


stopCamera();


}


//默认启动后置摄像头


mCamera = Camera.open(Camera.CameraInfo.CAMERA_FACING_BACK);


if (mCamera == null) {


Toast.makeText(this, "未能获取到相机!", Toast.LENGTH_SHORT).show();


return;


}


try {


//显示映视


mCamera.setPreviewDisplay(mSurfaceHolder);


//配置CameraParams



if (mCamera != null) {


Camera.Parameters params = mCamera.getParameters();


//设置相机的横竖屏幕


if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {


//竖屏


params.set("orientation", "portrait");


mCamera.setDisplayOrientation(90);


} else {


//横屏


params.set("orientation", "landscape");


mCamera.setDisplayOrientation(0);


}


//设置聚焦模式


params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);


//缩短Recording启动时间


params.setRecordingHint(true);


//是否支持影像稳定能力,支持则开启


if (params.isVideoStabilizationSupported())


params.setVideoStabilization(true);


mCamera.setParameters(params);


}



//启动相机预览


mCamera.startPreview();


} catch (IOException e) {


Log.d("TAG", "Error starting camera preview: " + e.getMessage());


}


}




设置停止相机工作方法


private void stopCamera() {


if (mCamera != null) {


mCamera.setPreviewCallback(null);


mCamera.stopPreview();


mCamera.release();


mCamera = null;


}


}



基本都是固定的套路



接下来给开始和停止按钮设置点击事件


开始调用star();


停止调用stop();



private void Start() {


判断路径File对象是否创建成功或者有此路径


boolean creakOk = createRecordDir();


if (!creakOk) {


return;


}


初始化相机


initCamera();


设置录像前需要将相机解锁 (非常重要)


mCamera.unlock();


MediaRecorder


setConfigRecord();


try {


//开始录制


mediaRecorder.prepare();


mediaRecorder.start();


} catch (IOException e) {


e.printStackTrace();


}


把是否正在录制的状态改变


isRecording = true;


}



private void setConfigRecord() {


mediaRecorder = new MediaRecorder(); 创建


mediaRecorder.reset(); 设置为空闲模式 可以赋属性了


mediaRecorder.setCamera(mCamera); 设置一个摄像头用于录制。


mediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {


@Override


public void onError(MediaRecorder mr, int what, int extra) {


try {


if (mediaRecorder != null) {


mediaRecorder.reset();


}


} catch (Exception e) {


e.printStackTrace();


}


}


});


记录录制时出现的错误的监听器,调用reset();方法设置为空闲模式



//使用SurfaceView预览


mediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());



//1.设置采集声音


mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);


//设置采集图像


mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);


//2.设置视频,音频的输出格式 mp4


mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);


//3.设置音频的编码格式


mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);


//设置图像的编码格式


mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);


//音频一秒钟包含多少数据位


CamcorderProfile mProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_480P);


mediaRecorder.setAudioEncodingBitRate(44100);


if (mProfile.videoBitRate > 2 * 1024 * 1024)


mediaRecorder.setVideoEncodingBitRate(2 * 1024 * 1024);


else


mediaRecorder.setVideoEncodingBitRate(1024 * 1024);


mediaRecorder.setVideoFrameRate(mProfile.videoFrameRate);



//设置选择角度,顺时针方向,因为默认是逆向90度的,这样图像就是正常显示了,这里设置的是观看保存后的视频的角度


mediaRecorder.setOrientationHint(90);


//设置录像的分辨率


mediaRecorder.setVideoSize(352, 288);


储存


mediaRecorder.setOutputFile(mVecordFile.getAbsolutePath());


}



判断路径File对象是否创建成功或者有此路径返回Boolean值


private boolean createRecordDir() {


if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {


Toast.makeText(this, "请查看您的SD卡是否存在!", Toast.LENGTH_SHORT).show();


return false;


}



File targetDir = Environment.


getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);


if (!targetDir.exists()) {


targetDir.mkdirs();


}


mVecordFile = new File(targetDir,


SystemClock.currentThreadTimeMillis() + ".mp4");



return true;


}




private void stop() {


if (isRecording && mediaRecorder != null) {


将监听还有预览设置为空避免崩溃


mediaRecorder.setOnErrorListener(null);


mediaRecorder.setPreviewDisplay(null);


//停止录制


mediaRecorder.stop();


mediaRecorder.reset();


//释放资源


mediaRecorder.release();


mediaRecorder = null;



isRecording = false;


}


吐司一下视屏存放位置


Toast.makeText(this, ""+mVecordFile.getAbsolutePath(), Toast.LENGTH_LONG).show();


}