注意解决目前http直接发送请求失败的问题:
(Cleartext HTTP traffic to xxx not permitted)
https://blog.csdn.net/qq_32534441/article/details/103529449

相关教程网站:
https://google.github.io/ExoPlayer/guide.html

前言

播放视频和音乐是Android开发中很常见的需求。 Android框架提供了MediaPlayer这个类,能够用最少代码实现多媒体播放。同时,Android还提供偏底层的多媒体API,比如MediaCodec、AudioTrack和MediaDrm,可用于构建自定义媒体播放器解决方案。

ExoPlayer是google开源的应用级媒体播放器项目,构建在Android的底层多媒体API之上。该开源项目包含ExoPlayer库和演示demo,github地址:https://github.com/google/ExoPlayer

优缺点

与Android内置的MediaPlayer相比,ExoPlayer具有许多优点:

  • 支持通过HTTP(DASH)和SmoothStreaming进行动态自适应流,这两种都不受MediaPlayer的支持。还支持许多其他格式。有关详细信息,请参阅支持的格式页

  • 能够自定义和扩展播放器,以适应各种不同需求。 ExoPlayer专门设计了这一点,大部分组件都可以自己替换

  • 官网说了很多,其实说到底最主要的就是各个组件可以自定义,还可以接入ffmpeg组件,基本能满足99.9%的需求

缺点:

  • 缺点就是这个开源库是基于Android4.1种的MediaCodec组件、Android4.4种的Widevine组件,所以最低支持版本是4.4

Library概述

ExoPlayer库的核心是ExoPlayer接口,ExoPlayer公开了传统的高级媒体播放器功能,例如缓冲媒体,播放,暂停和seek等功能。在具体实现方面,该开源库对播放的媒体类型、存储方式、位置、渲染方式等进行了最少的实现,旨在让开发者自定义各种特性。ExoPlayer实现不是直接实现加载和呈现媒体,而是将这项工作委托给各种组件。 所有ExoPlayer共同的组件有:

  • MediaSource:定义多媒体数据源,这个类的功能就是从Uri中读取多媒体文件的二进制数据。 MediaSource在播放开始时通过ExoPlayer.prepare注入

  • TrackSelector:轨道提取器,从MediaSource中提取各个轨道的二进制数据,交给Renderer渲染。创建播放器时初注入

  • Renderer:对多媒体中的各个轨道(音轨、视频轨、字幕轨等)数据进行渲染,渲染就是“播放”,把二进制文件渲染成声音、画面。 创建播放器时注入

  • LoadControl:对MediaSource进行控制,比如什么时候开始缓冲、缓冲多少等等。创建播放器时注入

该库为提供了这些组件的默认实现,能够满足大部分需求,如果有特殊需求,可以通过自定义组件来实现。 比如,可以自定义LoadControl来更改播放器的缓冲策略,或自定义Renderer来渲染Android本身不支持的编解码器。

整个库中都存在注入组件的概念,许多子组件都能单独替换成自定义组件,而不会影响整个流程。 例如,默认的MediaSource实现需要通过其构造函数注入一个或多个DataSource工厂, 通过提供自定义Factory,可以从非标准源或不同的网络堆栈加载数据。

入门

实现一个最简单的播放器,需要如下流程:

  1. 添加ExoPlayer库作为依赖
  2. 创建一个SimpleExoPlayer实例
  3. 将播放器连接到UI,用于视频输出和用户输入(也就是放在某个Activity中)
  4. 准备播放器,传入MediaSource作为多媒体源
  5. 播放完成后释放

这些步骤在下面更详细地概述。完整的示例可以参考demo(github地址:https://github.com/google/ExoPlayer)中的PlayerActivity。

添加ExoPlayer作为依赖

第一步是确保项目根目录中的build.gradle文件中包含jcenter仓库:

repositories {jcenter()google()
}

然后在应用app模块的build.gradle文件中添加ExoPlayer库的依赖:

    implementation 'com.google.android.exoplayer:exoplayer:2.6.0'implementation 'com.google.android.exoplayer:exoplayer-core:2.6.0'//(这里解释一下DASH(Dynamic Adaptive Streaming over HTTP)即自适应流媒体传输,什么意思呢,简单概括来说,就是在服务器端提前存好同一内容的不同码率、不同分辨率的多个分片以及相应的描述文件MPD,客户端在播放时即可以根据自身性能以及网络环境选择最适宜的版本)implementation 'com.google.android.exoplayer:exoplayer-dash:2.6.0'implementation 'com.google.android.exoplayer:exoplayer-ui:2.6.0'

不要忘记在AndroidManifest中添加网络权限:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"<uses-permission android:name="android.permission.INTERNET" />
</manifest>

创建播放器

使用ExoPlayerFactory创建一个ExoPlayer实例, 该Factory提供了一系列方法来创建各种定制ExoPlayer实例。 大部分情况下,使用ExoPlayerFactory.newSimpleInstance方法之一即可, 这些方法返回SimpleExoPlayer,它实现了ExoPlayer以添加额外的高级别播放器功能。 下面是创建SimpleExoPlayer的示例:

// step1. 创建一个默认的TrackSelector
Handler mainHandler = new Handler();// 创建带宽
BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();// 创建轨道选择工厂
TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);// 创建轨道选择器实例
TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);//step2. 创建播放器
SimpleExoPlayer player = ExoPlayerFactory.newSimpleInstance(context, trackSelector);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

使用SimpleExoPlayer的setVideoSurfaceView、setVideoTextureView、setVideoSurfaceHolder和setVideoSurface方法设置播放器的目标SurfaceView、TextureView、SurfaceHolder或Surface。

准备播放器

在ExoPlayer中,每一个多媒体文件均由MediaSource表示,要播放一个多媒体,您必须先创建一个相应的MediaSource实例,然后将此实例传递给ExoPlayer.prepare。 ExoPlayer库为DASH(DashMediaSource),SmoothStreaming(SsMediaSource),HLS(HlsMediaSource)和常规媒体文件(ExtractorMediaSource)提供了默认MediaSource实现,这些实现将在本指南的后面更详细地描述。 下面的代码演示如何播放一个mp4文件:

// 测量播放带宽,如果不需要可以传null
DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();// 创建加载数据的工厂
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context,Util.getUserAgent(context, "yourApplicationName"), bandwidthMeter);// 创建解析数据的工厂
ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();// 传入Uri、加载数据的工厂、解析数据的工厂,就能创建出MediaSource
MediaSource videoSource = new ExtractorMediaSource(mp4VideoUri,dataSourceFactory, extractorsFactory, null, null);// Prepare
player.prepare(videoSource);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

播放器准备好后,可以通过各种方法来控制播放。 例如,setPlayWhenReady启动和暂停播放,seekTo方法控制进度。

退出时通过ExoPlayer.release释放播放器,释放硬件资源。

MediaSource

在ExoPlayer中,每个多媒体均由MediaSource表示, ExoPlayer库为DASH(DashMediaSource)、SmoothStreaming(SsMediaSource)、HLS(HlsMediaSource)和常规媒体文件(ExtractorMediaSource)提供了默认实现。 github上的demo中,可以在PlayerActivity中找到实例化所有四个示例。

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

加载字幕文件

给出一个视频文件和一个单独的字幕文件,MergingMediaSource可以用于将它们合并到单个源中进行播放:

// 创建视频源
MediaSource videoSource = new ExtractorMediaSource(videoUri, ...);
// 创建字幕源
MediaSource subtitleSource = new SingleSampleMediaSource(subtitleUri, ...);
// 把视频和字幕合并
MergingMediaSource mergedSource = new MergingMediaSource(videoSource, subtitleSource);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

循环播放单个视频

使用LoopingMediaSource可以使视频无缝循环播放多次。 以下示例播放视频5次:

MediaSource source = new ExtractorMediaSource(videoUri, ...);
// 播放5次
LoopingMediaSource loopingSource = new LoopingMediaSource(source, 5);
  • 1
  • 2
  • 3

循环播放视频列表

ConcatenatingMediaSource可以连续播放两个或多个单独的MediaSource。 以下示例依次播放两个视频。 源之间的转换是无缝的,每个视频源可以是不同格式(例如,可以将480p H264的视频文件与720p VP9的视频文件连接在一起),可以是不同的类型(例如,将视频与仅音频流连接):

MediaSource firstSource = new ExtractorMediaSource(firstVideoUri, ...);
MediaSource secondSource = new ExtractorMediaSource(secondVideoUri, ...);
// 连接多媒体source
ConcatenatingMediaSource concatenatedSource =new ConcatenatingMediaSource(firstSource, secondSource);
  • 1
  • 2
  • 3
  • 4
  • 5

进一步组合MediaSource

可以进一步将复杂的MediaSources组合在一起。比如,给定两个视频A和B,以下示例显示了如何一起使用LoopingMediaSource和ConcatenatingMediaSource来播放序列(A,A,B):

MediaSource firstSource = new ExtractorMediaSource(firstVideoUri, ...);
MediaSource secondSource = new ExtractorMediaSource(secondVideoUri, ...);
// 第一个source播放两次
LoopingMediaSource firstSourceTwice = new LoopingMediaSource(firstSource, 2);
// 把第一个source和firstSourceTwice连接起来
ConcatenatingMediaSource concatenatedSource =new ConcatenatingMediaSource(firstSourceTwice, secondSource);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

下面的示例也可以得到相同的结果:

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);
  • 1
  • 2
  • 3
  • 4
  • 5

事件监听

播放期间,可以监听由ExoPlayer生成的事件,指示播放器的整体状态。 这些事件可用作更新用户界面(如播放控件)的触发器。 许多ExoPlayer组件还报告自己的组件特定的底层事件,可以用来监听性能。

上层事件

ExoPlayer通过addListener/removeListener方法添加/删除ExoPlayer.EventListener的实例, 监听者能够监听到播放状态的变化,以及播放失败的事件。

使用SimpleExoPlayer时,可以在播放器上设置其他侦听器。 比如,setVideoListener允许应用程序接收与视频渲染有关的事件,这些事件可能对于调整UI(例如,一个特定宽高比的视频被渲染到surface上了)有用。 可以在SimpleExoPlayer上设置其他侦听器来接收调试信息,例如调用setVideoDebugListener和setAudioDebugListener。

底层事件

除了上层监听外,ExoPlayer库提供的许多单独的组件允许自己的事件监听器。 通常需要将Handler对象传递给这些组件,这些Handler决定侦听器方法将在哪个线程调用,所以在大多数情况下,应该使用主线程的Handler。

向组件发送消息

一些组件允许在播放过程中更改配置。 一般来说,可以通过sendMessages或blockingSendMessages方法将消息通过ExoPlayer传递到组件来进行更改。 这种方法确保了线程安全,更改配置的操作与ExoPlayer上的其它事件一样,需要按顺序执行。

自定义

ExoPlayer与MediaPlayer的主要优点之一是可以自定义和扩展播放器,以更好地适应开发人员使用。 ExoPlayer库专门设计了这一点,定义了一些接口和抽象基类,使应用程序开发人员可以轻松地替换库提供的默认实现。 以下是构建自定义组件的一些case:

  • Renderer:可以自定义Renderer来处理默认实现不支持的多媒体格式

  • TrackSelector:自定义TrackSelector可以更改从MediaSource中提取轨道的方式

  • LoadControl:自定义LoadControl可以更改播放器的缓冲策略

  • Extractor:如果需要支持默认库不支持的容器格式,可以自定义Extractor类,然后可以将其与ExtractorMediaSource一起使用,以播放容器格式的多媒体

  • MediaSource:如果希望获取媒体样本以自定义方式提供给渲染器,或者希望实现自定义MediaSource合成行为,则实现自定义MediaSource类可能是适当的

  • DataSource:ExoPlayer库已经包含了许多不同情况的DataSource实现。您可能希望实现自己的DataSource类,以其他方式加载数据,比如通过自定义协议,使用自定义HTTP堆栈或从自定义持久缓存加载数据。

自定义指南

如果自定义组件需要将事件报告回应用程序,我们建议您使用与现有ExoPlayer组件相同的模型,其中将事件侦听器与Handler一起传递到组件的构造函数。

我们建议自定义组件使用与现有ExoPlayer组件相同的模型,以便在播放过程中可以方便地重新配置,请参考上面“向组件发送消息”章节。 为此,您应该实现一个ExoPlayerComponent并在其handleMessage方法中接收配置更改消息。 您的应用程序应通过调用ExoPlayer的sendMessages和blockingSendMessages方法来传递配置更改。

以下转自:
ExoPlayer基本使用和关键类流程

public class MainActivity extends AppCompatActivity {private final String testUrl="http://2449.vod.myqcloud.com/2449_22ca37a6ea9011e5acaaf51d105342e3.f20.mp4";SimpleExoPlayer mPlayer;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);initExoPlayer();}private void initExoPlayer() {RenderersFactory renderersFactory=new DefaultRenderersFactory(this);DefaultTrackSelector trackSelector=new DefaultTrackSelector();LoadControl loadControl=new DefaultLoadControl();mPlayer= ExoPlayerFactory.newSimpleInstance(renderersFactory, trackSelector,loadControl);SimpleExoPlayerView playerView=new SimpleExoPlayerView(this);playerView.setPlayer(mPlayer);setContentView(playerView);Uri mp4Uri=Uri.parse(testUrl);DefaultDataSourceFactory dataSourceFactory=new DefaultDataSourceFactory(this, Util.getUserAgent(this,"exoPlayerTest"));ExtractorsFactory extractorsFactory=new DefaultExtractorsFactory();MediaSource mediaSource=new ExtractorMediaSource(mp4Uri,dataSourceFactory,extractorsFactory,null,null);mPlayer.prepare(mediaSource);}@Overrideprotected void onDestroy() {mPlayer.release();super.onDestroy();}
}

#关键类流程图

如果对播放器原理完全不理解的同学可以看下此文章: https://www.jianshu.com/p/82e778eb618b

ExoPlayer开发指南(官方文档翻译)相关推荐

  1. WatchKit-Programming-Guide-Apple-Watch开发指南官方翻译及总结

    鉴于CSDN的Markdown很多bug,大家请看这里: WatchKit-Programming-Guide-Apple-Watch开发指南官方翻译及总结 Overview ### Developi ...

  2. [iOS]Advanced Memory Management Programming Guide 高级内存管理编程指南(官方文档翻译)

    Advanced Memory Management Programming Guide - 高级内存管理编程指南(官方文档翻译) 版权声明:本文为博主原创翻译,如需转载请注明出处. 新博客文章地址: ...

  3. OpenGL ES 苹果编程指南 官方文档翻译01

    OpenGL ES Programming Guide for iOS 文章源地址(英文):https://developer.apple.com/library/ios/#documentation ...

  4. UIControl事件---iOS-Apple苹果官方文档翻译

    本系列所有开发文档翻译链接地址: iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译PDF下载地址 UIControl事件1.UIControlEventTouchDown 单点触摸按 ...

  5. UIPageControl---iOS-Apple苹果官方文档翻译

    本系列所有开发文档翻译链接地址:iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译PDF下载地址 //转载请注明出处--本文永久链接:http://www.cnblogs.com/Ch ...

  6. iOS程序启动原理---iOS-Apple苹果官方文档翻译

    本系列所有开发文档翻译链接地址:iOS7开发-Apple苹果iPhone开发Xcode官方文档翻译PDF下载地址 //转载请注明出处--本文永久链接:http://www.cnblogs.com/Ch ...

  7. Hermez官方文档翻译(二)开发者-开发指南

    文章目录 开发者 开发指南 概述 账户 交易 L1交易 L1 User 交易 L1协调器交易 L2 交易 Forging 锻造 共识 资金分配 保护机制 L1/L2 Batches 协调器替代 Boo ...

  8. Quartz.net官方开发指南 第十课: 配置、资源使用以及SchedulerFactory

    Quartz以模块方式构架,因此,要使它运行,几个组件必须很好的咬合在一起.幸运的是,已经有了一些现存的助手可以完成这些工作. 在Quartz进行工作之前需要被配置的组件主要有: • ThreadPo ...

  9. Go官方库RPC开发指南

    Go官方提供了一个RPC库: net/rpc.包rpc提供了通过网络访问一个对象的方法的能力.服务器需要注册对象, 通过对象的类型名暴露这个服务.注册后这个对象的输出方法就可以远程调用,这个库封装了底 ...

最新文章

  1. java springboot b2b2c shop 多用户商城系统源码 (二): 配置管理...
  2. caioj 1066 动态规划入门(一维一边推4:护卫队)(分组型dp总结)
  3. java中treemap释放_在Java中从TreeMap删除键
  4. 【MySQL】事务隔离级别
  5. 华强北突围:比特币挖矿机成了最赚钱的生意
  6. awk 匹配_20分钟降服awk
  7. php的auth权限类源码
  8. MySql 数据类型 - 整型
  9. Ubuntu 10.10 下安装spoonwep-wpa工具
  10. 华为 荣耀 等手机解锁BootLoader
  11. 散热风扇是吹风还是吸风,配电柜电气柜机柜散热风扇的原理。
  12. 岁月温柔-23 妈妈转到省医院第3天 突然icu有床位了
  13. C++层次分析法一致性检验
  14. 嵌入式Linux为Qt定制keymap
  15. 赵丽颖冯绍峰官宣 | 微博服务器瘫痪!运维:该拿什么拯救我?
  16. 微信头像挂件来了,想在头像加什么就来加什么吧!
  17. Java 生成13位条形码 Ean-13码规则:第十三位数字是前十二位数字经过计算得到的校验码。
  18. 读《枪炮,病菌和钢铁》
  19. 中国物联网微控制器市场现状研究分析与发展前景预测报告(2022)
  20. 用MySQL模拟消息队列

热门文章

  1. FPGA云原生 Mailbox通信
  2. 【论文写作】图像分割学术论文中常用词汇记录
  3. 深入解读小间距led显示屏的未来发展应该何去何从?
  4. 【VScode】前端必备插件(持续补充中...)
  5. 夸西莫多的一首短诗--《瞬息间是夜晚》
  6. Java-使数值不使用科学计数法
  7. 了解Joomla-模板目录结构
  8. joomla模板(joomla模板框架)
  9. 网络营销十技--SEO 之外的网络营销手法(九)
  10. 【AUTOSAR-COM】-9.1-Tx/Rx Ipdu两种处理模式:IMMEDIATE和DEFERRED详解