Преглед изворни кода

百度音频播放无法获取时长的,从URL上重新获取一次

chendeben пре 8 месеци
родитељ
комит
90b65f2f89
1 измењених фајлова са 86 додато и 18 уклоњено
  1. 86 18
      entry/src/main/ets/view/LocalMusic.ets

+ 86 - 18
entry/src/main/ets/view/LocalMusic.ets

@@ -30,6 +30,7 @@ import { CommonConstants } from '../common/constants/CommonConstants';
 import { BaiduConstants } from '../common/constants/BaiduConstants';
 import { EventConstants } from '../common/constants/EventConstants';
 import Logger from '../common/util/Logger';
+import { http } from '@kit.NetworkKit';
 import { photoAccessHelper } from '@kit.MediaLibraryKit';
 import { BusinessError, emitter } from '@kit.BasicServicesKit';
 import { BubbleBean } from '../viewmodel/BubbleBean';
@@ -13258,6 +13259,9 @@ export struct LocalMusic {
   private setProgress() {
     let position = this.mIjkMediaPlayer.getCurrentPosition();
     let duration = this.mIjkMediaPlayer.getDuration();
+    if (duration <= 0 && this.duration > 0) {
+      duration = this.duration;
+    }
     let pos = 0;
     if (duration > 0) {
       this.slideEnable = true;
@@ -13571,27 +13575,91 @@ export struct LocalMusic {
 
           await this.initLyric(lyricPath);
 
+          const applyDuration = (durationMs: number): void => {
+            if (durationMs <= 0) {
+              return;
+            }
+            this.duration = durationMs;
+            this.durationTime = Math.floor(durationMs / 1000);
+            this.durationStringTime = secondToTime(this.durationTime);
+            this.totalTime = this.stringForTime(durationMs);
+            if (this.currentSong) {
+              this.currentSong.duration = this.totalTime;
+              try {
+                this.avSessionController.setAVMetadataMusic(this.currentSong, durationMs, this.lyricContent);
+              } catch (metaError) {
+                Logger.warn(TAG, `heanup 首次播放写入AVSession失败: ${(metaError as Error).message}`);
+              }
+            }
+          };
+          const fetchBaiduM3u8Duration = async (url: string): Promise<number> => {
+            if (!url || !isBaiduType(this.currentSong?.type ?? -1)) {
+              return 0;
+            }
+            const httpRequest = http.createHttp();
+            try {
+              const response = await httpRequest.request(url, {
+                method: http.RequestMethod.GET,
+                connectTimeout: 8000,
+                readTimeout: 8000,
+                expectDataType: http.HttpDataType.STRING,
+                header: {
+                  'User-Agent': BaiduConstants.STREAMING_USER_AGENT,
+                  'Host': 'pan.baidu.com'
+                }
+              });
+              if (response.responseCode !== 200 || typeof response.result !== 'string') {
+                return 0;
+              }
+              const text = response.result;
+              if (text.indexOf('#EXTM3U') < 0) {
+                return 0;
+              }
+              const lines = text.split('\n');
+              let totalSeconds = 0;
+              for (let i = 0; i < lines.length; i++) {
+                const line = lines[i].trim();
+                if (line.startsWith('#EXTINF:')) {
+                  const colonIndex = line.indexOf(':');
+                  if (colonIndex < 0) {
+                    continue;
+                  }
+                  const content = line.substring(colonIndex + 1);
+                  const commaIndex = content.indexOf(',');
+                  const numberPart = commaIndex >= 0 ? content.substring(0, commaIndex) : content;
+                  const seconds = Number(numberPart);
+                  if (!Number.isNaN(seconds) && seconds > 0) {
+                    totalSeconds += seconds;
+                  }
+                }
+              }
+              if (totalSeconds > 0) {
+                return Math.floor(totalSeconds * 1000);
+              }
+              return 0;
+            } catch (fetchError) {
+              Logger.warn(TAG, `heanup 解析百度M3U8时长失败: ${(fetchError as Error).message}`);
+              return 0;
+            } finally {
+              httpRequest.destroy();
+            }
+          };
+          const fetchDurationFallback = async (): Promise<void> => {
+            const durationMs = await fetchBaiduM3u8Duration(this.videoUrl);
+            if (durationMs > 0) {
+              Logger.info(TAG, `heanup 通过M3U8推导出时长: ${durationMs}ms`);
+              applyDuration(durationMs);
+              return;
+            }
+            Logger.warn(TAG, 'heanup 首次播放未拿到时长,保持未知');
+          };
+
           const preparedDuration = this.mIjkMediaPlayer.getDuration();
           console.info("onecold preparedDuration--" + preparedDuration)
           if (preparedDuration > 0) {
-            this.duration = preparedDuration;
-            this.durationTime = Math.floor(preparedDuration / 1000);
-            this.durationStringTime = secondToTime(this.durationTime);
-            console.info("onecold durationTime--" + this.durationTime)
-            console.info("onecold durationStringTime--" + this.durationStringTime)
-          }else{
-            setTimeout( ()=>{
-              this.duration  = this.mIjkMediaPlayer.getDuration();
-              this.durationTime = Math.floor(preparedDuration / 1000);
-              this.durationStringTime = secondToTime(this.durationTime);
-              console.info("onecold duration3--" + this.duration)
-              console.info("onecold durationStringTime3--" + this.durationStringTime)
-            },200)
-            this.duration  = this.mIjkMediaPlayer.getDuration();
-            this.durationTime = Math.floor(preparedDuration / 1000);
-            this.durationStringTime = secondToTime(this.durationTime);
-            console.info("onecold duration2--" + this.duration)
-            console.info("onecold durationStringTim2e--" + this.durationStringTime)
+            applyDuration(preparedDuration);
+          } else {
+            fetchDurationFallback();
           }
 
           setTimeout(() => {