当前位置: 首页 > news >正文

Android Studio新手开发第三十三天

利用MediaRecorder录制视频

        上一次介绍了如何利用MediaRecorder录制音频,而MediaRecorder也可以用于录制视频,在录制视频前需要获取相机权限,要在AndroidManifest.xml中添加权限声明以及在代码中查看是否已经获取该权限,若没有就提示用户开启权限或者直接到设置中手动开启,下面的代码没有做这一部分,直接在系统设置中手动开启了。示例代码如下,在布局文件中添加两个按钮、一个文本视图以及一个SurfaceView用于实时展示相机获取的视频内容。

<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MultiMedia.RecordVideoActivity"><Buttonandroid:id="@+id/startRecord"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="StartRecord" /><Buttonandroid:id="@+id/stopRecord"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="StopRecord" /><TextViewandroid:id="@+id/textView"android:layout_width="match_parent"android:layout_height="wrap_content"/><SurfaceViewandroid:id="@+id/surfaceView"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="center"/></androidx.appcompat.widget.LinearLayoutCompat>

        部分Java代码如下,主要看方法initializeCamera以及方法prepareMediaRecorder的内容。在方法initializeCamera中重点在于unlock方法的调用上,若想要调用方法setPreviewDisplay建议不要调用unlock方法,可能会报错如PreviewTexture failed,作者自己在学习使用时就出现这样的错误,后面将unlock方法去掉后就没问题了。

        在方法prepareMediaRecorder中若不想要使用方法setCamera是可以的但是在SurfaceView上显示的视频方向会颠倒与预期不符,这也是使用setCamera的原因之一,利用Camera类可以事先设置摄像头的一些配置然后再将它用于录制视频。若要调用setCamera方法则需要先将Camera解锁即调用unlock方法。在往后就是设置MediaRecorder的一些属性,如音频源,视频源,视频长度,视频规格,录制方向、输出格式以及编码器等。MediaRecorder的监听器中要实现Camera的初始化,若在onCreate方法中调用initializeCamera方法不能够实现实时展示视频内容,作者自己学的时候就出现该问题,不知道为什么。

public class RecordVideoActivity extends AppCompatActivity implements View.OnClickListener, MediaRecorder.OnInfoListener {private final String public_url = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString();private String private_url;private Button startRecord, stopRecord;private TextView textView;private SurfaceView surfaceView;private SurfaceHolder holder;private MediaRecorder mediaRecorder;private Camera camera;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_record_video);initView();}@Overridepublic void onInfo(MediaRecorder mediaRecorder, int i, int i1) {//录制时长达到预设值停止录制并释放MediaRecorderif (i == MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {stopRecording();}}@Overridepublic void onClick(View view) {if (view.getId() == R.id.startRecord) {startRecording();} else if (view.getId() == R.id.stopRecord) {if (mediaRecorder != null) {stopRecording();releaseMediaRecorder();}}}//初始化页面private void initView() {startRecord = findViewById(R.id.startRecord);stopRecord = findViewById(R.id.stopRecord);textView = findViewById(R.id.textView);private_url = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString();File recordFile = new File(private_url + "/audioRecord/");if (!recordFile.exists()) {boolean i = recordFile.mkdirs();if (i) {textView.setText("文件夹不存在,已新建!");}}// 初始化 SurfaceView 用于预览surfaceView = findViewById(R.id.surfaceView);holder = surfaceView.getHolder();holder.addCallback(new SurfaceHolder.Callback() {@Overridepublic void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {initializeCamera();//初始化Camera}@Overridepublic void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int i, int i1, int i2) {}@Overridepublic void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {}});startRecord.setOnClickListener(this);stopRecord.setOnClickListener(this);}//初始化Cameraprivate void initializeCamera() {// 初始化 Camera,0 通常代表后置摄像头camera = Camera.open(0);// 调整摄像头预览角度,例如设置为90度camera.setDisplayOrientation(90);// 设置SurfaceView不维护自己的缓冲区holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//若在这里先解锁Camera,那么在进入页面时将不能预览Camera即调用camera.setPreviewDisplay(holder)将会出错而不能调用camera.startPreview()进行预览//camera.unlock();// 将Camera的预览输出与SurfaceView关联try {camera.setPreviewDisplay(holder);} catch (IOException e) {Log.d(TAG, "initializeCamera: " + e.getMessage());}camera.startPreview(); // 开始预览}//准备录制视频,返回值为布尔类型,用于判断能否开始录制private boolean prepareMediaRecorder() {mediaRecorder = new MediaRecorder();camera.unlock(); // 解锁Camera以便MediaRecorder使用mediaRecorder.setCamera(camera); // 关联CameraCalendar calendar = Calendar.getInstance();String path = String.format("%s/audioRecord/%s%s%s%s%s.mp4", private_url, calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE));// 设置音频和视频源mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 设置音频源为麦克风mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // 设置视频源为摄像头// 设置输出格式mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); // 设置输出格式为MPEG-4// 设置音频和视频编码器mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); // 设置音频编码器为AACmediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); // 设置视频编码器为H.264// 设置输出文件mediaRecorder.setOutputFile(path);//录制5秒时间mediaRecorder.setMaxDuration(5000);// 设置视频参数mediaRecorder.setVideoSize(1280, 720); // 设置视频尺寸mediaRecorder.setVideoFrameRate(30); // 设置视频帧率// 设置视频编码比特率(可选)//mediaRecorder.setVideoEncodingBitRate(10000);// 设置录制方向,90度通常表示竖屏录制mediaRecorder.setOrientationHint(90);// 将预览设置关联到MediaRecordermediaRecorder.setPreviewDisplay(surfaceView.getHolder().getSurface());//添加信息监听器mediaRecorder.setOnInfoListener(this);try {mediaRecorder.prepare(); // 准备录制textView.setText("准备录制!");} catch (IOException e) {Log.d(TAG, "prepareMediaRecorder: " + e.getMessage());releaseMediaRecorder();return false;}return true;}//开始录制public void startRecording() {if (prepareMediaRecorder()) {mediaRecorder.start(); // 开始录制textView.setText("正在录制...");}}//停止录制,释放MediaRecord以及锁定Camerapublic void stopRecording() {if (mediaRecorder != null) {mediaRecorder.stop(); // 停止录制releaseMediaRecorder(); // 释放MediaRecordercamera.lock(); // 锁定CameratextView.setText("停止录制!");}}//释放MediaRecorderprivate void releaseMediaRecorder() {if (mediaRecorder != null) {mediaRecorder.reset(); // 重置MediaRecordermediaRecorder.release(); // 释放MediaRecordermediaRecorder = null;}}@Overrideprotected void onDestroy() {super.onDestroy();releaseMediaRecorder();if (camera != null) {camera.release(); // 释放Cameracamera = null;}}
}

        效果图如下,第一张是刚进入APP的页面,第二张是开始录制、第三张是结束录制、第四张是在保存路径上找到对应的视频。

http://www.dtcms.com/a/537078.html

相关文章:

  • 九牛科技网站开发微信营销做电影网站侵权
  • 基于dcmtk的dicom工具 第十章 读取dicom文件图像数据并显示
  • wordpress站点浏览网站建设和网站优化的区别
  • 天锐绿盾防泄密系统注册机,支持2025年V7.51版本注册
  • c语言实现队列【由浅入深-数据结构】
  • Flink ExecutionConfig 实战并行度、序列化、对象重用与全局参数
  • 家政类网站开发成本wordpress 音乐不中断
  • STM32-SPI协议
  • 西安网站开发php网站插件
  • LinearRAG—重新定义GraphRAG:无需关系抽取的线性图构建新范式 -香港理工
  • 第4章-程序计数器
  • HashMap 与 HashSet
  • 怎么在虚拟主机上建网站wordpress rest图片
  • 小米手机之间数据转移的6种方法
  • 前端开发中的表格标签
  • PaddleOCR-VL本地部署流程
  • 2.2 复合类型
  • 做网站图片自动切换宁波软件开发
  • quat:高性能四元数运算库
  • [MySQL]表——分组查询
  • 济南做网站的好公司有哪些极简资讯网站开发
  • 网站后台页面设计互联网+可以做什么项目
  • 项目八 使用postman实现简易防火墙功能
  • 使用postman 测试restful接口
  • 2008 iis 添加 网站 权限设置网站策划案4500
  • 以自主创新推动能源装备智能化升级,为能源安全构筑“确定性”底座
  • 构建AI智能体:七十六、深入浅出LoRA:低成本高效微调大模型的原理与实践
  • 中国各大网站排名网站源码爬取
  • FFmpeg 安装与配置教程(Windows 系统)
  • 【数字逻辑】 60进制数字秒表设计实战:用74HC161搭计数器+共阴极数码管显示(附完整接线图)