android视频录制
layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<SurfaceView
android:id="@+id/record_surfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#80ffffff"
android:padding="10dp">
<!-- 开始/结束 录制按钮 -->
<ImageView
android:id="@+id/record_control"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerInParent="true"
android:onClick="startRecord"
android:src="@drawable/recordvideo_start" />
<Chronometer
android:id="@+id/record_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:format="%s" />
</RelativeLayout>
</RelativeLayout>
代码:
package com.example.apple.demo.CameraPreview;
import com.example.apple.demo.R;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.os.Environment;
import android.os.Handler;
import android.os.SystemClock;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Chronometer;
import android.widget.Toast;
import android.content.Context;
import android.content.res.Configuration;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import java.io.File;
import java.io.IOException;
public class CustomRecordActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "CustomRecordActivity";
//UI
private ImageView mRecordControl;
private SurfaceView surfaceView;
private SurfaceHolder mSurfaceHolder;
private Chronometer mRecordTime;
//DATA
//录像机状态标识
private int mRecorderState;
public static final int STATE_INIT = 0; //开始录制
public static final int STATE_RECORDING = 1;//结束录制
// 存储文件
private File mVecordFile;
private Camera mCamera;
private MediaRecorder mediaRecorder;
private String currentVideoFilePath;
private String saveVideoPath = "";
private MediaRecorder.OnErrorListener OnErrorListener = new MediaRecorder.OnErrorListener() {
@Override
public void onError(MediaRecorder mediaRecorder, int what, int extra) {
try {
if (mediaRecorder != null) {
mediaRecorder.reset();
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
private void initView() {
surfaceView = (SurfaceView) findViewById(R.id.record_surfaceView);
mRecordControl = (ImageView) findViewById(R.id.record_control);
mRecordTime = (Chronometer) findViewById(R.id.record_time);
mRecordControl.setOnClickListener(this);
//配置SurfaceHolder
mSurfaceHolder = surfaceView.getHolder();
// 设置Surface不需要维护自己的缓冲区
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// 设置分辨率
mSurfaceHolder.setFixedSize(320, 280);
// 设置该组件不会让屏幕自动关闭
mSurfaceHolder.setKeepScreenOn(true);
//回调接口
mSurfaceHolder.addCallback(mSurfaceCallBack);
}
private SurfaceHolder.Callback mSurfaceCallBack = 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) {
releaseCamera();
}
};
/**
* 初始化摄像头
*
* @throws IOException
* @author liuzhongjun
*/
private void initCamera() {
if (mCamera != null) {
releaseCamera();
}
mCamera = Camera.open();
if (mCamera == null) {
Toast.makeText(this, "未能获取到相机!", Toast.LENGTH_SHORT).show();
return;
}
try {
//将相机与SurfaceHolder绑定
mCamera.setPreviewDisplay(mSurfaceHolder);
//配置CameraParams
configCameraParams();
//启动相机预览
mCamera.startPreview();
} catch (IOException e) {
//有的手机会因为兼容问题报错,这就需要开发者针对特定机型去做适配了
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
/**
* 设置摄像头为竖屏
*
* @author lip
* @date 2015-3-16
*/
private void configCameraParams() {
Camera.Parameters params = mCamera.getParameters();
//设置相机的横竖屏(竖屏需要旋转90°)
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);
}
/**
* 释放摄像头资源
*
* @date 2016-2-5
*/
private void releaseCamera() {
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}
/**
* 开始录制视频
*/
public boolean startRecord() {
initCamera();
//录制视频前必须先解锁Camera
mCamera.unlock();
configMediaRecorder();
try {
//开始录制
mediaRecorder.prepare();
mediaRecorder.start();
} catch (IOException e) {
return false;
}
return true;
}
/**
* 停止录制视频
*/
public void stopRecord() {
// 设置后不会崩
mediaRecorder.setOnErrorListener(null);
mediaRecorder.setPreviewDisplay(null);
//停止录制
mediaRecorder.stop();
mediaRecorder.reset();
//释放资源
mediaRecorder.release();
mediaRecorder = null;
}
/**
* 点击中间按钮,执行的UI更新操作
*/
private void refreshControlUI() {
if (mRecorderState == STATE_INIT) {
//录像时间计时
mRecordTime.setBase(SystemClock.elapsedRealtime());
mRecordTime.start();
mRecordControl.setImageResource(R.drawable.recordvideo_stop);
//1s后才能按停止录制按钮
mRecordControl.setEnabled(false);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mRecordControl.setEnabled(true);
}
}, 1000);
} else if (mRecorderState == STATE_RECORDING) {
mRecordTime.stop();
mRecordControl.setImageResource(R.drawable.recordvideo_start);
}
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.record_control: {
if (mRecorderState == STATE_INIT) {
if (getSDPath(getApplicationContext()) == null)
return;
//视频文件保存路径,configMediaRecorder方法中会设置
currentVideoFilePath = getSDPath(getApplicationContext()) + getVideoName();
//开始录制视频
if (!startRecord())
return;
refreshControlUI();
mRecorderState = STATE_RECORDING;
} else if (mRecorderState == STATE_RECORDING) {
//停止视频录制
stopRecord();
//先给Camera加锁后再释放相机
mCamera.lock();
releaseCamera();
refreshControlUI();
//判断是否进行视频合并
if ("".equals(saveVideoPath)) {
saveVideoPath = currentVideoFilePath;
}
mRecorderState = STATE_INIT;
//延迟一秒跳转到播放器,(确保视频合并完成后跳转) TODO 具体的逻辑可根据自己的使用场景跳转
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), "录制成功", Toast.LENGTH_SHORT).show();
onBackPressed();
}
}, 1000);
}
break;
}
}
}
/**
* 配置MediaRecorder()
*/
private void configMediaRecorder() {
mediaRecorder = new MediaRecorder();
mediaRecorder.reset();
mediaRecorder.setCamera(mCamera);
mediaRecorder.setOnErrorListener(OnErrorListener);
//使用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);
//设置立体声
// mediaRecorder.setAudioChannels(2);
//设置最大录像时间 单位:毫秒
// mediaRecorder.setMaxDuration(60 * 1000);
//设置最大录制的大小 单位,字节
// mediaRecorder.setMaxFileSize(1024 * 1024);
//音频一秒钟包含多少数据位
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(currentVideoFilePath);
Log.e("CustomRecordActivity", "CustomRecordActivity:" + getSDPath(CustomRecordActivity.this) + "append.mp4");
}
/**
* 创建视频文件保存路径
*/
public static String getSDPath(Context context) {
if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
Toast.makeText(context, "请查看您的SD卡是否存在!", Toast.LENGTH_SHORT).show();
return null;
}
File sdDir = Environment.getExternalStorageDirectory();
File eis = new File(sdDir.toString() + "/cqytjr/");
if (!eis.exists()) {
eis.mkdir();
}
return sdDir.toString() + "/cqytjr/";
}
private String getVideoName() {
return "video" + ".mp4";
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_record);
initView();
}
}
浙公网安备 33010602011771号