sangkf vor 7 Monaten
Ursprung
Commit
26239e2f0d
1 geänderte Dateien mit 101 neuen und 4 gelöschten Zeilen
  1. 101 4
      src/components/VideoPlayer.vue

+ 101 - 4
src/components/VideoPlayer.vue

@@ -7,6 +7,15 @@
         controls
         autoplay
       ></video>
+      <!-- 添加播放状态指示器 -->
+      <div v-if="playStatus !== 'playing' && playStatus !== 'paused'" class="play-status-overlay">
+        <div class="status-indicator">
+          <div v-if="playStatus === 'loading'" class="loading-spinner"></div>
+          <div v-if="playStatus === 'buffering'" class="buffering-spinner"></div>
+          <div v-if="playStatus === 'error'" class="error-icon">!</div>
+          <div class="status-text">{{ playStatusText }}</div>
+        </div>
+      </div>
     </div>
     <div class="control-panel">
       <div class="format-decoder-options">
@@ -76,7 +85,24 @@ export default {
       vjsPlayer: null,
       videoFormat: 'flv',
       decoderType: 'auto',
-      showPlayButton: false
+      showPlayButton: false,
+      // 添加播放状态相关数据
+      playStatus: 'idle', // idle, loading, buffering, playing, paused, error
+      errorMessage: ''
+    }
+  },
+  computed: {
+    // 根据播放状态返回对应的文本
+    playStatusText() {
+      const statusMap = {
+        idle: '准备就绪',
+        loading: '加载中...',
+        buffering: '缓冲中...',
+        playing: '播放中',
+        paused: '已暂停',
+        error: `播放错误: ${this.errorMessage}`
+      };
+      return statusMap[this.playStatus] || '未知状态';
     }
   },
   methods: {
@@ -86,11 +112,18 @@ export default {
         return;
       }
       
+      // 设置加载状态
+      this.playStatus = 'loading';
+      this.errorMessage = '';
+      
       // 销毁之前的播放器实例
       this.destroyPlayer();
       
       const videoElement = this.$refs.videoElement;
       
+      // 添加通用事件监听
+      this.addVideoEventListeners(videoElement);
+      
       // 根据选择的格式和解码选项加载视频
       if (this.decoderType === 'hardware') {
         // 使用 video.js 进行硬件加速解码
@@ -113,6 +146,40 @@ export default {
       }
     },
     
+    // 添加视频事件监听器
+    addVideoEventListeners(videoElement) {
+      // 移除之前的事件监听器
+      videoElement.removeEventListener('playing', this.handlePlaying);
+      videoElement.removeEventListener('pause', this.handlePause);
+      videoElement.removeEventListener('waiting', this.handleWaiting);
+      videoElement.removeEventListener('error', this.handleError);
+      
+      // 添加新的事件监听器
+      videoElement.addEventListener('playing', this.handlePlaying);
+      videoElement.addEventListener('pause', this.handlePause);
+      videoElement.addEventListener('waiting', this.handleWaiting);
+      videoElement.addEventListener('error', this.handleError);
+    },
+    
+    // 事件处理函数
+    handlePlaying() {
+      this.playStatus = 'playing';
+    },
+    
+    handlePause() {
+      this.playStatus = 'paused';
+    },
+    
+    handleWaiting() {
+      this.playStatus = 'buffering';
+    },
+    
+    handleError(e) {
+      this.playStatus = 'error';
+      this.errorMessage = e.target.error ? e.target.error.message : '未知错误';
+      console.error('视频播放错误:', e);
+    },
+    
     loadWithoutDecoder() {
       const videoElement = this.$refs.videoElement;
       
@@ -126,9 +193,12 @@ export default {
         videoElement.load();
         videoElement.play().catch(e => {
           console.error('原生播放失败:', e);
+          this.playStatus = 'error';
+          this.errorMessage = '浏览器不支持直接播放此格式';
           alert('您的浏览器可能不支持直接播放此格式,请尝试启用解码器');
         });
-      } else if (this.videoFormat === 'hls' && videoElement.canPlayType('application/vnd.apple.mpegurl')) {
+      }
+      else if (this.videoFormat === 'hls' && videoElement.canPlayType('application/vnd.apple.mpegurl')) {
         // 某些浏览器(Safari)原生支持HLS
         videoElement.src = this.videoUrl;
         videoElement.addEventListener('loadedmetadata', () => {
@@ -178,11 +248,14 @@ export default {
           // 添加错误处理
           this.flvPlayer.on(flvjs.Events.ERROR, (errorType, errorDetail) => {
             console.error('FLV软件解码错误:', errorType, errorDetail);
+            this.playStatus = 'error';
+            this.errorMessage = `FLV解码错误: ${errorType}`;
             
             // 尝试恢复播放
             if (errorType === flvjs.ErrorTypes.NETWORK_ERROR) {
               setTimeout(() => {
                 console.log('尝试重新加载视频...');
+                this.playStatus = 'loading';
                 this.flvPlayer.unload();
                 this.flvPlayer.load();
                 this.flvPlayer.play();
@@ -191,6 +264,7 @@ export default {
               // 媒体错误,尝试重新创建播放器
               setTimeout(() => {
                 console.log('尝试重新创建播放器...');
+                this.playStatus = 'loading';
                 this.destroyPlayer();
                 this.loadWithSoftwareDecoder();
               }, 2000);
@@ -199,11 +273,16 @@ export default {
           
           this.flvPlayer.play().catch(e => {
             console.error('软件解码播放失败:', e);
+            this.playStatus = 'error';
+            this.errorMessage = '软件解码播放失败';
           });
         } else {
+          this.playStatus = 'error';
+          this.errorMessage = '浏览器不支持FLV视频播放';
           alert('您的浏览器不支持FLV视频播放');
         }
-      } else if (this.videoFormat === 'hls') {
+      }
+      else if (this.videoFormat === 'hls') {
         // HLS 软件解码
         if (Hls.isSupported()) {
           this.hlsPlayer = new Hls({
@@ -287,8 +366,16 @@ export default {
       
       // 错误处理
       this.vjsPlayer.on('error', () => {
-        console.error('VideoJS 播放错误:', this.vjsPlayer.error());
+        const error = this.vjsPlayer.error();
+        console.error('VideoJS 播放错误:', error);
+        this.playStatus = 'error';
+        this.errorMessage = `VideoJS错误: ${error ? error.message : '未知错误'}`;
       });
+      
+      // 添加播放状态监听
+      this.vjsPlayer.on('playing', this.handlePlaying);
+      this.vjsPlayer.on('pause', this.handlePause);
+      this.vjsPlayer.on('waiting', this.handleWaiting);
     },
     
     getVideoJSType() {
@@ -420,9 +507,19 @@ export default {
       
       const videoElement = this.$refs.videoElement;
       if (videoElement) {
+        // 移除事件监听器
+        videoElement.removeEventListener('playing', this.handlePlaying);
+        videoElement.removeEventListener('pause', this.handlePause);
+        videoElement.removeEventListener('waiting', this.handleWaiting);
+        videoElement.removeEventListener('error', this.handleError);
+        
         videoElement.src = '';
         videoElement.removeAttribute('src');
       }
+      
+      // 重置播放状态
+      this.playStatus = 'idle';
+      this.errorMessage = '';
     }
   },
   beforeDestroy() {