【Android-R1】MediaRecorder和MediaPlayer的基本使用

2023-11-28 09:50

本文主要是介绍【Android-R1】MediaRecorder和MediaPlayer的基本使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

        最近看到网上曾经火热的倒放挑战感觉挺有意思,于是打算研发一款线下游戏APP,让广大群众可以体验一把感受一下。现在处于起步研究阶段,目前总算找对了方向,先把之前做的一些研究和笔记整理一下,今天先把MediaRecorder和MediaPlayer的基本使用写了。如果没有意外的话,我会把这个项目做成一个系列,代号R1(random one缩写,意思是这个项目是第一个随机的安卓项目),我会把这个项目中研究过的我认为有价值的东西整理成笔记发表在这里,欢迎各位小伙伴来一起探讨和学习,下面废话不多说,直接进入正题。

 MediaRecorder

        用一个东西必然要先了解它,所以我们先进android developer的MediaRecorder指南浏览一番,这个指南就是介绍一下基本的使用,如果要更详细的可以看MediaRecorder参考文档,我把我使用过程中需要注意的点再啰嗦一下。

        MediaRecorder这个玩意是有状态变化的,如果你的MediaRecorder还没进入准备状态就直接调用record方法,那么程序会直接报错;所以参考文档给了以下的状态变化图

         由此可知,对于录音这个过程的正确调用顺序是:

        new -->setAudioSource-->setOutputFormat-->setAudioEncoder-->setOutputFile-->

prepare-->start-->stop-->setAudioSource或release

        在new的时候,我发现我使用的sdk版本(API 31)会提示旧的构造函数已经deprecated,但是用新的构造函数反而会报错,所以那个提示可以先无视掉。

        大家看完这个图有没有什么想法,我有个想法是,如果我第一次录完音stop后,recorder回到初始状态,如果我想再次录音,又要再写一遍设置参数的代码,所以这里可以做个小扩展,从setAudioSource到prepare之前都封装掉,所以我们可以动手写个Recorder的子类。

import android.media.MediaRecorder;public class MyRecorder extends MediaRecorder{private final int DEFAULT_AUDIO_SOURCE = MediaRecorder.AudioSource.MIC;private final int DEFAULT_OUTPUT_FORMAT = MediaRecorder.OutputFormat.DEFAULT;private final int DEFAULT_AUDIO_ENCODER = MediaRecorder.AudioEncoder.DEFAULT;public MyRecorder(){}public void setDefaultParam(){setAudioSource(DEFAULT_AUDIO_SOURCE);setOutputFormat(DEFAULT_OUTPUT_FORMAT);setAudioEncoder(DEFAULT_AUDIO_ENCODER);}public void setParam(int audioSource,int outputFormat,int audioEncoder){setAudioSource(audioSource);setOutputFormat(outputFormat);setAudioEncoder(audioEncoder);}
}

        由于MediaRecorder的start和stop方法系统会自动将其放在后台运行,所以不用特意写个线程来避开UI线程的阻塞。这里做的扩展仅仅是为了调用时少写点代码。

        调用步骤如下所示:

mRecorder = new MyRecorder();
mRecorder.setParam(MediaRecorder.AudioSource.MIC,
MediaRecorder.OutputFormat.AMR_WB,
MediaRecorder.AudioEncoder.AMR_WB);
mRecorder.setOutputFile(getExternalFilesDir("").getAbsolutePath()
+ File.separator + getFileName());
try {mRecorder.prepare();
}catch (Exception e){e.printStackTrace();
}
mRecorder.start();

        其实我比较困惑的是编码器和格式各个值的意义,AudioEncoder的枚举值如下(方便排版,我将逗号换成tab):

AAC        AAC_ELD        AMR_NB        AMR_WB        DEFAULT        HE_AAC        OPUS       VORBIS

       OutputFormat的枚举值如下:


AAC_ADTS        AMR_NB        AMR_WB        DEFAULT        MPEG_2_TS        MPEG_4

OGG                RAW_AMR        THREE_GPP        WEBM

        先讲下DEFAULT值,这个值是由你的机器决定选取其他格式中的任意一种。我查了百度,似乎没有对这些值的详细讲解,也没有哪篇文章把每个算法对应输出的文件格式对号入座,那么这个艰巨的任务就交给我了!接下来我将列出每个OutputFormat对应的文件格式(后缀名)。

AAC_ADTS

        AAC音频格式Advanced Audio Coding(高级音频解码),是一种由MPEG-4标准定义的有损音频压缩格式。

        ADTS:ADTS的全称是Audio Data Transport Stream。是AAC音频的传输流格式。AAC音频格式在MPEG-2(ISO-13318-7 2003)中有定义。AAC后来又被采用到MPEG-4标准中。这种格式的特征是它是一个有同步字的比特流,解码可以在这个流中任何位置开始。它的特征类似于mp3数据流格式。

        还有一种传输格式是ADIF:Audio Data Interchange Format 音频数据交换格式。这种格式的特征是可以确定的找到这个音频数据的开始,不需进行在音频数据流中间开始的解码,即它的解码必须在明确定义的开始处进行。

        其实不用具体了解那么多格式,我们需要知道的是,以AAC开头的就是AAC压缩格式,其对应的输出文件格式为.aac;

AMR

        AMR(全称是Adaptibve Multi-Rate)是一种音频格式。主要用于移动设备的音频,压缩比比较大,但相对其他的压缩格式质量比较差,语音带宽范围:300-3400Hz,由于多用于人声,通话,效果还是很不错的。AMR-NB就是指AMR。

        “AMR-WB”全称为“Adaptive Multi-rate - Wideband”,即“自适应多速率宽带编码”,采样频率为16kHz,是一种同时被国际标准化组织ITU-T和3GPP采用的宽带语音编码标准,也称 为G722.2标准。AMR-WB提供语音带宽范围达到50~7000Hz,用户可主观感受到话音比以前更加自然、舒适和易于分辨。

        其对应格式:.amr

MPEG

        MPEG是一种专门针对运动图像和语音压缩的编码标准。上面列举的MPEG_2_TS和MPEG_4是不同的版本,支持MPEG的文件格式有很多,比如mp4,avi等。

OGG

        Ogg全称是OGGVobis(oggVorbis)是一种音频压缩格式,类似于MP3等的音乐格式。Ogg是完全免费、开放和没有专利限制的。OggVorbis文件的扩展名是".ogg"。这种文件的设计格式是非常先进的。现在创建的OGG文件可以在未来的任何播放器上播放,因此,这种文件格式可以不断地进行大小和音质的改良,而不影响旧有的编码器或播放器。

THREE_GPP

        3GPP是由一组电信合作伙伴建立的、成立于1998年12月的标准化组织或机构,其成员包括欧洲ETSI、日本ARIB和TTC、中国CCSA、韩国TTA和北美ATIS。其目标是在ITU的IMT-2000计划范围内制订和实现全球性的第三代移动通信电话系统技术规范和宽带标准,致力于GSM到UMTS(WCDMA)的演进。

        3GP是一种常见视频格式,是MPEG-4 Part 14(MP4)格式的一种简化版本,常用于手机。其对应文件格式:.3gp

WEBM

        WebM 格式,其实是以 Matroska(就是我们熟知的 MKV)容器格式为基础开发的新容器格式,里面包括了 VP8 视频和 Ogg Vorbis 音轨。Ogg Vorbis 本来就是开放格式, VP8 则是 Google 当年买下 On2 公司时取得的 视频编码器,这次 Google 也把这个编码器以类似 BSD 授权开放,因此 WebM 应该是不会有 H.264 的那些潜在的专利问题。

        对应文件格式:.webm

Opus

        Opus是一个有损声音编码的格式,由Xiph.Org基金会开发,之后由IETF(互联网工程任务组)进行标准化,目标是希望用单一格式包含声音和语音,取代Speex和Vorbis,且适用于网络上低延迟的即时声音传输,标准格式定义于RFC 6716文件。Opus格式是一个开放格式,使用上没有任何专利或限制。

        以上各种格式介绍借鉴自百度百科和一些大神的博客,如果有错误请多包涵~基本上,你设置的编码器编码算法和你的输出格式大类是一样的就OK了,比如AudioEncoder我设置AAC,OutputFormat设置AAC_ADTS,然后输出文件名的后缀设为.aac。

        

MediaPlayer

        参考文档里是这么介绍的:

        MediaPlayer class can be used to control playback of audio/video files and streams.

        MediaPlayer is not thread-safe. Creation of and all access to player instances should be on the same thread. If registering callbacks, the thread must have a Looper.

        翻译成人话就是,MediaPlayer是用来控制播放音频/视频的,其输入可以是文件或流的形式。但MediaPlayer不是线程安全的,MediaPlayer对象的创建以及对其域或方法的访问应当都在同一线程中,如果注册了回调函数,那么线程应该有个looper(这looper是啥我暂时不清楚,高手可以评论解答下)。

        与MediaRecorder相同,MediaPlayer也有一个状态图:

         我看到这个图片下还有好大一段文字,这些文字内容先放着哪天我有空了再完整整理出来,这次我就抓重点讲。从这张图可以分析出最基本的使用流程:

new-->setDataSource-->prepare-->start-->stop/pause-->release

        MediaPlayer相对MediaRecorder没有那么多需要设置的参数了,所以我们应当将关注的重点放在什么状态下才能调什么API上,以及怎么写代码更加规范,基本上对照着这张图调API不会有什么大问题,很多东西参考文档也已经给出详细解释了,所以MediaPlayer没啥好讲的。

        那么本期就简单讲了下MediaRecorder和MediaPlayer,这两个玩意其实已经封装得很好用了,底层的AudioRecord和AudioTrack才是真的调用起来麻烦的一批,好那么我们下期再见!

这篇关于【Android-R1】MediaRecorder和MediaPlayer的基本使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

Linux join命令的使用及说明

《Linuxjoin命令的使用及说明》`join`命令用于在Linux中按字段将两个文件进行连接,类似于SQL的JOIN,它需要两个文件按用于匹配的字段排序,并且第一个文件的换行符必须是LF,`jo... 目录一. 基本语法二. 数据准备三. 指定文件的连接key四.-a输出指定文件的所有行五.-o指定输出

Linux jq命令的使用解读

《Linuxjq命令的使用解读》jq是一个强大的命令行工具,用于处理JSON数据,它可以用来查看、过滤、修改、格式化JSON数据,通过使用各种选项和过滤器,可以实现复杂的JSON处理任务... 目录一. 简介二. 选项2.1.2.2-c2.3-r2.4-R三. 字段提取3.1 普通字段3.2 数组字段四.

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

k8s按需创建PV和使用PVC详解

《k8s按需创建PV和使用PVC详解》Kubernetes中,PV和PVC用于管理持久存储,StorageClass实现动态PV分配,PVC声明存储需求并绑定PV,通过kubectl验证状态,注意回收... 目录1.按需创建 PV(使用 StorageClass)创建 StorageClass2.创建 PV

Redis 基本数据类型和使用详解

《Redis基本数据类型和使用详解》String是Redis最基本的数据类型,一个键对应一个值,它的功能十分强大,可以存储字符串、整数、浮点数等多种数据格式,本文给大家介绍Redis基本数据类型和... 目录一、Redis 入门介绍二、Redis 的五大基本数据类型2.1 String 类型2.2 Hash

Redis中Hash从使用过程到原理说明

《Redis中Hash从使用过程到原理说明》RedisHash结构用于存储字段-值对,适合对象数据,支持HSET、HGET等命令,采用ziplist或hashtable编码,通过渐进式rehash优化... 目录一、开篇:Hash就像超市的货架二、Hash的基本使用1. 常用命令示例2. Java操作示例三

Linux创建服务使用systemctl管理详解

《Linux创建服务使用systemctl管理详解》文章指导在Linux中创建systemd服务,设置文件权限为所有者读写、其他只读,重新加载配置,启动服务并检查状态,确保服务正常运行,关键步骤包括权... 目录创建服务 /usr/lib/systemd/system/设置服务文件权限:所有者读写js,其他