首页 > 学院 > 开发设计 > 正文

使用mediaRecorder录像的小坑

2019-11-09 15:06:14
字体:
来源:转载
供稿:网友

之前写好的工具类,直接封装好了,代码如下:

package jun.yuanlai;import android.content.Context;import android.hardware.Camera;import android.media.CamcorderPRofile;import android.media.MediaRecorder;import android.os.Environment;import android.os.Handler;import android.os.Message;import android.util.Log;import android.view.SurfaceView;import android.view.View;import android.widget.Toast;import java.io.File;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;/** * Created by cj on 2016/11/29. */public class Recorderutil {    private static final String TAG = "cj";    Context context;    private MediaRecorder mediaRecorder;    private SurfaceView sv_view;    private boolean isRecording;    private int time;    private Handler handler = new Handler(){        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            sv_view.setVisibility(View.GONE);            Toast.makeText(context, "停止录像,并保存文件", Toast.LENGTH_SHORT).show();        }    };    public Recorderutil(Context context, MediaRecorder mediaRecorder, SurfaceView sv_view, int time) {        this.context = context;        this.mediaRecorder = mediaRecorder;        this.sv_view = sv_view;        this.time = time;    }    public void startRecord() {        //准备名字        Date date = new Date();        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmm");        String format = dateFormat.format(date);        String path = Environment.getExternalStorageDirectory().getAbsolutePath();        String name = path + "/" + format + ".mp4";        //准备好了        sv_view.setVisibility(View.VISIBLE);        try {            File file = new File(name);            if (file.exists()) {                // 如果文件存在,删除它,演示代码保证设备上只有一个录音文件                file.delete();            }            mediaRecorder = new MediaRecorder();//			mediaRecorder.reset();//            mediaRecorder.setCamera(Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT));            // 设置音频录入源            mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);            // 设置视频图像的录入源            mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);            Log.e(TAG, "start: 输出格式");            // 设置录入媒体的输出格式            mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);            // 设置音频的编码格式            mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);            // 设置视频的编码格式//			mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);            mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);            // 设置视频的采样率,每秒4帧            mediaRecorder.setVideoFrameRate(4);            // 设置视频录制的分辨率。必须放在设置编码和格式的后面,否则报错//			mediaRecorder.setVideoSize(240, 240);            //一换这个6.0就走起来了            CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);            mediaRecorder.setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);//			mediaRecorder.setVideoEncodingBitRate(640*480);            // 设置录制视频文件的输出路径            Log.e(TAG, "start: 输出路径");            mediaRecorder.setOutputFile(file.getAbsolutePath());            // 设置捕获视频图像的预览界面            mediaRecorder.setPreviewDisplay(sv_view.getHolder().getSurface());//			mediaRecorder.setOrientationHint(180);// 视频旋转            Log.e(TAG, "start: surfaceholder也有了");            mediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {                @Override                public void onError(MediaRecorder mr, int what, int extra) {                    Log.e(TAG, "onError: 录制出错");                    // 发生错误,停止录制                    mediaRecorder.stop();                    mediaRecorder.release();                    mediaRecorder = null;                    isRecording = false;                    Toast.makeText(context, "录制出错", Toast.LENGTH_SHORT).show();                }            });            // 准备、开始            mediaRecorder.prepare();            Log.e(TAG, "start: 不走了");            mediaRecorder.start();            Log.e(TAG, "start: 也开始了");            isRecording = true;            Toast.makeText(context, "开始录像", Toast.LENGTH_SHORT).show();        } catch (Exception e) {            e.printStackTrace();            Log.e(TAG, "startRecord: "+e.toString() );        }        //录制5秒后自动停止        Timer timer = new Timer();        timer.schedule(new TimerTask() {            @Override            public void run() {                stopRecord();            }        },time);    }    public  void stopRecord(){        if (isRecording) {            // 如果正在录制,停止并释放资源            mediaRecorder.stop();            mediaRecorder.release();            mediaRecorder = null;            isRecording=false;            new Thread(new Runnable() {                @Override                public void run() {                    handler.sendEmptyMessage(0);                }            }).start();        }else{            Log.e(TAG, "已经停止录制" );        }    }}

我调用的时候直接使用这两句就可以了;如下:

MediaRecorder mediaRecorder = new MediaRecorder();                Recorderutil recorderutil = new Recorderutil(this,mediaRecorder,surfaceview,10000);                recorderutil.startRecord();通过按钮调用的时候,我的红米是4.4.2的系统,会弹出一个请求访问相机的对话框,允许之后就可以直接开始录像了,但是蹊跷的是如果不通过button调用,

会出现问题就是mediarecorder启动不了,会执行异常catch块,报的错误是invalid preview surface,意思就是无效的surfaceview,但是为什么会出现那样的问题呢?至今没有想明白,只好百度,不得不说,会点英语还是挺好的,中国的博客没有一个解释清楚的,结果又一个stackoverflow网站上,有这个问题,好好研读了一下,原因就是surfaceview还没有初始化好呢,就调用了 mediaRecorder.setPreviewDisplay(holder.getSurface());解决方法就是等surfaceview完全创建之后再进行调用,所以就需要改代码,改成在activity里调用的时候先getholder,在create回调里面进行录制视频,就好了

SurfaceHolder holder = surfaceview.getHolder();                holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);                holder.addCallback(new SurfaceHolder.Callback() {                    @Override                    public void surfaceCreated(SurfaceHolder holder) {                        surfaceHolder = holder;                        MediaRecorder mediaRecorder = new MediaRecorder();                        Recorderutil recorderutil = new Recorderutil(MainActivity.this,mediaRecorder,surfaceHolder,10000);                        recorderutil.startRecord();                    }                    @Override                    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {                    }                    @Override                    public void surfaceDestroyed(SurfaceHolder holder) {                    }                });


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表