Просмотр исходного кода

修复一些提前缓存的逻辑

onecold 7 месяцев назад
Родитель
Сommit
a0f2b9bee4

+ 33 - 7
entry/src/main/ets/common/util/RemotePlayerUtil.ets

@@ -25,6 +25,7 @@ import { CommonConstants } from '../constants/CommonConstants';
 
 const TAG = 'heanup RemotePlayerUtil';
 
+
 export interface MetadataExtractionOptions {
   context?: Context;
   autoParseMusicName?: boolean;
@@ -90,30 +91,47 @@ export function cloneVideoItem(item: VideoItem): VideoItem {
  * @param songList 当前播放列表
  * @param currentIndex 当前播放索引
  * @param playType 播放模式 (0:连续播放 1:单片重复播放 2:正常播放 3:随机播放)
+ * @param playedIndices 已播放的歌曲索引集合(随机模式使用)
+ * @returns 随机模式下的下一首索引,非随机模式返回-1
  */
 export async function preloadNextSongIfNeeded(
   songList: VideoItem[],
   currentIndex: number,
-  playType: number
-): Promise<void> {
+  playType: number,
+  playedIndices?: Set<number>
+): Promise<number> {
   Logger.info(TAG, `preloadNextSongIfNeeded 被调用 - songList长度: ${songList?.length || 0}, currentIndex: ${currentIndex}, playType: ${playType}`);
 
   const preloadEnabled = PreferencesUtil.getBooleanSync('preload_next_song', true);
   if (!preloadEnabled) {
     Logger.info(TAG, '提前缓存下一首功能未启用');
-    return;
+    return -1;
   }
 
   if (!ArrayUtil.isNotEmpty(songList) || songList.length <= 1) {
     Logger.info(TAG, '歌曲列表为空或只有一首,无需提前缓存');
-    return;
+    return -1;
   }
 
+
   // 计算下一首索引
   let nextIndex = 0;
   if (playType === 3) {
-    // 随机播放模式,随机选择一首
-    nextIndex = Math.floor(Math.random() * songList.length);
+    // 随机播放模式,随机选择一首(排除当前播放和已播放的)
+    let attempt = 0;
+    const maxAttempts = 100;
+    do {
+      nextIndex = Math.floor(Math.random() * songList.length);
+      attempt++;
+    } while ((nextIndex === currentIndex || (playedIndices && playedIndices.has(nextIndex))) && attempt < maxAttempts);
+
+    // 如果所有歌曲都播放过,清空已播放集合并重新随机
+    if (attempt >= maxAttempts && playedIndices && playedIndices.size === songList.length) {
+      playedIndices.clear();
+      nextIndex = Math.floor(Math.random() * songList.length);
+    }
+
+    Logger.info(TAG, `随机播放模式,预缓存下一首索引: ${nextIndex}, 尝试次数: ${attempt}`);
   } else {
     // 顺序或循环播放模式
     if (currentIndex === songList.length - 1) {
@@ -126,7 +144,7 @@ export async function preloadNextSongIfNeeded(
   // 如果下一首就是当前正在播放的(单曲循环),则不缓存
   if (nextIndex === currentIndex && playType === 1) {
     console.info(TAG, '单曲循环模式,无需提前缓存');
-    return;
+    return -1;
   }
 
   const nextSong = songList[nextIndex];
@@ -199,8 +217,16 @@ export async function preloadNextSongIfNeeded(
     const err = error as Error;
     console.warn(TAG, `提前缓存下一首失败: ${err.message}`);
   }
+
+  // 随机模式返回预缓存的索引,其他模式返回-1
+  if (playType === 3) {
+    Logger.info(TAG, `返回预缓存的随机索引: ${nextIndex}`);
+    return nextIndex;
+  }
+  return -1;
 }
 
+
 /**
  * 为歌曲设置播放URL
  * @param song 歌曲对象

+ 75 - 30
entry/src/main/ets/view/LocalMusic.ets

@@ -9591,6 +9591,7 @@ export struct LocalMusic {
   @State isYesFull: boolean = false
   private seekValue: number = 0
   @State isVideoLock: boolean = false; // Whether the video playback is locked
+  private preloadNextRandomIndex: number = -1; // 预缓存的随机下一首索引
   eventHub = getContext().eventHub;
   //投播组件
   private avSessionController: AvSessionController = AvSessionController.getInstance(false);
@@ -10237,9 +10238,11 @@ export struct LocalMusic {
             else {
               this.isSeekTo = true;
               this.mDestroyPage = false;
-              this.showLoadIng();
+              // 只有播放网盘歌曲时才显示转圈圈
+              if (this.currentSong && isRemoteCloudType(this.currentSong.type)) {
+                this.showLoadIng();
+              }
               this.seekTo(position + "");
-              this.isSeekTo = false;
             }
             return true
           }
@@ -10461,16 +10464,19 @@ export struct LocalMusic {
           .layoutWeight(1)
           .enabled(this.slideEnable)
           .onChange((value: number, mode: SliderChangeMode) => {
-            // if (mode == 2) {
+
+
             this.isSeekTo = true;
             this.mDestroyPage = false;
-            this.showLoadIng();
+            // 只有播放网盘歌曲时才显示转圈圈
+            if (this.currentSong && isRemoteCloudType(this.currentSong.type)) {
+              this.showLoadIng();
+            }
             LogUtils.getInstance().LOGI("slider-->seekValue start:" + value);
             let seekValue = value * (this.mIjkMediaPlayer.getDuration() / 100);
             this.seekTo(seekValue + "");
             // this.setProgress()
             LogUtils.getInstance().LOGI("slider-->seekValue end:" + seekValue);
-            this.isSeekTo = false;
             // }
           })
 
@@ -10740,15 +10746,18 @@ export struct LocalMusic {
         .enabled(this.slideEnable)
         .onChange((value: number, mode: SliderChangeMode) => {
           // if (mode == 2) {
+
           this.isSeekTo = true;
           this.mDestroyPage = false;
-          this.showLoadIng();
+          // 只有播放网盘歌曲时才显示转圈圈
+          if (this.currentSong && isRemoteCloudType(this.currentSong.type)) {
+            this.showLoadIng();
+          }
           LogUtils.getInstance().LOGI("slider-->seekValue start:" + value);
           let seekValue = value * (this.mIjkMediaPlayer.getDuration() / 100);
           this.seekTo(seekValue + "");
           // this.setProgress()
           LogUtils.getInstance().LOGI("slider-->seekValue end:" + seekValue);
-          this.isSeekTo = false;
           // }
         })
       Text(this.totalTime)
@@ -13116,8 +13125,11 @@ export struct LocalMusic {
       this.startPlay(startOffset)
     }
 
-    // 提前缓存下一首
-    void this.preloadNextSongInternal();
+    // 仅当前播放的是网盘歌曲时,才提前缓存下一首
+    // 排除用户拖动进度条的情况
+    if (this.currentSong && isRemoteCloudType(this.currentSong.type) && !this.isSeekTo) {
+      void this.preloadNextSongInternal();
+    }
   }
 
   startPlay(startOffset?:number) {
@@ -13799,7 +13811,13 @@ export struct LocalMusic {
       onSeekComplete: () => {
         LogUtils.getInstance().LOGI("OnSeekCompleteListener-->go");
         console.info('onecold startPlayOrResumePlay 10643')
-        that.startPlayOrResumePlay();
+        // seek 完成,延迟恢复播放,确保 ijkplayer 内部状态完全稳定
+        setTimeout(() => {
+          // seek 完成,隐藏转圈圈并重置标志
+          that.hideLoadIng();
+          that.isSeekTo = false;
+          that.startPlayOrResumePlay();
+        }, 200); // 延迟200ms,确保ijkplayer内部状态稳定
 
       }
     }
@@ -14574,7 +14592,21 @@ export struct LocalMusic {
 
   // 内部方法:提前缓存下一首
   private async preloadNextSongInternal(): Promise<void> {
-    await preloadNextSongIfNeeded(this.songList, this.curIndex, this.playType);
+    // 随机模式下传递已播放索引集合
+    if (this.playType === 3) {
+      this.preloadNextRandomIndex = await preloadNextSongIfNeeded(
+        this.songList,
+        this.curIndex,
+        this.playType,
+        this.playedIndices
+      );
+    } else {
+      this.preloadNextRandomIndex = await preloadNextSongIfNeeded(
+        this.songList,
+        this.curIndex,
+        this.playType
+      );
+    }
   }
 
   // 存储已播放的歌曲索引
@@ -14587,28 +14619,41 @@ export struct LocalMusic {
     // }
     if (ArrayUtil.isNotEmpty(this.songList)) {
       if (this.songList.length > 3) {
-        // 如果所有歌曲都播放过一次,清空已播放索引集合
-        if (this.playedIndices.size === this.songList.length) {
-          this.playedIndices.clear();
-        }
+        // 优先使用预缓存的随机索引(仅网盘播放时)
+        const nextSong = this.songList[this.preloadNextRandomIndex >= 0 ? this.preloadNextRandomIndex : 0];
+        const isNextRemote = nextSong && isRemoteCloudType(nextSong.type);
+        const isCurrentRemote = this.currentSong && isRemoteCloudType(this.currentSong.type);
+
+        if (this.preloadNextRandomIndex >= 0 && this.preloadNextRandomIndex < this.songList.length && isNextRemote && isCurrentRemote) {
+          Logger.info('heanup randomPlay', `使用预缓存的随机索引: ${this.preloadNextRandomIndex} (网盘播放)`);
+          this.curIndex = this.preloadNextRandomIndex;
+          this.playedIndices.add(this.curIndex);
+          this.preloadNextRandomIndex = -1; // 重置预缓存索引
+        } else {
+          // 如果没有预缓存索引,则正常随机选择
+          // 如果所有歌曲都播放过一次,清空已播放索引集合
+          if (this.playedIndices.size === this.songList.length) {
+            this.playedIndices.clear();
+          }
 
-        // 随机选择一个未播放的歌曲索引
-        let newIndex: number;
-        // 添加超时机制防止无限循环
-        let attempt = 0;
-        const maxAttempts = 100; // 根据需求调整
-        do {
-          newIndex = RandomUtil.getRandomNumber(0, this.songList.length - 1);
-          attempt++;
-        } while (this.playedIndices.has(newIndex) && attempt < maxAttempts);
+          // 随机选择一个未播放的歌曲索引
+          let newIndex: number;
+          // 添加超时机制防止无限循环
+          let attempt = 0;
+          const maxAttempts = 100; // 根据需求调整
+          do {
+            newIndex = RandomUtil.getRandomNumber(0, this.songList.length - 1);
+            attempt++;
+          } while (this.playedIndices.has(newIndex) && attempt < maxAttempts);
 
-        if (attempt >= maxAttempts) {
-          // 处理无法找到新索引的情况(如随机选择或按顺序播放)
-          newIndex = Math.floor(Math.random() * this.songList.length);
-        }
+          if (attempt >= maxAttempts) {
+            // 处理无法找到新索引的情况(如随机选择或按顺序播放)
+            newIndex = Math.floor(Math.random() * this.songList.length);
+          }
 
-        this.curIndex = newIndex;
-        this.playedIndices.add(newIndex);
+          this.curIndex = newIndex;
+          this.playedIndices.add(newIndex);
+        }
       } else {
         // 当歌曲数量小于或等于3时,直接播放下一首
         if (this.curIndex == this.songList.length - 1) {

+ 3 - 3
entry/src/main/ets/view/NavidromePage.ets

@@ -1344,9 +1344,9 @@ export struct NavidromePage {
     videoItem.lyricContent = song.lyrics;
 
     // 调试日志:检查歌曲的 albumId 和 artistId
-    if (this.allVideos.length < 3) {
-      Logger.info('heanup', `歌曲 ${title}: artistId=${song.artistId}, albumId=${song.albumId}, artist=${song.artist}, album=${song.album}`);
-    }
+    // if (this.allVideos.length < 3) {
+    //   Logger.info('heanup', `歌曲 ${title}: artistId=${song.artistId}, albumId=${song.albumId}, artist=${song.artist}, album=${song.album}`);
+    // }
     if (song.track !== undefined && song.track !== null) {
       videoItem.track = song.track.toString();
     }