Android中使用ExoPlayer播放音频时插入中插广告方案咨询
基于ExoPlayer实现自定义中插广告(Mid-Roll)方案
核心思路
无需依赖IMA或VAST协议,直接利用ExoPlayer的拼接播放列表(ConcatenatingMediaSource)结合播放进度监听,将广告音频作为普通媒体源插入到剧集的指定时间节点。本质是把完整剧集拆分为「广告前片段」+「广告源」+「广告后片段」的组合,按顺序播放。
具体实现步骤
1. 拆分剧集与创建广告媒体源
- 先获取剧集的总时长,确定中插广告的触发时间点(比如每15分钟一次,或固定的几个时间戳)。
- 使用
ClippingMediaSource截取剧集的前后分段,同时创建广告的媒体源(和普通剧集源创建方式一致):// 假设midRollTime是预设的中插时间,单位为微秒 val episodeMediaSource = ProgressiveMediaSource.Factory(dataSourceFactory) .createMediaSource(MediaItem.fromUri(episodeUrl)) // 截取剧集从开始到中插点的片段 val preAdSegment = ClippingMediaSource( episodeMediaSource, 0, midRollTime ) // 截取剧集从中插点到结束的片段 val postAdSegment = ClippingMediaSource( episodeMediaSource, midRollTime, C.TIME_END_OF_SOURCE ) // 创建广告媒体源 val adMediaSource = ProgressiveMediaSource.Factory(dataSourceFactory) .createMediaSource(MediaItem.fromUri(adAudioUrl))
2. 构建拼接播放列表并播放
将拆分后的片段和广告源按顺序加入ConcatenatingMediaSource,再设置给播放器:
val concatenatedSource = ConcatenatingMediaSource( preAdSegment, adMediaSource, postAdSegment ) player.setMediaSource(concatenatedSource) player.prepare() player.play()
3. 动态插入广告(可选场景)
如果需要在播放过程中动态触发广告(比如根据用户行为或实时规则),可以通过监听播放进度,动态修改播放列表:
var adInserted = false player.addListener(object : Player.Listener { override fun onPositionDiscontinuity(oldPosition: Player.PositionInfo, newPosition: Player.PositionInfo, reason: Int) { super.onPositionDiscontinuity(oldPosition, newPosition, reason) val currentPos = player.currentPosition // 检查是否到达中插点且未插入过广告 if (currentPos >= midRollTime && !adInserted) { player.pause() // 截取当前位置到剧集结尾的剩余片段 val remainingSegment = ClippingMediaSource( episodeMediaSource, currentPos, C.TIME_END_OF_SOURCE ) // 替换原剧集源,插入广告和剩余片段 concatenatedSource.removeMediaSource(0) concatenatedSource.addMediaSource(adMediaSource) concatenatedSource.addMediaSource(remainingSegment) adInserted = true player.play() } } })
4. 异常与体验优化
- 广告加载失败时,监听
Player.Listener的onPlayerError事件,自动跳过广告,直接播放后续剧集片段。 - 若允许用户跳过广告,可在广告播放时显示跳过按钮,点击后调用
player.seekToNextMediaItem()切换到剧集片段。
内容的提问来源于stack exchange,提问作者Meenakshi Khandelwal
相关产品推荐
相关产品推荐

