Android Chromecast Sender更新元数据如何避免音频流重缓冲
问题场景
- 已参照官方文档完成Chromecast Android Sender端媒体元数据投放功能,初始加载流程正常,可正确展示媒体标题、封面、正常播放流
- 对接实时音频流场景时,需要不定期更新媒体元数据,要求更新过程不能触发音频流重新缓冲
- 现有实现所有媒体相关操作都走
load()流程,更新元数据时会导致流缓冲
现有问题代码
override fun loadMediaLoadRequestData(request: PlatformBridgeApis.MediaLoadRequestData?) { if (request == null) return val remoteMediaClient: RemoteMediaClient = remoteMediaClient ?: return val mediaLoadRequest = getMediaLoadRequestData(request) remoteMediaClient.load(mediaLoadRequest) } fun getMediaLoadRequestData(request: PlatformBridgeApis.MediaLoadRequestData): MediaLoadRequestData { val mediaInfo = getMediaInfo(request.mediaInfo) return MediaLoadRequestData.Builder() .setMediaInfo(mediaInfo) .setAutoplay(request.shouldAutoplay) .setCurrentTime(request.currentTime) .build() } fun getMediaInfo(mediaInfo: PlatformBridgeApis.MediaInfo?): MediaInfo? { if (mediaInfo == null) return null val streamType = getStreamType(mediaInfo.streamType) val metadata = getMediaMetadata(mediaInfo.mediaMetadata) val mediaTracks = mediaInfo.mediaTracks.map { getMediaTrack(it) } val customData = JSONObject(mediaInfo.customDataAsJson ?: "{}") return MediaInfo.Builder(mediaInfo.contentId) .setStreamType(streamType) .setContentType(mediaInfo.contentType) .setMetadata(metadata) .setMediaTracks(mediaTracks) .setStreamDuration(mediaInfo.streamDuration) .setCustomData(customData) .build() }
问题根源
调用RemoteMediaClient.load()方法的语义是加载全新的媒体资源,只要触发该方法,接收器端就会重置当前播放状态、重新拉取媒体流,必然产生缓冲,无法满足同一条实时流更新元数据的需求。
实现方案
- 拆分「加载新流」和「更新现有流元数据」两个逻辑分支,同一条流的元数据更新不要走
load()流程 - 元数据更新场景使用Cast SDK提供的专用API,直接更新当前播放媒体的元数据,不会触发流重载
- 在原有
loadMediaLoadRequestData方法中增加判断:如果本次请求的内容ID和当前正在播放的内容ID一致,直接走元数据更新逻辑,否则走原有加载新流逻辑
修改后的完整代码如下:
override fun loadMediaLoadRequestData(request: PlatformBridgeApis.MediaLoadRequestData?) { if (request == null) return val remoteMediaClient: RemoteMediaClient = remoteMediaClient ?: return val targetContentId = request.mediaInfo?.contentId val currentPlayingContentId = remoteMediaClient.mediaInfo?.contentId // 同一条流的元数据更新,走无缓冲更新逻辑 if (targetContentId != null && targetContentId == currentPlayingContentId) { val newMetadata = getMediaMetadata(request.mediaInfo?.mediaMetadata) val customData = JSONObject(request.mediaInfo?.customDataAsJson ?: "{}") // 调用SDK专用元数据更新接口,不会触发流重新加载/缓冲 remoteMediaClient.setMediaMetadata(newMetadata, customData) return } // 不同流/首次加载,走原有load流程 val mediaLoadRequest = getMediaLoadRequestData(request) remoteMediaClient.load(mediaLoadRequest) } // 以下原有工具方法无需修改 fun getMediaLoadRequestData(request: PlatformBridgeApis.MediaLoadRequestData): MediaLoadRequestData { val mediaInfo = getMediaInfo(request.mediaInfo) return MediaLoadRequestData.Builder() .setMediaInfo(mediaInfo) .setAutoplay(request.shouldAutoplay) .setCurrentTime(request.currentTime) .build() } fun getMediaInfo(mediaInfo: PlatformBridgeApis.MediaInfo?): MediaInfo? { if (mediaInfo == null) return null val streamType = getStreamType(mediaInfo.streamType) val metadata = getMediaMetadata(mediaInfo.mediaMetadata) val mediaTracks = mediaInfo.mediaTracks.map { getMediaTrack(it) } val customData = JSONObject(mediaInfo.customDataAsJson ?: "{}") return MediaInfo.Builder(mediaInfo.contentId) .setStreamType(streamType) .setContentType(mediaInfo.contentType) .setMetadata(metadata) .setMediaTracks(mediaTracks) .setStreamDuration(mediaInfo.streamDuration) .setCustomData(customData) .build() }
注意事项
- 官方提供的Default Media Receiver、Styled Media Receiver都原生支持该元数据更新逻辑,无适配成本;如果使用自定义接收器,需要确保收到元数据更新指令时仅刷新UI展示,不触发媒体源重新加载即可
- 禁止在同流更新场景调用
load()方法,即使传入的MediaInfo参数和当前完全一致,部分接收器实现仍会触发流重载,无法保证无缓冲效果 - 如果需要同时更新媒体轨道、自定义数据、时长等其他非流地址字段,可以基于当前
remoteMediaClient.mediaInfo构建新的MediaInfo实例,仅替换需要更新的字段,调用remoteMediaClient.updateMediaInfo()方法传入即可,同样不会触发流缓冲
内容的提问来源于stack exchange,提问作者bypass112
相关产品推荐
相关产品推荐

