diff --git a/README.md b/README.md index 1ae20ca07e461828396ed3d4a54f53b73482843f..ddf16a9ff316ed6d18b7b078a976df0c94da2e38 100644 --- a/README.md +++ b/README.md @@ -152,7 +152,7 @@ > **说明**:由于代码示例自身无法实现弱网模拟,因此需要自行进行弱网模拟并测试效果。本示例开发中通过clumsy进行弱网模拟, > 参考[clumsy使用教程](http://jagt.github.io/clumsy/manual.html)。开发者也可自行选择其他方法模拟弱网环境。 -1. 视频正常播放中,应用弱网环境,此时视频缓存整体处于降低趋势,缓冲压力较大。当视频剩余播放缓存时长低于阈值时,记录1s内视频下载速率,参考其值降低视频码率。 +1. 视频正常播放中,应用弱网环境,此时视频缓存整体处于降低趋势,缓冲压力较大。当视频剩余播放缓存时长低于阈值时,获取近期视频下载速率,参考其值降低视频码率。 2. 视频码率调节后,网络可以满足当前码率,此时视频缓存整体处于上升趋势,缓存压力较小。若视频剩余缓存播放时长高于阈值,且当前码率下已缓存视频的可播放时长达到了 高一级码率的最大视频缓存可播放时长,并且近期峰值下载速率高于下一级码率,则考虑上调一级码率。例如缓存区大小为20MB,上一次降低码率后的峰值下载速率为1MB/s, diff --git a/entry/src/main/ets/common/CommonConstants.ets b/entry/src/main/ets/common/CommonConstants.ets index be17cf08cf786189f4159df8cf89b4a5a143a14a..279468f6b18f23d754e743930427611fee5723b9 100644 --- a/entry/src/main/ets/common/CommonConstants.ets +++ b/entry/src/main/ets/common/CommonConstants.ets @@ -24,6 +24,7 @@ export class AVPlayerConstants { ]; public static readonly PLAYBACK_INTERVAL_MS: number = 500; public static readonly NET_CHECK_INTERVAL_MS: number = 500; + public static readonly RECENT_DOWNLOAD_LIST_LENGTH: number = 3; } export class ViewConstants { diff --git a/entry/src/main/ets/viewmodel/AVPlayerController.ets b/entry/src/main/ets/viewmodel/AVPlayerController.ets index 80f06747afb16c3b4d4f2a6f9407e0b032c72ae7..2f908c292644e99b8177e6bbdb62c23aefa85e4b 100644 --- a/entry/src/main/ets/viewmodel/AVPlayerController.ets +++ b/entry/src/main/ets/viewmodel/AVPlayerController.ets @@ -33,6 +33,8 @@ export class AVPlayerController { private isResumePlay: boolean = false; private currentBitrateIndex: number | undefined = undefined; private maxBufferValueList: Array = []; + private recentDownRates: Array = []; + private downloadRate: number = 0; private maxDownloadRate: number = 0; private source: media.MediaSource | undefined = undefined; private strategy: media.PlaybackStrategy | undefined = undefined; @@ -148,6 +150,10 @@ export class AVPlayerController { } } + private isDownloading() { + return this.downloadRate !== 0; + } + private isNewResolutionCaching() { return this.currentBitrateIndex !== this.currentResolutionIndex; } @@ -161,15 +167,32 @@ export class AVPlayerController { }); } + private getRecentDownRate(newDownRate: number) { + this.recentDownRates.push(newDownRate); + const rateCount = this.recentDownRates.length; + if (rateCount > AVPlayerConstants.RECENT_DOWNLOAD_LIST_LENGTH) { + this.recentDownRates.shift(); + return this.recentDownRates.reduce((acc, curr) => acc + curr, 0) / AVPlayerConstants.RECENT_DOWNLOAD_LIST_LENGTH; + } else { + return 0; + } + } + + private clearDownloadRate() { + this.downloadRate = 0; + this.recentDownRates = []; + } + // [Start GetDownloadRate] // entry/src/main/ets/viewmodel/AVPlayerController.ets private setPlaybackInfoInterval(avPlayer: media.AVPlayer) { this.playbackCallbackInterval = setInterval(async () => { avPlayer.getPlaybackInfo().then((playbackInfo: media.PlaybackInfo) => { - // 定时获取当前视频平均下载速率、1s内下载速率以及峰值下载速率 + // 定时获取当前视频平均下载速率、1s内下载速率、近期下载速率以及近期峰值下载速率 this.videoInfo.averageDownloadRate = Number(playbackInfo[media.PlaybackInfoKey.AVG_DOWNLOAD_RATE]); this.videoInfo.downloadRate = Number(playbackInfo[media.PlaybackInfoKey.DOWNLOAD_RATE]); - this.maxDownloadRate = Math.max(this.videoInfo.downloadRate, this.maxDownloadRate); + this.downloadRate = this.getRecentDownRate(this.videoInfo.downloadRate); + this.maxDownloadRate = Math.max(this.downloadRate, this.maxDownloadRate); }); }, AVPlayerConstants.PLAYBACK_INTERVAL_MS); } @@ -224,6 +247,8 @@ export class AVPlayerController { avPlayer.on('bitrateDone', (bitrate: number) => { // [StartExclude BasicCallback] Logger.info(`AVPlayer set bitrate done, bitrate: ${bitrate}`); + // 重置峰值下载速率 + this.maxDownloadRate = 0; // [EndExclude BasicCallback] // 设置码率成功,记录当前设置后的码率,此处记录索引值 this.currentBitrateIndex = this.bitrateList.findIndex((value) => value === bitrate); @@ -248,8 +273,9 @@ export class AVPlayerController { this.videoInfo.currentBufferInfoType = infoType; this.videoInfo.currentBufferInfoValue = value; - // 对于其他缓存类型信息、处于seek期间、或无法正常获取码率信息的视频源,不进行处理 - if (infoType !== media.BufferingInfoType.CACHED_DURATION || this.isSeeking || !this.isValidVideoStream()) { + // 对于其他缓存类型信息、不处于有效下载状态(下载中且获取到的下载速率不为0)、处于seek期间、或无法正常获取码率信息的视频源,不进行处理 + if (infoType !== media.BufferingInfoType.CACHED_DURATION || !this.isDownloading() || this.isSeeking || + !this.isValidVideoStream()) { return; } // [EndExclude CustomBitrateRule] @@ -304,6 +330,7 @@ export class AVPlayerController { this.setScreenKeepOnStatus(true); } else { this.isPlaying = false; + this.clearDownloadRate(); this.setScreenKeepOnStatus(false); } @@ -358,13 +385,14 @@ export class AVPlayerController { private findTargetBitrate() { const bitrateListLength = this.bitrateList.length; - if (this.videoInfo.downloadRate > this.bitrateList[bitrateListLength - 1]) { + const downloadBitrate = this.downloadRate; + if (downloadBitrate > this.bitrateList[bitrateListLength - 1]) { return this.bitrateList[bitrateListLength - 1]; } else { const targetBitrate = this.bitrateList.find((_value, index) => index < bitrateListLength - 1 && - this.bitrateList[index] <= this.videoInfo.downloadRate && - this.bitrateList[index + 1] > this.videoInfo.downloadRate + this.bitrateList[index] <= downloadBitrate && + this.bitrateList[index + 1] > downloadBitrate ) ?? this.bitrateList[0]; return targetBitrate; } @@ -373,9 +401,6 @@ export class AVPlayerController { private autoReduceBitrate(targetBitrate: number) { customToast($r('app.string.resolution_auto_reducing'), ViewConstants.TOAST_TIME_MS); this.setBitrate(targetBitrate); - - // 网络场景可能发生变化,重置峰值下载速率 - this.maxDownloadRate = 0; } private autoIncreaseBitrate(targetBitrate: number) {