|
|
@@ -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(() => {
|