android之ExoPlayer探索

播放视频和音乐是Android设备上的热门活动。 Android框架提供了MediaPlayer作为以最少代码播放媒体的快速解决方案。 它还提供低级媒体API,如MediaCodec,AudioTrack和MediaDrm,可用于构建自定义媒体播放器解决方案。

一:ExoPlayer简介

ExoPlayer是一个开源的应用程序级媒体播放器,构建在Android的低级媒体API之上。 它提供了Android的MediaPlayer API的替代方法,用于在本地和通过Internet播放音频和视频。 ExoPlayer支持Android的MediaPlayer API目前不支持的功能,包括DASH和SmoothStreaming自适应播放。 与MediaPlayer API不同,ExoPlayer易于自定义和扩展,并且可以通过Play商店应用程序更新进行更新。


二:ExoPlayer支持的格式:

MP4,M4A,FMP4,WebM,MKV,MP3,Ogg,WAV,MPEG-TS,MPEG-PS,FLV和ADTS AAC


三:ExoPlayer优缺点

ExoPlayer具有许多优于Android内置的MediaPlayer的优点:

支持通过HTTP的动态自适应流(DASH)和SmoothStreaming,MediaPlayer不支持这两种格式。还支持许多其他格式。有关详情,请参阅支持的格式页面。
支持高级HLS功能,如正确处理#EXT-X-DISCONTINUITY标记。
无缝合并,连接和循环媒体的能力。
自定义和扩展播放器以适应您的用例的能力。 ExoPlayer是专门为此而设计的,允许许多组件被自定义实现替代。
轻松更新播放器以及您的应用程序。因为ExoPlayer是您在应用程序apk中包含的库,您可以控制使用哪个版本,并且您可以轻松地更新到较新版本作为常规应用程序更新的一部分。
更少的设备特定问题。
支持Android 4.4(API级别19)及更高版本上的Widevine常用加密。


重要的是要注意,还有一些缺点:

ExoPlayer的标准音频和视频组件依赖于Android的MediaCodec API,它是在Android 4.1(API级别16)中发布的。因此,他们不在早期版本的Android上工作。 Widevine通用加密适用于Android 4.4(API级别19)及更高版本。

四:库概述

ExoPlayer库的核心是ExoPlayer接口。 ExoPlayer公开了传统的高级媒体播放器功能,例如缓冲媒体,播放,暂停和搜索的能力。实现被设计为对所播放的媒体的类型(如何以及在何处被存储以及如何被呈现)进行少量假设(并且因此对其施加少许限制)。而不是直接实现媒体的加载和呈现,ExoPlayer实现将这项工作委托给在创建播放器或准备播放时注入的组件。所有ExoPlayer实现共同的组件有:

定义要播放的媒体,加载媒体以及从中可读取加载的媒体的MediaSource。在播放开始时通过ExoPlayer.prepare注入MediaSource。
呈现媒体的各个组件的渲染器。渲染器在创建播放器时注入。
TrackSelector,用于选择MediaSource提供的由每个可用渲染器使用的轨道。创建播放器时注入TrackSelector。
LoadControl控制MediaSource何时缓冲更多介质,以及缓冲多少介质。创建播放器时会注入LoadControl。
该库为常见用例提供这些组件的默认实现,如下面更详细描述的。 ExoPlayer可以使用这些组件,但如果需要非标准行为,也可以使用自定义实现构建。例如,可以注入自定义LoadControl来更改播放器的缓冲策略,或者可以注入自定义渲染器以使用Android本机不支持的视频编解码器。

注入实现播放器功能的组件的概念存在于整个库中。上面列出的组件的默认实现将工作委托给进一步注入的组件。这允许许多子组件被单独地替换为定制实现。例如,默认的MediaSource实现需要一个或多个DataSource工厂通过它们的构造函数注入。通过提供自定义工厂,可以从非标准源或通过不同的网络堆栈加载数据。

五:将ExoPlayer添加到项目依赖中

1. ExoPlayer发布在Jcenter上。所以需要在项目根目录的build.gralde文件中添加如下代码:

respositories{

          jcenter(); 

}

ExoPlayer对应的gradle地址如下:

compile 'com.google.android.exoplayer:exoplayer:r2.X.X'
其中r2.X.X是您的首选版本。 有关最新版本,请参阅项目的版本。 有关更多详细信息,请参阅Bintray上的项目。
2. 创建SimpleExoPlayer实例

使用ExoPlayerFactory创建一个ExoPlayer实例。ExoPlayerFactory提供了一系列方法来创建具有不同级别的自定义的ExoPlayer实例。对于绝大多数使用情况,库提供的默认Renderer实现就足够了。对于这种情况,应该使用 ExoPlayerFactory.newSimpleInstance方法之一。这些方法返回SimpleExoPlayer,它扩展了ExoPlayer以添加额外的高级别播放器功能。下面的代码是创建SimpleExoPlayer的示例。

// 1.创建一个默认TrackSelector
Handler mainHandler = new Handler();
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveVideoTrackSelection.Factory(bandwidthMeter);
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);

// 2.创建一个默认的LoadControl
LoadControl loadControl = new DefaultLoadControl();

// 3.创建播放器
SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(context,trackSelector,loadControl);

3. 将player关联到View上

ExoPlayer库提供了一个SimpleExoPlayerView,它封装了一个PlaybackControlView和一个Surface渲染视频。 SimpleExoPlayerView可以包含在应用程序的布局xml中。 将播放器绑定到视图的过程非常简单:

simpleExoPlayerView.setPlayer(player);

如果需要对播放器控件和渲染视频的Surface进行细粒度控制,则可以分别使用SimpleExoPlayer的setVideoSurfaceViewsetVideoTextureViewsetVideoSurfaceHoldersetVideoSurface方法直接设置播放器的目标SurfaceView,TextureView,SurfaceHolder或Surface。 您可以使用PlaybackControlView作为独立组件,或实现自己的播放控件,直接与播放器交互。 setTextOutputsetId3Output可用于在播放期间接收字幕和ID3元数据输出。

4.准备player

在ExoPlayer中,每个媒体由MediaSource表示。要播放一个媒体,您必须先创建一个相应的MediaSource,然后将此对象传递给ExoPlayer.prepare。 ExoPlayer库为DASH(DashMediaSource),SmoothStreaming(SsMediaSource),HLS(HlsMediaSource)和常规媒体文件(ExtractorMediaSource)提供MediaSource实现。这些实现在本指南后面更详细地描述。以下代码显示如何使用适合播放MP4文件的MediaSource准备播放器。

// Measures bandwidth during playback. Can be null if not required.
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
// Produces DataSource instances through which media data is loaded.
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(this,
    Util.getUserAgent(this, "yourApplicationName"), bandwidthMeter);
// Produces Extractor instances for parsing the media data.
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
// This is the MediaSource representing the media to be played.
MediaSource videoSource = new ExtractorMediaSource(mp4VideoUri,
    dataSourceFactory, extractorsFactory, null, null);
// Prepare the player with the source.
player.prepare(videoSource);
当ExoPlayer准备就绪后,我们可以通过player控制视频的播放、前进或后退。

5.释放资源

当你不需要player时,可以通过调用ExoPlayer.release来释放资源。

六:MediaSource

在ExoPlayer中,每个媒体由MediaSource表示。 ExoPlayer库为DASH(DashMediaSource),SmoothStreaming(SsMediaSource),HLS(HlsMediaSource)和常规媒体文件(ExtractorMediaSource)提供MediaSource实现。 如何实例化所有四个示例可以在ExoPlayer演示应用程序中的PlayerActivity中找到。

除了上面描述的MediaSource实现之外,ExoPlayer库还提供MergingMediaSource,LoopingMediaSource和ConcatenatingMediaSource。 这些MediaSource实现通过组合实现更复杂的回放功能。 一些常见的用例如下所述。 注意,虽然在视频回放的上下文中描述了以下示例,但是它们同样适用于仅音频回放,并且实际上也适用于任何支持的媒体类型的回放。


  1. 合并视频和字幕
  给定视频文件和单独的字幕文件,MergingMediaSource可以用于将它们合并成单个源以供回放。
   
   
MediaSource videoSource = new ExtractorMediaSource(videoUri, dataSourceFactory, extractorsFactory, null, null );
Format format = Format.createTextSampleFormat( null , MimeTypes.APPLICATION_TTML, null , Format.NO_VALUE,
Format.NO_VALUE, "en" , null );
MediaSource subtitleSource = new SingleSampleMediaSource(subtitleUri, dataSourceFactory, format, C.TIME_UNSET);
MergingMediaSource mergedSource = new MergingMediaSource(videoSource, subtitleSource);
2.循环播放视频
视频可以使用LoopingMediaSource无缝地循环。以下示例无限期循环视频,也可以在创建LoopingMediaSource时
指定有限循环计数
   
   
MediaSource source = new ExtractorMediaSource(videoUri, ...);
// Loops the video indefinitely.
LoopingMediaSource loopingSource = new LoopingMediaSource(source);
// Plays the video twice.
LoopingMediaSource loopingSource = new LoopingMediaSource(source, 2 );
3.连续播放视频
ConcatenatingMediaSource 支持顺序播放两个或多个单独的MediaSource。 以下示例依次播放两个视频。
源之间的转换是无缝的。 没有要求被连接的源是相同的格式(例如,连接包含480p H264的视频文件和包含720p VP9的
视频文件)。 源甚至可以是不同类型(例如,将视频与仅音频流串接在一起)。
MediaSource firstSource = new ExtractorMediaSource(firstVideoUri, ...);
MediaSource secondSource = new ExtractorMediaSource(secondVideoUri, ...);
// Plays the first video, then the second video.
ConcatenatingMediaSource concatenatedSource = new ConcatenatingMediaSource(firstSource,
secondSource);
七:Advanced composition
有可能进一步结合复合MediaSources用于更多不寻常的用例。 给定两个视频A和B,以下示例显示如何将
LoopingMediaSource和ConcatenatingMediaSource一起使用以无限地循环序列(A,A,B)。
MediaSource firstSource = new ExtractorMediaSource(firstVideoUri, ...);
MediaSource secondSource = new ExtractorMediaSource(secondVideoUri, ...);
// Plays the first video twice.
LoopingMediaSource firstSourceTwice = new LoopingMediaSource(firstSource, 2);
// Plays the first video twice, then the second video.
ConcatenatingMediaSource concatenatedSource =
    new ConcatenatingMediaSource(firstSourceTwice, secondSource);
// Loops the sequence indefinitely.
LoopingMediaSource compositeSource = new LoopingMediaSource(concatenatedSource);
以下示例是等效的,表明可以有多种方式实现相同的结果。
MediaSource firstSource = new ExtractorMediaSource(firstVideoUri, ...);
MediaSource secondSource = new ExtractorMediaSource(secondVideoUri, ...);
// Plays the first video twice, then the second video.
ConcatenatingMediaSource concatenatedSource =
    new ConcatenatingMediaSource(firstSource, firstSource, secondSource);
// Loops the sequence indefinitely.
LoopingMediaSource compositeSource = new LoopingMediaSource(concatenatedSource);
重要的是,避免在组合中多次使用相同的MediaSource实例,除非根据文档明确允许。 在上面的示例中使用firstSource两次
是一个这样的情况,因为ConcatenatingMediaSource的Javadoc显式地声明允许重复条目。 然而,一般来说,由组合物形
成的对象的图应该是树。 允许在合成中使用多个等效的MediaSource实例。
八:事件监听
ExoPlayer提供了一个ExoPlay.EventListener这一接口,通过addListener和removeListener可以添加和删除相关接口。这个接
口可以监听player状态的更改,提供的方法如下。除此以外,SimpleExoPlayer提供了setVideoListener负责接收与视频渲
染 有关的事件,setVideoDebugListenersetAudioDebugListener用于调试信息。

1.事件回调(High Level Event)

ExoPlayer提供了一个ExoPlay.EventListener这一接口,通过addListener和removeListener可以添加和删除相关接口。这个接
口可以监听player状态的更改,提供的方法如下。除此以外,SimpleExoPlayer提供了setVideoListener负责接收与视频渲染
有关的事件setVideoDebugListenersetAudioDebugListener用于调试信息。
2.Handler(Low Level Event)
通过调用ExoPlayer.void sendMessages(ExoPlayerMessage... )
ExoPlayer.void blockingSendMessages(ExoPlayerMessage... messages)实现和ExoPlayer交互,再由内部的Handler
进行消的分发和处理。其实,在具体实现上,回调是通过Handler.handleMessage(Message)实现的,两者在实现上是一
样的。

九:使用Stetho对ExoPlayer进行网络调试

Stetho是FaceBook出品的Android调试利器,在它的配合下,可以使用Chrome进行调试。当然,ExoPlayer也支持Stetho调试,开启方式如下:

1.实现添加相关库依赖

由于ExoPlayer的数据读取是由接口com.google.android.exoplayer2.upstream.DataSource实现的,这里的我们采用的类

com.google.android.exoplayer2.ext.okhttp.OkHttpDataSourceFactory,所以需要添加如下依赖

        
        
compile 'com.google.android.exoplayer:extension-okhttp:r2.1.1'
compile 'com.squareup.okhttp3:okhttp:3.5.0'
compile 'com.facebook.stetho:stetho:1.4.2'
compile 'com.facebook.stetho:stetho-okhttp3:1.4.2'

2.网络和Stetho的初始化

通过Stetho.initializeWithDefaults(Context)完成Stetho的初始化。
创建OkHttpClient,并添加StethoInterceptor到NetworkInterceptor

        
        
Stetho.initializeWithDefaults( this );
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addNetworkInterceptor( new StethoInterceptor())
.build();

3.创建OkHttpDataSource

        
        
DataSource.Factory dataSourceFactory =
new OkHttpDataSourceFactory(okHttpClient, userAgent, bandwidthMeter);

4.查看调试结果

打开chrome://inspect,我们就可以在Developer ToolsNetwork部分查看到相关的调试结果:




 


  • 15
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ExoPlayer是一个开源的Android音视频播放器,由Google开发和维护。它支持多种音视频格式、网络协议和多种数据源,可以满足各种应用场景的需求。下面是使用ExoPlayer进行音视频播放的基本步骤: 1. 添加ExoPlayer库依赖 在项目的build.gradle中添加以下依赖库: ``` implementation 'com.google.android.exoplayer:exoplayer-core:2.14.0' implementation 'com.google.android.exoplayer:exoplayer-dash:2.14.0' // 适用于DASH格式视频 implementation 'com.google.android.exoplayer:exoplayer-ui:2.14.0' // 可选依赖,提供了默认的播放器UI组件 ``` 2. 创建ExoPlayer实例 在需要播放视频的Activity或Fragment中创建ExoPlayer实例: ``` SimpleExoPlayer player = new SimpleExoPlayer.Builder(context).build(); ``` 3. 准备媒体资源 准备需要播放的媒体资源,可以是本地文件或网络地址。如果是网络资源,需要使用ExtractorMediaSource或DashMediaSource进行数据源的构建: ``` MediaItem mediaItem = MediaItem.fromUri(uri); // uri为需要播放的资源地址 player.setMediaItem(mediaItem); player.prepare(); ``` 4. 开始播放 调用ExoPlayer的start方法即可开始播放: ``` player.play(); ``` 5. 暂停和停止播放 可以通过pause和stop方法实现暂停和停止播放: ``` player.pause(); player.stop(); ``` 6. 释放资源 在Activity或Fragment的生命周期中,需要在onDestroy或onDestroyView方法中释放ExoPlayer资源: ``` player.release(); ``` 以上就是使用ExoPlayer进行音视频播放的基本步骤。需要注意的是,ExoPlayer在播放过程中可能会抛出各种异常,需要在代码中进行处理。同时,ExoPlayer还提供了丰富的参数配置和事件监听接口,可以根据具体需求进行配置和使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值