|
|
@@ -21,6 +21,10 @@ import { fileIo } from '@kit.CoreFileKit';
|
|
|
import { media } from '@kit.MediaKit';
|
|
|
import { fileUri } from '@kit.CoreFileKit';
|
|
|
import { VideoItem } from '../viewmodel/VideoItem';
|
|
|
+import { RemoteDriveManager } from '../common/util/RemoteDriveManager';
|
|
|
+import { RemoteCacheManager } from '../common/network/RemoteCacheManager';
|
|
|
+import { RemoteCacheType } from '../common/network/RemoteSongCache';
|
|
|
+import { extractFtpRelativePath, extractSmbRelativePath, isFtpType, isSmbType } from '../common/util/RemotePlayerUtil';
|
|
|
|
|
|
const TAG = 'heanup CastController';
|
|
|
|
|
|
@@ -159,7 +163,38 @@ export class CastController {
|
|
|
|
|
|
try {
|
|
|
// 判断是否是流媒体
|
|
|
- let isStreaming = this.isUrl(videoUrl);
|
|
|
+ let localCachePath: string | undefined = undefined;
|
|
|
+ if (this.isLoopbackUrl(videoUrl) && (isSmbType(songItem.type) || isFtpType(songItem.type))) {
|
|
|
+ try {
|
|
|
+ const manager = RemoteDriveManager.getInstance();
|
|
|
+ const accountId = songItem.webdav_account_id;
|
|
|
+ if (accountId) {
|
|
|
+ const account = await manager.getWebDavAccountById(accountId);
|
|
|
+ if (account) {
|
|
|
+ if (isSmbType(songItem.type)) {
|
|
|
+ const relative = extractSmbRelativePath(songItem, account.smbShare);
|
|
|
+ if (relative) {
|
|
|
+ localCachePath = await RemoteCacheManager.ensureCached(RemoteCacheType.SMB, {
|
|
|
+ account,
|
|
|
+ remotePath: relative
|
|
|
+ });
|
|
|
+ }
|
|
|
+ } else if (isFtpType(songItem.type)) {
|
|
|
+ const relative = extractFtpRelativePath(songItem);
|
|
|
+ if (relative) {
|
|
|
+ localCachePath = await RemoteCacheManager.ensureCached(RemoteCacheType.FTP, {
|
|
|
+ account,
|
|
|
+ remotePath: relative
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.warn(TAG, `投播缓存准备失败,继续使用流媒体地址: ${(error as Error).message}`);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ let isStreaming = !localCachePath && this.isUrl(videoUrl);
|
|
|
console.info( TAG, `是否流媒体: ${isStreaming}`);
|
|
|
|
|
|
let description: avSession.AVMediaDescription = {
|
|
|
@@ -180,15 +215,13 @@ export class CastController {
|
|
|
console.info( TAG, `✅ 使用流媒体地址投播: ${videoUrl}`);
|
|
|
} else {
|
|
|
// 本地文件使用 fdSrc
|
|
|
- // let uri = fileUri.getUriFromPath(songItem.filePath);
|
|
|
- //console.info( TAG, `文件URI: ${uri}`);
|
|
|
-
|
|
|
- this.castFile = fileIo.openSync(songItem.filePath, fileIo.OpenMode.READ_ONLY);
|
|
|
+ const localPath = localCachePath || videoUrl || songItem.filePath;
|
|
|
+ this.castFile = fileIo.openSync(localPath, fileIo.OpenMode.READ_ONLY);
|
|
|
console.info( TAG, `✅ 打开文件成功, fd: ${this.castFile.fd}`);
|
|
|
|
|
|
let fdSrc: media.AVFileDescriptor = { fd: this.castFile.fd };
|
|
|
description.fdSrc = fdSrc;
|
|
|
- console.info( TAG, `✅ 使用本地文件投播: ${songItem.filePath}, fd: ${this.castFile.fd}`);
|
|
|
+ console.info( TAG, `✅ 使用本地文件投播: ${localPath}, fd: ${this.castFile.fd}`);
|
|
|
}
|
|
|
|
|
|
playItem = {
|
|
|
@@ -242,6 +275,16 @@ export class CastController {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+ private isLoopbackUrl(url: string): boolean {
|
|
|
+ if (!url) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (url.startsWith('http://127.') || url.startsWith('http://localhost') || url.startsWith('https://localhost')) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 设置投播状态变化监听器
|
|
|
*/
|