首页 >> 大全

第十一章 多媒体应用开发(音视频播放)

2023-06-17 大全 47 作者:考证青年

第十一章 多媒体应用开发

文章目录 1.2 的状态图和及生命周期 2、类 2.3 环绕音2.4 均衡器2.5 预设混响处理: .6 环境声混响器: .7 :示波器 3、类 4、使用播放音频 5、类 6、使用 和播放视频

第一节 音视频开发

SDK 提供了简单的 API 来播放音频、视频,从而让大部分的 应用程序开发者无需为音频和视频的一些底层操作而担忧。 提供了常见音频、视频的编码、解码机制, 支持的音频格式较多,常见的有 MP3、WAVE、Ogg 和 3GP 等,支持的视频格式常见的有 MP4 和 3GP 等。在 操作系统之中,开发者直接使用 类就可以完成音频或视频文件的播放操作。

1、 类

是处于 多媒体包下".media."的 自带的多媒体库, 一般我们用于实现音频和视频(视频需要和其他控件一起使用比如: 和 等)的操作

1.1使用 播放音频 1.创建对象,并装载音频文件

① 可以使用直接new的方式:

MediaPlayer mp = new MediaPlayer();
//要用setDataSource()方法指定要播放的资源文件。并且在调用start()方法之前需要调用prepare ()。
//装载文件
player=new MediaPlayer();
try {player.setDataSource(this,Uri.**parse**("android.resource://" + getPackageName() + "/" + R.raw.**da**));player.prepare();
} catch (IOException e) {e.printStackTrace();
}

② 也可以使用的方式,如:

MediaPlayer mp = MediaPlayer.create(this, R.raw.test);
//这时就不用调用setDataSource了,直接用player.start(),不需要也不能在start()方法之前调用prepare()方法

2.设置要播放的文件

的一共四个方法:

在使用()方法装载音频文件后,实际上并未真正装载该音频文件,还需要调用的 ()方法真正装载音频件

要播放的文件主要包括3个来源:

① 播放应用中事先自带的资源

res文件夹与asset文件夹的区别?

中资源分为两种,一种是res下可编译的资源文件, 这种资源文件系统会在R.Java里面自动生成该资源文件的ID,访问也很简单,只需要调用R.xxx.id即可;第二种就是放在文件夹下面的原生资源文件,放在这个文件夹下面的文件不会被R文件编译,所以不能像第一种那样直接使用;并且res/raw不可以有目录结构,而则可以有目录结构,也就是目录下可以再建立文件夹

A. 播放应用的资源文件

​ i. 调用的( , int resid)方法加载指定资源文件。

​ ii. 调用的start()、pause ()、stop()等方法控制播放即可。

音频资源文件一般放在应用的/res/raw目录下

例如:.(this, R.raw.song);

或者使用()

Uri uri=Uri.parse("android.resource://"+this.getPackageName()+"/"+R.raw.da);player=new MediaPlayer();try {​     player.setDataSource(this,uri);​     player.prepare();} catch (IOException e) {​     e.printStackTrace();}

B. 播放应用的原始资源文件

​ i. 调用中的 ()方法获取应用的。

​ ii. 调用对象的( name)方法打开指定的原生资源,该方法返回一个对象。

​ //获取通过()的方法获取asset目录下指定文件的对象。

​ iii. 调用的()、()和()方法来获取音频文件的、开始位置、长度等。

​ //在中一项的文件描述符。这提供你自己打开的可用于读取的数据,以及在文件中的偏移量和长度的该项的数据。

​ iv. 创建对象,并调用对象的( fd , long ,long )方法来装载音频资源。

​ v. 调用对象的 ()方法准备音频。

​ vi. 调用的start()、pause()、stop()等方法控制播放即可

② 存储在SD卡或其他文件路径下的媒体文件

​ i. 创建对象,并调用对象的( path)方法装载指定音频文件。

​ ii. 调用对象的()方法准备音频。

​ iii. 调用的start()、stop()等方法控制播放即可。

例如:player=new MediaPlayer();try {player.setDataSource("/sdcard/pm.mp3");	
//或者
player.setDataSource(Environment.getExternalStorageDirectory ()+"/pm.mp3");
​    player.prepare();} catch (IOException e) {
​    e.printStackTrace();}

注意:对访问需要在.xml设置相应权限

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

安卓23.0版本以上,不仅仅要设置上面的权限,还要在对SD卡有读写操作的地方授权

//判断是否6.0以上的手机
if(Build.VERSION.SDK_INT>=23){
//判断是否有这个权限
int permission = ActivityCompat.checkSelfPermission (this, Manifest.permission.READ_EXTERNAL_STORAGE);
//checkSelfPermission检查对应权限是否打开,如果是PackageManager.PERMISSION_GRANTED 表示打开
if (permission != PackageManager.PERMISSION_GRANTED) {// 请求权限ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, EXTERNAL_STORAGE_REQ_CODE);
}
//第二个参数表示请求的权限数组
//第三个参数表示的请求码,请求码要求大于0

③ 网络上的媒体文件

​ A. 直接使用( ,Uri uri)

例如:MediaPlayer mp=MediaPlayer.create(this,Uri.parse(http://www.test.cn/music/m1.mp3);

​ B. 调用( ,Uri uri)

例如:mp.setDataSource(this,Uri.parse("http://www.test.cn/music/m1.mp3"));

注:要在.xml文件中授予程序访问网络的权限,具体代码如下:

<users-permission android:name="android.permission.INTERNET"/>

3.对播放器的主要控制方法:

通过控制播放器的状态的方式来控制媒体文件的播放,其中:()和() 提供了同步和异步两种方式设置播放器进入状态

()

同步地为播放器的回放做准备。设置数据源和显示表面之后,需要调用()或()。对于文件,可以调用(),它会阻塞,直到准备好播放为止。

()

异步地为播放器的回放做准备。设置数据源和显示表面之后,需要调用()或()。对于流,应该调用(),它会立即返回,而不是阻塞,直到缓冲了足够的数据。

方法是将资源同步缓存到内存中,一般加载本地较小的资源可以用这个,如果是较大的资源或者网络资源建议使用方法

需要设置监听事件r();来通知资源已经获取到了,然后实现( mp)方法.在里面启动

videoView.setOnPreparedListener(p);
OnPreparedListener p = new OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.play();}
};

4.的监听事件

通常在新建一个实体后,会对给它增加需要的监听事件

1.2 的状态图和及生命周期

状态

Error状态

状态(初始化)

状态

同步方法:使用本地音视频文件,调用 () 同步的将 状态变为状态

异步方法:使用网络音视频,需要缓冲;调用 ()异步的将 状态变为 状态,最后再到状态 ,状态是个短暂的状态

状态是一个过渡状态( state),处于状态时,可以通过相对应的方法设置音量,屏幕常亮,播放循环等。

状态

状态

状态

2、类

提升音频效果的方法总体分为软件和硬件两大类。硬件如:HiFi耳机、、音源修复算法、音效算法等等。软件层面,可以大致分为基于音频数据流的处理方式以及基于的音效框架的处理方式。基于音频数据流的处理方式比较容易理解,基本原理就是先把数据丢给第三方的库进行处理,接着将处理完成的数据重新写入原有数据流的节点即可。这里主要探讨下基于的音效框架的处理方式。就是 audio ( 音频框架)

的具体效果作用在音频数据上,只管播放音频,二者通过(通过的()方法可以获得)关联起来。可以说,音效的处理对是透明的,具体的处理由框架进行。

2.1 是音效控制基类,开发者不应直接使用此类,应该使用它的派生类:

以上音效包含在.media.包中

当创建时,如果音频效果应用到一个具体的和的实例,应用程序必须指定该实例的音频 ID,如果要应用音频输出混响的效果必须制定 0.

要创建音频输出混响(音频 0)要求要有 S权限

2.2 : 重低音调节器 重低音调节器的用法

1. 初始化

private BassBoost mBass =new BassBoost(0, mMediaPlayer.audioSessionId)

第一个参数代表该音效控制器的优先级,这里设置为0,第二个参数仍然是的id

2. 启用

为了启用它们同样需要调用(true)方法

3. 调用相关方法

的常用方法如下:

2.3 环绕音

环绕音依赖于输入和输出通道的数量和类型,需要打开立体声通道。通过放置音源于不同的位置,环绕音完美地再现了声音的质感和饱满感。

1. 初始化

Virtualizer mVirtualizer= new Virtualizer (0, mMediaPlayer.getAudioSessionId()); //优先级为0

如果指定的会话ID为0,则作用于主要的音频输出混音器(mix)。

2. 启用

为了启用它们同样需要调用(true)方法

3. 调用相关方法

的常用方法如下:

Virtualizer mVirtualizer= new Virtualizer(0,mPlayer.getAudioSessionId()); //优先级为0if (mVirtualizer.getStrengthSupported()){
short strength = mVirtualizer.getRoundedStrength(); mVirtualizer.setStrength((short)strength);
}

2.4 均衡器

均衡器的原理:调整某一频率声音的分贝。所以我们在使用均衡器之前需要先获取当前系统支持的所有可调整的频率,例如有些手机目前仅支持60、230、910、3600、这些频率。

1. 初始化

Equalizer mEqualizer = new Equalizer(0, mPlayer.getAudioSessionId()); //优先级为0

2. 启用

为了启用它们同样需要调用(true)方法

3. 调用相关方法

的常用方法如下:

//获取能够设置的最小和最大分贝数

val = .[0]

val = .[1]

```

2.5 预设混响处理:

一个声音在产生后会往各个方向传播。如果这个声音是在室内产生的,接收方会首先听到音源本身发出的声音,然后听到来自墙壁、天花板和地板的回声。这些回声又会在传播到障碍物上时产生二次回声、三次回声…接收方会持续不断地听到声音,这每一次声音的辨识度越来越低,且响度随时间衰减。混响器()对于音频接收者的环境建模非常重要,它可以被用于模拟在不同环境中播放音乐产生的效果,或者在游戏中为玩家生成更加沉浸式的音频体验。APP 可以通过预设混响器提前配置全局的混响参数,这种方式在为音乐播放添加混响效果时被广泛使用。如果 APP 需要配置更高级的环境声混响参数,最好使用环境声混响器来实现。

1. 初始化

PresetReverb  mPresetReverb = new PresetReverb(0, mPlayer.getAudioSessionId());//同时要初始化一个均衡器和一个或多个List用于存储预设音场的名字和值

2. 启用

为了启用它们同样需要调用(true)方法

3. 获取所有预设名字()

4. 使用作为选择工具,并且在选择监听中使用均衡器(预设音场控制器只定义了音场,具体实现需要均衡器)

5. 设定音场

mEqualizer.usePreset(list.get(i))

2.6 环境声混响器:

如果想要有很好的混响效果可以使用

常用方法:

2.7 :示波器

示波器是用来显示波形的控件,但是这不是一个View,它只是提供了当前的波形信息(byte数组),我们需要自定义View去显示

首先需要一个权限

<uses-permission android:name="android.permission.RECORD_AUDIO"/>

有两个比较重要的方法

通过一个监听器来监听所采集的数据

mVisualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener(),Visualizer.getMaxCaptureRate() / 2, true, false){}

一共有4个参数,第一个参数是监听者,第二个参数表示的是采集的频率,第三个参数表示是否采集波形,第四个参数表示是否采集频率

r 有2个回调,一个用于显示FFT数据,展示不同频率的振幅,另一个用于显示声音的波形图

对的许多设置必须在之前完成

注意:并不能保证所有的设备都能支持这些效果的,所以应该首先调用在对应音频效果类上的()的方法来检测它的可用性。

例如:.();

上述三个子类的操作步骤:

3、类

在音频应用中使用淡入,淡出和交叉淡入淡出以及其他短暂的自动音量转换。类是在.0中新增的功能。

使用进行音量控制实际是通过 .来实现的。

3.1 .

.的三个参数

插补器类型

音量曲线始终通过指定的控制点,根据配置的内插器类型,控制点之间的值由样条曲线导出。

可用插补器类型有四个常量 :

持续时间

时间间隔[0.0,1.0]中的指定时间坐标缩放到指定的持续时间(以毫秒为单位)。这决定了运行时音量曲线的实际时间长度,并将曲线应用于音频输出。

3.2 使用

1.创建配置

在构建之前,必须创建一个实例.。

VolumeShaper.Configuration config =new VolumeShaper.Configuration.Builder().setDuration(3000).setCurve(new float[] {0.f, 1.f}, new float[] {0.f, 1.f}).setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR).build();

**如果没有参数,**..构造函数将返回一个构建器,该构建器使用默认设置创建一个配置:BIC,持续时间为1秒,并且不包含曲线。在调用之前,您必须向构建器添加曲线build()。

2.创建一个

要创建一个,调用(),传入.对象

volumeShaper = myMediaPlayer.createVolumeShaper(config);

不能在之间共享,但可以调用相同配置来创建多个应用于不同的

3.运行

​ 创建后,第一次调用apply()必须指定PLAY 操作进行启动

shaper.apply(VolumeShaper.Operation.PLAY);

改变曲线:使用()方法来更改曲线。

4、使用播放音频

由于占用资源较多,且不支持同时播放多个音频,所以还提供了另一个播放音频的类——。即音频池,可以同时播放多个短小的音频,如果超过流的最大数目,会基于优先级自动停止先前播放的流,而且占用的资源较少。另外还支持自行设置声音的品质、 音量、 播放比率等参数。

4.1 相对于的优点

适合短且对反应速度比较高的情况(游戏音效或按键声等),文件大小一般控制在几十K到几百K,最好不超过1M

可以与同时播放,也可以同时播放多个声音;

最终编解码实现与相同;

只能同时播放一个声音,加载文件有一定的时间,适合文件比较大,响应时间要是那种不是非常高的场景

4.2 的创建

的创建方式在不同版本中会有所不同,为了更好的兼容性,应该对API版本进行判断,再对应的进行创建。

在5.0以前,直接使用它的构造方法即可

SoundPool (int maxStreams, int streamType, int srcQuality)

而在这之后,则需要使用模式来创建

SoundPool.Builder spb = new SoundPool.Builder()
.setMaxStreams(16)
.setAudioAttributes (audioAttributes)
.build();

(音频属性)

AudioAttributes {mUsagemContentTypemSourcemFlagsmTags / mFormattedTags / mBundle (key value pairs)}

使用模式来构造

AudioAttributes attr = new AudioAttributes.Builder()      //设置音效相关属性.setUsage(AudioAttributes.USAGE_GAME)         // 设置音效使用场景.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)  // 设置音效的类型.build();

4.3 加载所要播放的音频

创建对象后,可以调用load()方法来加载要播放的音频。load()方法的语法格式有以下4种。

上述方法都会返回一个声音的ID,后面我们可以通过这个ID来播放指定的声音

:没什么用的一个参数,建议设置为1,保持和未来的兼容性

为了更好地管理所加载的每个音频,一般使用对象来管理这些音频。这时可以先创建一个对象,然后应用该对象的put()方法将加载的音频保存到该对象中。例如,创建一个对象,并应用put()方法添加一个音频

4.4 播放音频

调用对象的play()方法可播放指定的音频。

创建完 后,通过tener设置监听,用来监听资源加载完毕的事件发生。这主要是为了播放做准备.通过名字可猜测到, 当音频资源加载完成后,会回调设置的监听的方法, 在这个方法里, 可以进行播放音频

soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {@Overridepublic void onLoadComplete(SoundPool soundPool, int voiceId, int status) {if (status == 0) {
​          soundPool.play(voiceId, 1, 1, 1, 0, 1);}}});

4.5 播放控制

是对流的特定实例的引用,通过 的 pause\\stop 方法, 就可以对播放进行控制。

4.6 播放音量调节

通过 的 方法就可以设置指定 的流的左右声道的音量值

mSoundPool.setVolume(mStreamID, mCruLeftVolume, mCurRightVolume);

4.7 资源释放

通过 方法来卸载之前load的资源 , 并通过 方法释放占用的资源

4.8 注意事项

尽管 使用比较简单,但是还是有许多需要注意的地方:

5、类

是主要的视频播放View,它其实是对的再次封装; 底层仍然是使用 来对视频文件进行控制。

5.1 的基本操作步骤

首先需要在布局文件中添加该组件,然后在中获取该组件,并应用其()方法或()方法加载要播放的视频,最后调用start()方法来播放视频。另外,组件还提供了stop()和pause()方法,用于停止或暂停视频的播放。

在布局文件中添加 组件

基本语法格式:

<VideoView​    android:id="@+id/video_view"​    android:layout_width="wrap_content"​    android:layout_height="wrap_content"​    app:layout_constraintTop_toTopOf="parent"​    app:layout_constraintBottom_toBottomOf="parent"​    app:layout_constraintLeft_toLeftOf="parent"​    app:layout_constraintRight_toRightOf="parent"/>

2.调用的两个方法来加载指定视频。

  //获取raw下的文件   
videoView.setVideoURI(Uri.parse("android.resource:// lmh.example.exam1_6 /" + R.raw.video));//获取外部存储下的文件   
videoView.setVideoPath(Environment.getExternalStorageDirectory() + "/big_buck.mp4");//     访问网络视频   
videoView.setVideoPath("http://www.test.com/big_buck.mp4");

3.调用的start()、stop()、pause()方法来控制视频播放。

5.2 组件

是封装的辅助控制器,带有暂停,播放,停止,进度条等控件。通过+可以很轻松的通过图形控制界面实现视频播放、停止、快进、快退等功能。

注意: 和只能同时调用其中一个方法。

6、使用 和播放视频 6.1

继承之View,但拥有独立的绘制表面,即它不与其宿主窗口共享同一个绘图表面,可以单独在一个线程进行绘制,并不会占用主线程的资源。这样,绘制就会比较高效,游戏,视频播放,还有最近热门的直播,都可以用

和普通View的区别

6.2

public SurfaceHolder getHolder()   

6.3 与结合

的作用:

双缓冲

​ 内部实现了双缓冲的机制,但是实现这个功能是非常消耗系统内存的。因为移动设备的局限性,在设计的时候规定,如果为用户可见的时候,创建的用于显示视频流解析的帧图片,如果发现变为用户不可见的时候,则立即销毁的,以达到节约系统资源的目的。

​ 如果开发人员不对进行维护,会出现最小化程序后,再打开应用的时候,视频的声音在继续播放,但是不显示画面了的情况,这就是因为当不被用户可见的时候,之前的已经被销毁了,再次进入的时候,界面上的已经是新的了。所以需要我们开发人员去编码维护,维护需要用到它的一个回调,.(),它需要实现三个如下三个方法:

以下是这三个方法的调用的过程,在应用中分别为实现了这三个方法,先进入应用,被创建,创建好之后会改变的大小,然后按Home键回退到桌面销毁,最后再进入应用,重新并改变其大小。

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了