ExoPlayer MediaSource 深入解析:从 MediaItem 到媒体源工厂与播放列表 API

发布时间:2026/9/20 11:54:51
ExoPlayer MediaSource 深入解析:从 MediaItem 到媒体源工厂与播放列表 API 音视频移动开发【免费下载链接】ExoPlayerAn extensible media player for Android项目地址https://gitcode.com/gh_mirrors/exop/ExoPlayer点击查看免费下载本指南围绕 ExoPlayer 的媒体源MediaSource抽象展开先厘清对外 API 的MediaItem与内部播放核心的MediaSource之间的关系再深入DefaultMediaSourceFactory如何按内容类型自动创建对应媒体源随后给出注入自定义工厂、配置缓存与广告等定制方案最后介绍基于 MediaSource 的播放列表 API。读完本文你将掌握 ExoPlayer 媒体源创建与定制的完整链路并能在仓库源码中找到每一层实现证据。MediaItem 与 MediaSource播放器的双层媒体抽象在 ExoPlayer 中每一段媒体在对外 API 层都由MediaItem表示——它承载 URI、MIME 类型、剪辑配置、字幕配置、广告配置、直播配置等描述信息。但在播放器内部真正负责播放内容的是MediaSource实例。MediaItem与MediaSource之间通过MediaSource.Factory这座桥衔接播放器拿到MediaItem后调用工厂的createMediaSource(MediaItem)生成对应的MediaSource再交给内部播放管线。从源码角度看MediaSource接口MediaSource.java对媒体源定义了两大职责提供 Timeline向播放器描述媒体的结构周期数、窗口数等并在媒体结构变化时通过onSourceInfoRefreshed回调刷新提供 MediaPeriod通过createPeriod(...)为 Timeline 中的每个周期生成MediaPeriod它是播放器加载和读取媒体数据的通道。需要特别注意的是MediaSource的方法不应由应用代码直接调用播放器内部的ExoPlayer播放逻辑会在合适的时机触发它们同一MediaSource实例可复用但同时只能服务于一个ExoPlayer实例。默认情况下播放器使用DefaultMediaSourceFactory它根据媒体项的特征能创建以下 5 种内容型MediaSource内容类型MediaSource 实现适用场景参考文档DASHDashMediaSourceMPEG-DASH 自适应流媒体dash.mdSmoothStreamingSsMediaSourceMicrosoft Smooth Streamingsmoothstreaming.mdHLSHlsMediaSourceHTTP Live Streaminghls.md常规媒体文件ProgressiveMediaSourceMP4、MP3 等本地或渐进式下载文件progressive.mdRTSPRtspMediaSourceRTSP 实时流rtsp.md此外DefaultMediaSourceFactory还会依据媒体项的其他属性剪辑、广告、字幕、直播等组合出更复杂的媒体源这部分在 Media items 页面 中有更详细的说明。DefaultMediaSourceFactory 的内容类型识别与委托机制DefaultMediaSourceFactory的核心入口是createMediaSource(MediaItem)其完整流程实现在 DefaultMediaSourceFactory.java 中主要分三步第一步SSAI 特殊处理。若 URI 的 scheme 为C.SSAI_SCHEME服务端广告插入则直接交给setServerSideAdInsertionMediaSourceFactory(...)设置的专用工厂处理。第二步内容类型推断。调用Util.inferContentTypeForUriAndMimeType(uri, mimeType)判定内容类型其规则在 DefaultMediaSourceFactory.java 的类注释中明确给出URI 以.mpd结尾或 mimeType 显式设为MimeTypes.APPLICATION_MPD→ DASHURI 以.m3u8结尾或 mimeType 设为MimeTypes.APPLICATION_M3U8→ HLSURI 以.ism、.ism/Manifest结尾或 mimeType 设为MimeTypes.APPLICATION_SS→ SmoothStreaming均不匹配 → 回退到ProgressiveMediaSource.Factory由DefaultExtractorsFactory逐个探测可用的 Extractor若所有 Extractor 都无法解析该流则抛出UnrecognizedInputFormatException。提示以上推断同时依赖 URI 后缀与显式 mimeType 字段因此对于后缀不标准的资源可通过在MediaItem中显式设置mimeType来保证类型识别正确。第三步懒加载委托工厂。这一步由内部类DelegateFactoryLoaderDefaultMediaSourceFactory.java完成。它通过Class.forName(com.google.android.exoplayer2.source.dash.DashMediaSource$Factory)之类的反射方式按需实例化各类工厂只有应用的 classpath 中包含对应模块如exoplayer-dash、exoplayer-hls、exoplayer-smoothstreaming、exoplayer-rtsp时对应工厂才会被加载模块缺失时捕获ClassNotFoundException该内容类型即不被支持getSupportedTypes()中不会出现该类型已加载的工厂实例会被缓存复用并对CmcdConfiguration.Factory、DrmSessionManagerProvider、LoadErrorHandlingPolicy做统一透传。这也是想播放 HLS 就必须在依赖中加入 HLS 模块这一要求的源码级原因——工厂与模块一一对应按需反射加载避免不必要的类被打包。定制 MediaSource 创建注入工厂与完整示例对于默认配置无法满足需求的 AppExoPlayer 提供了两层定制手段。在构建播放器时注入 MediaSource.FactoryExoPlayer.Builder提供setMediaSourceFactory(MediaSource.Factory)方法见 ExoPlayer.java可在构建播放器时替换默认工厂。官方文档给出了一个同时满足插入广告 使用CacheDataSource.Factory支持缓存需求的完整示例MediaSource.Factory mediaSourceFactory new DefaultMediaSourceFactory(context) .setDataSourceFactory(cacheDataSourceFactory) .setLocalAdInsertionComponents( adsLoaderProvider, /* adViewProvider */ playerView); ExoPlayer player new ExoPlayer.Builder(context) .setMediaSourceFactory(mediaSourceFactory) .build();DefaultMediaSourceFactory 的可配置项结合 DefaultMediaSourceFactory.java 的源码该工厂支持链式配置的主要选项如下配置方法作用关键说明setDataSourceFactory(DataSource.Factory)设置请求媒体数据所用的DataSource工厂传入CacheDataSource.Factory即可启用缓存换用自定义实现可控制网络栈setLocalAdInsertionComponents(AdsLoader.Provider, AdViewProvider)为带adsConfiguration的媒体项配置本地广告插入组件若未配置而媒体项含广告配置日志会警告Playing media without ads并跳过广告见 maybeWrapWithAdsMediaSourcesetServerSideAdInsertionMediaSourceFactory(MediaSource.Factory)处理 scheme 为 SSAI 的 URI传null可移除先前设置setDrmSessionManagerProvider(DrmSessionManagerProvider)为每个媒体源提供 DRM 会话管理传入null不再自动兜底需显式构造DefaultDrmSessionManagerProvidersetLoadErrorHandlingPolicy(LoadErrorHandlingPolicy)设置加载错误处理策略同样要求显式传非空实例setCmcdConfigurationFactory(CmcdConfiguration.Factory)配置 CMCDCommon Media Client Data上报会透传给所有委托工厂setLiveTargetOffsetMs / setLiveMinOffsetMs / setLiveMaxOffsetMs设置直播流的期望/最小/最大 offset毫秒传C.TIME_UNSET使用媒体自身默认值setLiveMinSpeed / setLiveMaxSpeed设置直播流追赶播放的最小/最大倍速传C.RATE_UNSET使用媒体自身默认值experimentalUseProgressiveMediaSourceForSubtitles(boolean)实验性字幕改用ProgressiveMediaSource而非SingleSampleMediaSource默认 false未来版本可能改名或移除关于直播配置的优先级源码createMediaSource中有明确的合并逻辑仅当MediaItem的liveConfiguration中对应字段为C.TIME_UNSET/C.RATE_UNSET时才用工厂级的全局配置覆盖若覆盖后配置有变化会重新构建一份携带LiveConfiguration的MediaItemDefaultMediaSourceFactory.java。注入完全自定义的 MediaSource.Factory除配置DefaultMediaSourceFactory外还可以直接注入自定义的MediaSource.Factory实现例如支持某种自定义媒体源类型。MediaSource.Factory接口MediaSource.java需要实现的核心方法包括createMediaSource(MediaItem)为加入播放列表的每个MediaItem创建媒体源这是播放列表逐个条目转换的必经入口详见 playlists.mdgetSupportedTypes()声明该工厂支持的内容类型setDrmSessionManagerProvider(...)/setLoadErrorHandlingPolicy(...)接收播放器透传的全局配置。MediaSource 层面的播放列表 APIExoPlayer接口在MediaItem播放列表 API 之外还定义了一批直接接受MediaSource的播放列表方法ExoPlayer.java从而绕过播放器内部的MediaSource.Factory将现成的MediaSource实例直接交给播放器方法行为setMediaSources(ListMediaSource)清空播放列表并添加给定媒体源位置重置到默认位置setMediaSources(ListMediaSource, boolean resetPosition)同上resetPositionfalse时从当前条目与位置继续setMediaSources(ListMediaSource, int startMediaItemIndex, long startPositionMs)指定起始条目索引与起始位置INDEX_UNSET/TIME_UNSET表示不重置setMediaSource(MediaSource)/setMediaSource(MediaSource, long startPositionMs)/setMediaSource(MediaSource, boolean resetPosition)单条目版本addMediaSource(MediaSource)/addMediaSource(int index, MediaSource)追加或在指定索引插入单个媒体源addMediaSources(ListMediaSource)/addMediaSources(int index, ListMediaSource)追加或在指定索引批量插入官方文档给出的组合用法示例如下// Set a list of media sources as initial playlist. exoPlayer.setMediaSources(listOfMediaSources); // Add a single media source. exoPlayer.addMediaSource(anotherMediaSource); // Can be combined with the media item API. exoPlayer.addMediaItem(/* index */ 3, MediaItem.fromUri(videoUri)); exoPlayer.prepare(); exoPlayer.play();从源码实现看这些方法最终由 MediaSourceList.java 统一管理媒体源会被封装进MaskingMediaSource再进入播放器内部ExoPlayerImpl→ExoPlayerImplInternal的播放管线这保证了按需 lazy 创建 MediaPeriod以及 Timeline 的动态刷新。此外旧的prepare(MediaSource)形式已废弃官方建议改用setMediaSource(...)prepare()的组合。进阶createMediaSource 内部的组合逻辑DefaultMediaSourceFactory.createMediaSource的最后阶段体现了媒体源可组合的设计——它并不是简单返回单一媒体源而是根据MediaItem属性做三层包装DefaultMediaSourceFactory.java字幕合并若媒体项带subtitleConfigurations会为主媒体源追加字幕媒体源默认SingleSampleMediaSource并通过MergingMediaSource合并为一个多轨媒体源剪辑裁剪若设置了clippingConfiguration起始/结束位置、是否相对于默认位置、是否从关键帧开始则用ClippingMediaSource包裹实现裁剪见 maybeClipMediaSource广告包装若媒体项带adsConfiguration且已配置广告组件则再用AdsMediaSource包裹实现本地广告插入。这种工厂产出基础媒体源 组合器逐层包装的模式正是 ExoPlayer 媒体源体系可扩展性的核心新增能力只需新增一个包装型MediaSource仓库中还可见ConcatenatingMediaSource、LoopingMediaSource、MergingMediaSource、FilteringMediaSource等同族实现均位于 source 目录。相关文档与源码导航播放列表与MediaItem概念playlists.md、media-items.md各格式详解dash.md、hls.md、smoothstreaming.md、progressive.md、rtsp.md核心源码DefaultMediaSourceFactory.java、MediaSource.java、MediaSourceFactory.java、ExoPlayer.java、MediaSourceList.java注意当前仓库中的com.google.android.exoplayer2包已标记为弃用官方建议迁移到包含相同 ExoPlayer 代码的androidx.media3仓库根目录提供 media3-migration.sh 迁移脚本辅助完成替换。本文所述 API 与机制在迁移后保持对应关系。赞分享音视频移动开发【免费下载链接】ExoPlayerAn extensible media player for Android项目地址https://gitcode.com/gh_mirrors/exop/ExoPlayer点击查看免费下载相关推荐3 步把 SillyTavern 提速 70%:一份完整的性能优化清单3 步把 SillyTavern 提速 70%:一份完整的性能优化清单 打开 SillyTavern 主页,首屏要等约 4 秒,角色列表还要再转 300 毫秒。音视频移动开发ExoPlayer实时流媒体播放从入门到精通的完整指南ExoPlayer实时流媒体播放从入门到精通的完整指南 ExoPlayer作为Android平台上功能强大的开源媒体播放器库为开发者提供了完整的实时流媒体播音视频移动开发突破播放瓶颈ExoPlayer核心组件MediaSource与Renderer架构原理解析突破播放瓶颈ExoPlayer核心组件MediaSource与Renderer架构原理解析 在Android音视频开发中你是否还在为播放器的兼容性、性能优化音视频移动开发上一篇【亲测免费】 Amazing-QRPython编写的强大二维码生成器下一篇提升Angular性能NGX-ECHARTS的TreeShaking定制构建指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询