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