用MediaRecorder实现简单的录像功能

2023-12-05 06:58

本文主要是介绍用MediaRecorder实现简单的录像功能,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

思路:定义一个SurfaceView用来显示预览,在SurfaceHolder的回调中用Camera对象启动预览,然后调用MediaRecorder来录像。只是实现了简单的录像开始和停止功能,顶部能显示显示录像的时间,还有待完善。

代码如下:

在AndroidManifest.xml添加下面的权限:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 硬件支持 -->
<uses-feature android:name="android.hardware.camera"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent" ><SurfaceViewandroid:id="@+id/camera_preview"android:layout_width="match_parent"android:layout_height="match_parent" /><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentTop="true"android:layout_centerHorizontal="true"android:orientation="horizontal"><TextViewandroid:id="@+id/timestamp_minute_prefix"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#7F00FF"android:textSize="30sp"android:text="0"/><TextViewandroid:id="@+id/timestamp_minute_text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#7F00FF"android:textSize="30sp"android:text="0"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#7F00FF"android:textSize="30sp"android:text=":"/><TextViewandroid:id="@+id/timestamp_second_prefix"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#7F00FF"android:textSize="30sp"android:text="0"/><TextViewandroid:id="@+id/timestamp_second_text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#7F00FF"android:textSize="30sp"android:text="0"/></LinearLayout><ImageButtonandroid:id="@+id/record_shutter"android:layout_width="64dp"android:layout_height="64dp"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"android:layout_marginBottom="15dp"android:background="@android:color/transparent"android:scaleType="centerCrop"android:src="@drawable/recording_shutter" /></RelativeLayout>
MainActivity.java
package com.jackie.videorecorder;import java.io.File;import android.app.Activity;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.Size;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.TextView;import org.w3c.dom.Text;public class MainActivity extends Activity implements OnClickListener {private SurfaceView mCameraPreview;private SurfaceHolder mSurfaceHolder;private ImageButton mShutter;private TextView mMinutePrefix;private TextView mMinuteText;private TextView mSecondPrefix;private TextView mSecondText;private Camera mCamera;private MediaRecorder mRecorder;private final static int CAMERA_ID = 0;private boolean mIsRecording = false;private boolean mIsSufaceCreated = false;private static final String TAG = "Jackie";private Handler mHandler = new Handler();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mCameraPreview = (SurfaceView) findViewById(R.id.camera_preview);mMinutePrefix = (TextView) findViewById(R.id.timestamp_minute_prefix);mMinuteText = (TextView) findViewById(R.id.timestamp_minute_text);mSecondPrefix = (TextView) findViewById(R.id.timestamp_second_prefix);mSecondText = (TextView) findViewById(R.id.timestamp_second_text);mSurfaceHolder = mCameraPreview.getHolder();mSurfaceHolder.addCallback(mSurfaceCallback);mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);mShutter = (ImageButton) findViewById(R.id.record_shutter);mShutter.setOnClickListener(this);}@Overrideprotected void onPause() {super.onPause();if (mIsRecording) {stopRecording();}stopPreview();}private  SurfaceHolder.Callback mSurfaceCallback = new SurfaceHolder.Callback() {@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {mIsSufaceCreated = false;}@Overridepublic void surfaceCreated(SurfaceHolder holder) {mIsSufaceCreated = true;}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {startPreview();}};//启动预览private void startPreview() {//保证只有一个Camera对象if (mCamera != null || !mIsSufaceCreated) {Log.d(TAG, "startPreview will return");return;}mCamera = Camera.open(CAMERA_ID);Parameters parameters = mCamera.getParameters();Size size = getBestPreviewSize(CameraUtils.PREVIEW_WIDTH, CameraUtils.PREVIEW_HEIGHT, parameters);if (size != null) {parameters.setPreviewSize(size.width, size.height);}parameters.setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);parameters.setPreviewFrameRate(20);//设置相机预览方向mCamera.setDisplayOrientation(90);mCamera.setParameters(parameters);try {mCamera.setPreviewDisplay(mSurfaceHolder);
//			mCamera.setPreviewCallback(mPreviewCallback);} catch (Exception e) {Log.d(TAG, e.getMessage());}mCamera.startPreview();}private void stopPreview() {//释放Camera对象if (mCamera != null) {try {mCamera.setPreviewDisplay(null);} catch (Exception e) {Log.e(TAG, e.getMessage());}mCamera.stopPreview();mCamera.release();mCamera = null;}}private Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters) {Camera.Size result = null;for (Camera.Size size : parameters.getSupportedPreviewSizes()) {if (size.width <= width && size.height <= height) {if (result == null) {result = size;} else {int resultArea = result.width * result.height;int newArea = size.width * size.height;if (newArea > resultArea) {result = size;}}}}return result;}@Overridepublic void onClick(View v) {if (mIsRecording) {stopRecording();} else {initMediaRecorder();startRecording();//开始录像后,每隔1s去更新录像的时间戳mHandler.postDelayed(mTimestampRunnable, 1000);}}private void initMediaRecorder() {mRecorder = new MediaRecorder();//实例化mCamera.unlock();//给Recorder设置Camera对象,保证录像跟预览的方向保持一致mRecorder.setCamera(mCamera);mRecorder.setOrientationHint(90);  //改变保存后的视频文件播放时是否横屏(不加这句,视频文件播放的时候角度是反的)mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); // 设置从麦克风采集声音mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // 设置从摄像头采集图像mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);  // 设置视频的输出格式 为MP4mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); // 设置音频的编码格式mRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); // 设置视频的编码格式mRecorder.setVideoSize(176, 144);  // 设置视频大小mRecorder.setVideoFrameRate(20); // 设置帧率
//        mRecorder.setMaxDuration(10000); //设置最大录像时间为10smRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());//设置视频存储路径File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES) + File.separator + "VideoRecorder");if (!file.exists()) {//多级文件夹的创建file.mkdirs();}mRecorder.setOutputFile(file.getPath() + File.separator + "VID_" + System.currentTimeMillis() + ".mp4");}private void startRecording() {if (mRecorder != null) {try {mRecorder.prepare();mRecorder.start();} catch (Exception e) {mIsRecording = false;Log.e(TAG, e.getMessage());}}mShutter.setImageDrawable(getResources().getDrawable(R.drawable.recording_shutter_hl));mIsRecording = true;}private void stopRecording() {if (mCamera != null) {mCamera.lock();}if (mRecorder != null) {mRecorder.stop();mRecorder.release();mRecorder = null;}mShutter.setImageDrawable(getResources().getDrawable(R.drawable.recording_shutter));mIsRecording = false;mHandler.removeCallbacks(mTimestampRunnable);//将录像时间还原mMinutePrefix.setVisibility(View.VISIBLE);mMinuteText.setText("0");mSecondPrefix.setVisibility(View.VISIBLE);mSecondText.setText("0");//重启预览startPreview();}private Runnable mTimestampRunnable = new Runnable() {@Overridepublic void run() {updateTimestamp();mHandler.postDelayed(this, 1000);}};private void updateTimestamp() {int second = Integer.parseInt(mSecondText.getText().toString());int minute = Integer.parseInt(mMinuteText.getText().toString());second++;Log.d(TAG, "second: " + second);if (second < 10) {mSecondText.setText(String.valueOf(second));} else if (second >= 10 && second < 60) {mSecondPrefix.setVisibility(View.GONE);mSecondText.setText(String.valueOf(second));} else if (second >= 60) {mSecondPrefix.setVisibility(View.VISIBLE);mSecondText.setText("0");minute++;mMinuteText.setText(String.valueOf(minute));} else if (minute >= 60) {mMinutePrefix.setVisibility(View.GONE);}}
}

效果如下:



这篇关于用MediaRecorder实现简单的录像功能的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/456597

相关文章

基于Python Playwright进行前端性能测试的脚本实现

《基于PythonPlaywright进行前端性能测试的脚本实现》在当今Web应用开发中,性能优化是提升用户体验的关键因素之一,本文将介绍如何使用Playwright构建一个自动化性能测试工具,希望... 目录引言工具概述整体架构核心实现解析1. 浏览器初始化2. 性能数据收集3. 资源分析4. 关键性能指

使用Redis快速实现共享Session登录的详细步骤

《使用Redis快速实现共享Session登录的详细步骤》在Web开发中,Session通常用于存储用户的会话信息,允许用户在多个页面之间保持登录状态,Redis是一个开源的高性能键值数据库,广泛用于... 目录前言实现原理:步骤:使用Redis实现共享Session登录1. 引入Redis依赖2. 配置R

SpringBoot实现RSA+AES自动接口解密的实战指南

《SpringBoot实现RSA+AES自动接口解密的实战指南》在当今数据泄露频发的网络环境中,接口安全已成为开发者不可忽视的核心议题,RSA+AES混合加密方案因其安全性高、性能优越而被广泛采用,本... 目录一、项目依赖与环境准备1.1 Maven依赖配置1.2 密钥生成与配置二、加密工具类实现2.1

在Java中实现线程之间的数据共享的几种方式总结

《在Java中实现线程之间的数据共享的几种方式总结》在Java中实现线程间数据共享是并发编程的核心需求,但需要谨慎处理同步问题以避免竞态条件,本文通过代码示例给大家介绍了几种主要实现方式及其最佳实践,... 目录1. 共享变量与同步机制2. 轻量级通信机制3. 线程安全容器4. 线程局部变量(ThreadL

Python yield与yield from的简单使用方式

《Pythonyield与yieldfrom的简单使用方式》生成器通过yield定义,可在处理I/O时暂停执行并返回部分结果,待其他任务完成后继续,yieldfrom用于将一个生成器的值传递给另一... 目录python yield与yield from的使用代码结构总结Python yield与yield

python使用Akshare与Streamlit实现股票估值分析教程(图文代码)

《python使用Akshare与Streamlit实现股票估值分析教程(图文代码)》入职测试中的一道题,要求:从Akshare下载某一个股票近十年的财务报表包括,资产负债表,利润表,现金流量表,保存... 目录一、前言二、核心知识点梳理1、Akshare数据获取2、Pandas数据处理3、Matplotl

分布式锁在Spring Boot应用中的实现过程

《分布式锁在SpringBoot应用中的实现过程》文章介绍在SpringBoot中通过自定义Lock注解、LockAspect切面和RedisLockUtils工具类实现分布式锁,确保多实例并发操作... 目录Lock注解LockASPect切面RedisLockUtils工具类总结在现代微服务架构中,分布

Java使用Thumbnailator库实现图片处理与压缩功能

《Java使用Thumbnailator库实现图片处理与压缩功能》Thumbnailator是高性能Java图像处理库,支持缩放、旋转、水印添加、裁剪及格式转换,提供易用API和性能优化,适合Web应... 目录1. 图片处理库Thumbnailator介绍2. 基本和指定大小图片缩放功能2.1 图片缩放的

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

深度解析Spring Security 中的 SecurityFilterChain核心功能

《深度解析SpringSecurity中的SecurityFilterChain核心功能》SecurityFilterChain通过组件化配置、类型安全路径匹配、多链协同三大特性,重构了Spri... 目录Spring Security 中的SecurityFilterChain深度解析一、Security