用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

相关文章

C#实现将Excel表格转换为图片(JPG/ PNG)

《C#实现将Excel表格转换为图片(JPG/PNG)》Excel表格可能会因为不同设备或字体缺失等问题,导致格式错乱或数据显示异常,转换为图片后,能确保数据的排版等保持一致,下面我们看看如何使用C... 目录通过C# 转换Excel工作表到图片通过C# 转换指定单元格区域到图片知识扩展C# 将 Excel

基于Java实现回调监听工具类

《基于Java实现回调监听工具类》这篇文章主要为大家详细介绍了如何基于Java实现一个回调监听工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录监听接口类 Listenable实际用法打印结果首先,会用到 函数式接口 Consumer, 通过这个可以解耦回调方法,下面先写一个

使用Java将DOCX文档解析为Markdown文档的代码实现

《使用Java将DOCX文档解析为Markdown文档的代码实现》在现代文档处理中,Markdown(MD)因其简洁的语法和良好的可读性,逐渐成为开发者、技术写作者和内容创作者的首选格式,然而,许多文... 目录引言1. 工具和库介绍2. 安装依赖库3. 使用Apache POI解析DOCX文档4. 将解析

Qt中QGroupBox控件的实现

《Qt中QGroupBox控件的实现》QGroupBox是Qt框架中一个非常有用的控件,它主要用于组织和管理一组相关的控件,本文主要介绍了Qt中QGroupBox控件的实现,具有一定的参考价值,感兴趣... 目录引言一、基本属性二、常用方法2.1 构造函数 2.2 设置标题2.3 设置复选框模式2.4 是否

C++使用printf语句实现进制转换的示例代码

《C++使用printf语句实现进制转换的示例代码》在C语言中,printf函数可以直接实现部分进制转换功能,通过格式说明符(formatspecifier)快速输出不同进制的数值,下面给大家分享C+... 目录一、printf 原生支持的进制转换1. 十进制、八进制、十六进制转换2. 显示进制前缀3. 指

springboot整合阿里云百炼DeepSeek实现sse流式打印的操作方法

《springboot整合阿里云百炼DeepSeek实现sse流式打印的操作方法》:本文主要介绍springboot整合阿里云百炼DeepSeek实现sse流式打印,本文给大家介绍的非常详细,对大... 目录1.开通阿里云百炼,获取到key2.新建SpringBoot项目3.工具类4.启动类5.测试类6.测

pytorch自动求梯度autograd的实现

《pytorch自动求梯度autograd的实现》autograd是一个自动微分引擎,它可以自动计算张量的梯度,本文主要介绍了pytorch自动求梯度autograd的实现,具有一定的参考价值,感兴趣... autograd是pytorch构建神经网络的核心。在 PyTorch 中,结合以下代码例子,当你

SpringBoot集成Milvus实现数据增删改查功能

《SpringBoot集成Milvus实现数据增删改查功能》milvus支持的语言比较多,支持python,Java,Go,node等开发语言,本文主要介绍如何使用Java语言,采用springboo... 目录1、Milvus基本概念2、添加maven依赖3、配置yml文件4、创建MilvusClient

JS+HTML实现在线图片水印添加工具

《JS+HTML实现在线图片水印添加工具》在社交媒体和内容创作日益频繁的今天,如何保护原创内容、展示品牌身份成了一个不得不面对的问题,本文将实现一个完全基于HTML+CSS构建的现代化图片水印在线工具... 目录概述功能亮点使用方法技术解析延伸思考运行效果项目源码下载总结概述在社交媒体和内容创作日益频繁的

使用Python开发一个带EPUB转换功能的Markdown编辑器

《使用Python开发一个带EPUB转换功能的Markdown编辑器》Markdown因其简单易用和强大的格式支持,成为了写作者、开发者及内容创作者的首选格式,本文将通过Python开发一个Markd... 目录应用概览代码结构与核心组件1. 初始化与布局 (__init__)2. 工具栏 (setup_t