Procházet zdrojové kódy

优化视频处理逻辑,新增标准HLS流地址判断,改进视频信息加载方式,移除冗余查询参数,提升用户体验

wuyi před 3 měsíci
rodič
revize
0c7e29b418
3 změnil soubory, kde provedl 80 přidání a 44 odebrání
  1. 21 10
      src/components/VideoProcessor.vue
  2. 0 10
      src/views/Home.vue
  3. 59 24
      src/views/VideoPlayer.vue

+ 21 - 10
src/components/VideoProcessor.vue

@@ -191,6 +191,12 @@ const processCover = async (url: string): Promise<void> => {
   }
   }
 };
 };
 
 
+// 判断是否为标准的 HLS 流地址
+const isStandardHlsUrl = (url: string): boolean => {
+  // 简单判断:只要包含 .m3u8 就是 HLS 流
+  return url.includes(".m3u8");
+};
+
 // 处理视频 URL
 // 处理视频 URL
 const processVideo = async (url: string): Promise<void> => {
 const processVideo = async (url: string): Promise<void> => {
   if (!url) return;
   if (!url) return;
@@ -199,6 +205,15 @@ const processVideo = async (url: string): Promise<void> => {
     loading.value = true;
     loading.value = true;
     error.value = "";
     error.value = "";
 
 
+    // 检查是否为标准的 HLS 流地址
+    if (isStandardHlsUrl(url)) {
+      processedVideoUrl.value = url;
+      await nextTick();
+      await initVideoPlayer();
+      emit("videoLoaded", processedVideoUrl.value);
+      return;
+    }
+
     let processedUrl = url;
     let processedUrl = url;
     if (processedUrl.includes("cover")) {
     if (processedUrl.includes("cover")) {
       processedUrl = processedUrl.replace("cover", "play");
       processedUrl = processedUrl.replace("cover", "play");
@@ -209,10 +224,7 @@ const processVideo = async (url: string): Promise<void> => {
       const decryptedData = await loader(processedUrl);
       const decryptedData = await loader(processedUrl);
 
 
       if (typeof decryptedData === "string") {
       if (typeof decryptedData === "string") {
-        // 处理 M3U8 内容
         const playlist = processM3u8Content(decryptedData, processedUrl);
         const playlist = processM3u8Content(decryptedData, processedUrl);
-
-        // 创建 Blob URL
         const blob = new Blob([playlist], { type: "application/x-mpegURL" });
         const blob = new Blob([playlist], { type: "application/x-mpegURL" });
         processedVideoUrl.value = URL.createObjectURL(blob);
         processedVideoUrl.value = URL.createObjectURL(blob);
       } else {
       } else {
@@ -222,7 +234,7 @@ const processVideo = async (url: string): Promise<void> => {
       processedVideoUrl.value = url;
       processedVideoUrl.value = url;
     }
     }
 
 
-    // 初始化播放器
+    await nextTick();
     await initVideoPlayer();
     await initVideoPlayer();
     emit("videoLoaded", processedVideoUrl.value);
     emit("videoLoaded", processedVideoUrl.value);
   } catch (err) {
   } catch (err) {
@@ -270,14 +282,13 @@ const processM3u8Content = (m3u8Text: string, baseUrl: string): string => {
 
 
 // 初始化视频播放器
 // 初始化视频播放器
 const initVideoPlayer = async (): Promise<void> => {
 const initVideoPlayer = async (): Promise<void> => {
-  if (!videoElement.value || !processedVideoUrl.value) return;
+  if (!videoElement.value || !processedVideoUrl.value) {
+    return;
+  }
 
 
   const video = videoElement.value;
   const video = videoElement.value;
-
-  // 销毁现有的 HLS 实例
   destroyHls();
   destroyHls();
 
 
-  // 检查浏览器是否原生支持 HLS
   if (video.canPlayType("application/vnd.apple.mpegurl")) {
   if (video.canPlayType("application/vnd.apple.mpegurl")) {
     video.src = processedVideoUrl.value;
     video.src = processedVideoUrl.value;
   } else if (Hls.isSupported()) {
   } else if (Hls.isSupported()) {
@@ -295,7 +306,7 @@ const initVideoPlayer = async (): Promise<void> => {
         switch (data.type) {
         switch (data.type) {
           case Hls.ErrorTypes.NETWORK_ERROR:
           case Hls.ErrorTypes.NETWORK_ERROR:
             if (data.details === "manifestParsingError") {
             if (data.details === "manifestParsingError") {
-              error.value = "视频加载失败";
+              error.value = "视频清单解析失败";
               hlsInstance.value?.destroy();
               hlsInstance.value?.destroy();
               hlsInstance.value = null;
               hlsInstance.value = null;
               video.src = processedVideoUrl.value;
               video.src = processedVideoUrl.value;
@@ -361,7 +372,7 @@ const onVideoLoadedData = (): void => {};
 
 
 const onVideoCanPlay = (): void => {
 const onVideoCanPlay = (): void => {
   if (props.autoPlay && videoElement.value) {
   if (props.autoPlay && videoElement.value) {
-    videoElement.value.play().catch(console.warn);
+    videoElement.value.play().catch(() => {});
   }
   }
 };
 };
 
 

+ 0 - 10
src/views/Home.vue

@@ -654,16 +654,6 @@ const playVideo = (video: any) => {
   router.push({
   router.push({
     name: "VideoPlayer",
     name: "VideoPlayer",
     params: { id: video.id },
     params: { id: video.id },
-    query: {
-      name: video.name,
-      cover: video.cover,
-      m3u8: video.m3u8,
-      duration: video.duration,
-      view: video.view,
-      like: video.like,
-      time: video.time,
-      taginfo: JSON.stringify(video.taginfo || []),
-    },
   });
   });
 };
 };
 
 

+ 59 - 24
src/views/VideoPlayer.vue

@@ -225,7 +225,7 @@
 <script setup lang="ts">
 <script setup lang="ts">
 import { ref, onMounted, onUnmounted, computed } from "vue";
 import { ref, onMounted, onUnmounted, computed } from "vue";
 import { useRoute, useRouter } from "vue-router";
 import { useRoute, useRouter } from "vue-router";
-import { searchVideoByTags } from "@/services/api";
+import { searchVideoByTags, getVideoDetail } from "@/services/api";
 import VideoProcessor from "@/components/VideoProcessor.vue";
 import VideoProcessor from "@/components/VideoProcessor.vue";
 
 
 // 路由相关
 // 路由相关
@@ -346,30 +346,65 @@ const playVideo = (video: any) => {
 };
 };
 
 
 // 加载视频信息
 // 加载视频信息
-const loadVideoInfo = () => {
+const loadVideoInfo = async () => {
   // 优先从路由参数获取ID
   // 优先从路由参数获取ID
   const videoId = route.params.id || route.query.id;
   const videoId = route.params.id || route.query.id;
 
 
-  // 从查询参数获取其他信息
-  const videoData = route.query;
-
   if (videoId) {
   if (videoId) {
-    videoInfo.value = {
-      id: videoId,
-      name: videoData.name || `视频 ${videoId}`,
-      cover: videoData.cover || "",
-      m3u8: videoData.m3u8 || "",
-      duration: videoData.duration || 0,
-      view: videoData.view || 0,
-      like: videoData.like || 0,
-      time: videoData.time || 0,
-      taginfo: videoData.taginfo ? JSON.parse(videoData.taginfo as string) : [],
-    };
-
-    // 设置页面标题
-    document.title = `${videoInfo.value.name} - 视频播放`;
-
-    // console.log("加载视频信息:", videoInfo.value);
+    try {
+      // 通过API获取视频详情
+      const response = await getVideoDetail(device, String(videoId));
+
+      if (response.status === 0 && response.data) {
+        const data = response.data;
+        videoInfo.value = {
+          id: data.id || videoId,
+          name: data.name || `视频 ${videoId}`,
+          cover: data.cover || "",
+          m3u8: data.m3u8 || "",
+          duration: data.duration || 0,
+          view: data.view || 0,
+          like: data.like || 0,
+          time: data.time || 0,
+          taginfo: data.tags
+            ? data.tags
+                .split(",")
+                .map((tag: string) => ({ name: tag.trim(), hash: tag.trim() }))
+            : [],
+        };
+
+        // 设置页面标题
+        document.title = `${videoInfo.value.name} - 视频播放`;
+      } else {
+        console.error("获取视频详情失败:", response.msg);
+        // 设置默认值
+        videoInfo.value = {
+          id: videoId,
+          name: `视频 ${videoId}`,
+          cover: "",
+          m3u8: "",
+          duration: 0,
+          view: 0,
+          like: 0,
+          time: 0,
+          taginfo: [],
+        };
+      }
+    } catch (error) {
+      console.error("获取视频详情失败:", error);
+      // 设置默认值
+      videoInfo.value = {
+        id: videoId,
+        name: `视频 ${videoId}`,
+        cover: "",
+        m3u8: "",
+        duration: 0,
+        view: 0,
+        like: 0,
+        time: 0,
+        taginfo: [],
+      };
+    }
   } else {
   } else {
     console.error("未找到视频ID");
     console.error("未找到视频ID");
   }
   }
@@ -429,9 +464,9 @@ const loadRelatedVideos = async () => {
   }
   }
 };
 };
 
 
-onMounted(() => {
-  loadVideoInfo();
-  loadRelatedVideos();
+onMounted(async () => {
+  await loadVideoInfo();
+  await loadRelatedVideos();
 });
 });
 
 
 // 组件卸载时的清理工作已移至 VideoProcessor 组件
 // 组件卸载时的清理工作已移至 VideoProcessor 组件