• Android 开发 MediaRecorder音频录制


    前言

      MediaRecorder类是Android sdk提供的一个专门用于音视频录制,一般利用手机麦克风采集音频和摄像头采集图像.这个类是属于简单的音频录制类,录制音频简单容易但是对音频流的控制也比较弱,这篇博客将只介绍音频的录制

    实现流程

    1. 获取权限
    2. 实例化MediaRecorder
    3. 配置MediaRecorder
    4. 开启录音
    5. 停止录音
    6. 暂停录音与恢复录音
    7. 销毁释放

    获取权限

        <!--音频录制权限 -->
        <uses-permission android:name="android.permission.RECORD_AUDIO" />
        <!--读取和写入存储权限-->
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    注意!在Android 5.0后需要动态授权

    实例化MediaRecorder

      private MediaRecorder mMediaRecorder;
        private void initMediaRecorer(){
            mMediaRecorder = new MediaRecorder();
        }

    没啥好说的,就是new一个MediaRecorder

    配置MediaRecorder

    private void configMediaRecorer(){
            File demoAmrFile = new File(getExternalCacheDir(),"demo.amr");
            if (demoAmrFile.exists()){
                demoAmrFile.delete();
            }
            mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//音频录入源
            mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);//录制音频的输出格式
            mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);//录制音频的编码格式  目前手机设备上可能就AMR_NB有用
            mMediaRecorder.setOutputFile(demoAmrFile.getAbsolutePath());//音频输出路径和文件名称 注意!这个设置是有顺序要求的,必需是上面编码格式设置完成后才能,写到前面会报错
            mMediaRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {
                @Override
                public void onError(MediaRecorder mr, int what, int extra) {
                    //异常监听
                    mMediaRecorder.stop();//暂停
                    mMediaRecorder.release();//释放资源
                    mMediaRecorder = null;
                }
            });
            mMediaRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {//信息回调
                @Override
                public void onInfo(MediaRecorder mr, int what, int extra) {
    
                }
            });
    
        }

    注意!每一次录制音频前都需要配置一次.假设你录制暂停后,想重新录制新音频也需要重新执行一次这个方法,重新配置MediaRecorder!

    再次注意! 配置参数是有顺序要求的的,没有按照顺序配置会报错,一般顺序是 > 配置音频源 > 配置音频输出格式 和 编码格式 > 配置其他参数(例如:文件大小限制/录制时间限制/音频比特率)> 配置文件保存路径  >  配置各种监听.

    开启录音

      private void startRecorer(){
            if (mMediaRecorder != null){
                try {
                    mMediaRecorder.prepare();//准备
                    mMediaRecorder.start();//开启
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    注意!点击后,开始录制之前先配置一次

     mBtnStatr.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    configMediaRecorer();
                    startRecorer();
    
                }
            });

    暂停录音

    private void stopRecorer(){
            if (mMediaRecorder != null){
                mMediaRecorder.stop();//暂停
                mMediaRecorder.reset();//重启到空闲状态 此方法调用后需要重新配置参数
            }
        }

    暂停录音与恢复录音

    暂停录制,注意这里是pause()方法,不是stop()

    private void pauseRecorder(){
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                mMediaRecorder.pause();//暂停
            }
        }

    恢复录制

    private void resumeRecorder(){
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                mMediaRecorder.resume();//恢复
            }
        }

    销毁释放

    private void destroy(){
            if (mMediaRecorder != null){
                mMediaRecorder.stop();
                mMediaRecorder.release();//调用这个方法前必需先调用stop()方法
                mMediaRecorder = null;
            }
        }

    请注意! 如果在start后马上执行stop方法可能会出现 RuntimeException的异常抛出。如果你有需求会被用户操作到连续点击录制,解决办法是增加操作延迟(比如点击延迟)与截获这个异常进行处理。

    介绍有关音频录制的API

    关于开始/停止/暂停/恢复/重置/释放的方法我就不在这里说明了,上面的流程代码里有写注释.也说了它们的关键点.另外录制视频的相关API也不在这里介绍

    setAudioSource(int audio_source)

    配置音频录入源,一般只需要选择MediaRecorder.AudioSource.MIC即可

    setOutputFormat(int output_format)

    设置录制音频的输出格式,在MediaRecorder.OutputFormat里有以下这些格式可以选择,一般常用AAC_ADTS

    • DEFAULT:默认  在不更新对应值的情况下,不要更改这些值
    • THREE_GPP:3GP格式
    • MPEG_4:MP4格式
    • RAW_AMR:录制原始文件,这只支持音频录制,同时要求音频编码为AMR_NB
    • AMR_NB:   常用与通话文件语音格式 语音带宽范围:300-3400Hz,8KHz采样 
    • AMR_WB:   常用与通话文件语音格式  语音带宽范围: 50-7000Hz,16KHz采样 
    • AAC_ADIF:  Audio Data Interchange Format音频数据交换格式。这种格式的特征是可以确定的找到这个音频数据的开始,不需进行在音频数据流中间开始的解码,即它的解码必须在明确定义的开始处进行。故这种格式常用在磁盘文件中。
    • AAC_ADTS:  Audio Data Transport Stream 音频数据传输流。这种格式的特征是它是一个有同步字的比特流,解码可以在这个流中任何位置开始。它的特征类似于mp3数据流格式。这种格式可以用于广播电视。
    • OUTPUT_FORMAT_RTP_AVP: 未知
    • MPEG_2_TS:MPEG2-TS(Transport Stream“传输流”;又称TS、TP、MPEG-TS 或 M2T)是用于音效、图像与数据的通信协定,最早应用于DVD的实时传送节目。
    • WEBM:  WebM由Google提出,是一个开放、免费的媒体文件格式。WebM 影片格式其实是以 Matroska(即 MKV)容器格式为基础开发的新容器格式,里面包括了VP8影片轨和 Ogg Vorbis 音轨,其中Google将其拥有的VP8视频编码技术以类似BSD授权开源,Ogg Vorbis 本来就是开放格式。 WebM标准的网络视频更加偏向于开源并且是基于HTML5标准的,WebM 项目旨在为对每个人都开放的网络开发高质量、开放的视频格式,其重点是解决视频服务这一核心的网络用户体验。Google 说 WebM 的格式相当有效率,应该可以在 netbook、tablet、手持式装置等上面顺畅地使用

     setAudioEncoder(int audio_encoder)

     设置录制音频的编码格式  请酌情设置,有些设备并不支持一些格式。一般常用AAC。全部格式请参考如下代码:

            public static final int DEFAULT = 0;
            /** AMR (Narrowband) audio codec */
            public static final int AMR_NB = 1;
            /** AMR (Wideband) audio codec */
            public static final int AMR_WB = 2;
            /** AAC Low Complexity (AAC-LC) audio codec */
            public static final int AAC = 3;
            /** High Efficiency AAC (HE-AAC) audio codec */
            public static final int HE_AAC = 4;
            /** Enhanced Low Delay AAC (AAC-ELD) audio codec */
            public static final int AAC_ELD = 5;
            /** Ogg Vorbis audio codec */
            public static final int VORBIS = 6;

    setOutputFile(String path)

    设置输出音频文件的路径加文件名称,另外有一个setOutputFile(File file)方法,这个方法需要26API

    setAudioEncodingBitRate(int bitRate)

    设置音频的比特率, 比特率是指每秒传送的比特(bit)数。单位为 bps(Bit Per Second),比特率越高,每秒传送数据就越多,音频也就越清晰

    setMaxFileSize(long max_filesize_bytes)

    设置录音文件的最大存储大小 ,单位是byte

    setMaxDuration(int max_duration_ms)

    设置录音文件的最大录制时间,单位是毫秒

    setOnErrorListener(OnErrorListener l)

    设置监听异常报错

    setAudioChannels(int numChannels) 

    设置音频声道,官方注解里也说了这个方法的值一般是1或者2,分别代表单声道与双声道.

    setOnInfoListener(OnInfoListener listener)

    设置监听录制信息,对应返回信息,请参考如下代码注释:

        mMediaRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {//信息回调
                @Override
                public void onInfo(MediaRecorder mr, int what, int extra) {
                    switch (what) {
                        case MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED:
                            //已设置最大录制持续时间,现在已达到
                            break;
                        case MediaRecorder.MEDIA_ERROR_SERVER_DIED:
                            //媒体服务器死亡。在这种情况下,应用程序必须释放* MediaRecorder对象并实例化一个新对象
                            break;
                        case MediaRecorder.MEDIA_RECORDER_ERROR_UNKNOWN:
                            //未指定的媒体记录器错误
                            break;
                        case MediaRecorder.MEDIA_RECORDER_INFO_UNKNOWN:
                            //未指定的媒体记录器信息
                            break;
                       case MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_APPROACHING:
                           //已设置最大文件大小,并且当前记录的文件大小*已达到限制的90%
                           //达到或者超过90%限制时每个文件发送一次,要继续记录,应该使用{@link #setNextOutputFile}设置下一个输出文件。
                           //否则,达到最大文件大小时,录制将停止
                           break;
                       case MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED:
                           //已设置最大文件大小,现在已达到。
                           //注意:如果应用程序已经通过{@link #setNextOutputFile}设置了下一个输出文件,则不会发送此事件
                           break;
                       case MediaRecorder.MEDIA_RECORDER_INFO_NEXT_OUTPUT_FILE_STARTED:
                           //已达到最大文件大小,媒体记录器信息下一个输出文件已开始,
                           //并且MediaRecorder已将*输出切换为应用程序{@link #setNextOutputFile}设置的新文件
                           //为了获得最佳实践,应用程序应使用此事件来跟踪*是否使用了先前设置的文件
                           break;
                    }
    
                }
            });
  • 相关阅读:
    SQL如何获取上一条..下一条..首尾记录
    PHP判断浏览器类型的代码
    html命名规范
    使用JavaScript JS 获取label for 标签的值和for值
    PNG透明兼容IE6的几种方法
    冉茂锋同学去上课了
    十一戒,自勉
    语录
    CreateThread最后还是调用的ntdll.dll里面的ZwCreateThread
    InitializeObjectAttributes
  • 原文地址:https://www.cnblogs.com/guanxinjing/p/10976026.html
Copyright © 2020-2023  润新知