播放视频和音乐是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部分查看到相关的调试结果:



   


更多相关文章

  1. Android--Android四大组件(一)(Android studio)
  2. 最简单的基于FFmpeg的移动端例子:Android 视频解码器
  3. Android 用Mediacodec硬解码视频包AVpacket
  4. Android开发视频教程-深入浅出系列Lesson20-AFF111029学习Androi
  5. android的多媒体数据库
  6. Android视频开发浅析
  7. android 横竖屏切换属性和播放视频全屏切换

随机推荐

  1. Android(安卓)之布局
  2. Android(安卓)View系统解析(上)
  3. 项目中那些事|控件之TextView
  4. 保持长宽比 对背景图像进行修改android:s
  5. 25个你应该阅读的Android网站
  6. android最佳实践(三)
  7. Android(安卓)添加按钮
  8. android 让一个控件按钮居于底部的几种方
  9. android 五种数据存储之使用ContentProvi
  10. Android菜鸟日记17-SeekBar的图片效果