LivePlayerWrapper.vue 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. <template>
  2. <div ref="videoEl" class="live-player-wrapper" style="width: 100%; height: 100%">
  3. <live-player ref="player" :video-url="src" live stretch autoplay muted controls style="width: 100%; height: 100%" @error="handleError" />
  4. </div>
  5. </template>
  6. <script setup lang="ts">
  7. import LivePlayer from '@liveqing/liveplayer-v3';
  8. import { useDrag } from '/@/hooks/event/useDrag';
  9. import { onBeforeUnmount, onMounted, onUnmounted, ref } from 'vue';
  10. // 注册组件
  11. defineProps<{
  12. src: string;
  13. }>();
  14. const videoEl = ref<HTMLElement | null>(null);
  15. const player = ref<LivePlayer | null>(null);
  16. let retryCount = 0;
  17. const maxRetry = 30; // 最大重试次数
  18. const retryInterval = 3000; // 重试间隔(毫秒)
  19. let timer: NodeJS.Timeout | null = null;
  20. function handleError(err) {
  21. if (retryCount < maxRetry) {
  22. retryCount++;
  23. console.log(`第 ${retryCount} 次重试...`);
  24. timer = setTimeout(() => {
  25. if (player.value && player.value.play) player.value.play();
  26. }, retryInterval);
  27. } else {
  28. console.error('重试次数已达上限,停止重连');
  29. // 可在此处显示“连接失败,请刷新”提示
  30. showReconnectButton();
  31. }
  32. }
  33. function showReconnectButton() {
  34. if (player.value)
  35. player.value.innerHTML = `
  36. <div style="color: white; text-align: center; padding: 20px;">
  37. 视频连接失败<br>
  38. <button onclick="location.reload()" style="margin-top: 10px; padding: 8px 16px;">点击重试</button>
  39. </div>
  40. `;
  41. }
  42. onMounted(() => {
  43. if (videoEl.value) useDrag(videoEl.value);
  44. });
  45. onBeforeUnmount(() => {
  46. if (timer) clearTimeout(timer);
  47. if (player.value && player.value.destroy) player.value.destroy();
  48. if (player.value && player.value.remove) player.value.remove();
  49. });
  50. </script>
  51. <style scoped>
  52. /* 断流重连时避免 video.js 黑色 poster/modal 突然压暗画面 */
  53. .live-player-wrapper :deep(.vjs-modal-dialog),
  54. .live-player-wrapper :deep(.vjs-loading-spinner),
  55. .live-player-wrapper :deep(.vjs-big-play-button),
  56. .live-player-wrapper :deep(.vjs-poster) {
  57. display: none !important;
  58. opacity: 0 !important;
  59. visibility: hidden !important;
  60. pointer-events: none !important;
  61. }
  62. .live-player-wrapper :deep(video),
  63. .live-player-wrapper :deep(.video-js) {
  64. opacity: 1 !important;
  65. }
  66. </style>