index.vue 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. <template>
  2. <div class="player-box">
  3. <video ref="videoRef" :autoplay="autoPlay" :controls="controls" :muted="muted" />
  4. <div v-show="isLoading" class="loader" />
  5. </div>
  6. </template>
  7. <script lang="ts" setup name="FlvVideo">
  8. import flvjs from 'flv.js';
  9. const props = defineProps({
  10. videoUrl: {
  11. require: true,
  12. default: () => ''
  13. },
  14. autoPlay: {
  15. type: Boolean,
  16. default: false
  17. },
  18. muted: {
  19. type: Boolean,
  20. default: true
  21. },
  22. controls: {
  23. type: Boolean,
  24. default: false
  25. }
  26. });
  27. const emits = defineEmits(['onPlaying', 'onPlayError']);
  28. const videoRef = ref();
  29. let flvPlayer = ref();
  30. let isLoading = ref(false);
  31. // 播放视频
  32. const handleVideoPlay = () => {
  33. if (flvjs.isSupported()) {
  34. isLoading.value = true;
  35. if (flvPlayer.value) {
  36. flvPlayer.value.pause();
  37. flvPlayer.value.unload();
  38. flvPlayer.value.detachMediaElement();
  39. flvPlayer.value.destroy();
  40. }
  41. flvPlayer.value = flvjs.createPlayer(
  42. {
  43. type: 'flv',
  44. url: props.videoUrl
  45. },
  46. {
  47. cors: true, //是否跨域
  48. enableWorker: true, //是否多线程工作
  49. anableStashBuffer: false, //是否启用缓存
  50. autoCleanupSourceBuffer: true //是否自动缓存
  51. }
  52. );
  53. flvPlayer.value.attachMediaElement(videoRef.value);
  54. flvPlayer.value.load();
  55. flvPlayer.value.play();
  56. videoRef.value.addEventListener('playing', () => {
  57. isLoading.value = false; // 视频开始播放时关闭加载状态
  58. emits('onPlaying');
  59. });
  60. //报错重连
  61. flvPlayer.value.on(flvjs.Events.ERROR, (errType, errDetail) => {
  62. if (flvPlayer.value) {
  63. destoryVideo();
  64. }
  65. isLoading.value = false;
  66. emits('onPlayError');
  67. });
  68. }
  69. };
  70. const destoryVideo = () => {
  71. if (flvPlayer.value) {
  72. flvPlayer.value.pause();
  73. flvPlayer.value.unload();
  74. flvPlayer.value.detachMediaElement();
  75. flvPlayer.value.destroy();
  76. flvPlayer.value = null;
  77. }
  78. };
  79. onMounted(() => {
  80. if (props.autoPlay) {
  81. handleVideoPlay();
  82. }
  83. });
  84. defineExpose({
  85. handleVideoPlay,
  86. destoryVideo
  87. });
  88. </script>
  89. <style lang="scss" scoped>
  90. .player-box {
  91. position: relative;
  92. display: inline-flex;
  93. justify-content: center;
  94. align-items: center;
  95. background-color: #000;
  96. video {
  97. width: 100%;
  98. height: 100%;
  99. }
  100. .playWnd {
  101. z-index: 10;
  102. width: 100%;
  103. height: 100%;
  104. }
  105. .video-enlarge {
  106. width: 34px;
  107. height: 34px;
  108. position: absolute;
  109. top: 20px;
  110. right: 20px;
  111. z-index: 10;
  112. }
  113. .loader {
  114. position: absolute;
  115. z-index: 10;
  116. left: 50%;
  117. top: 50%;
  118. transform: translate(-50%, -50%);
  119. width: 32px;
  120. height: 32px;
  121. background: url('@/assets/images/video/ajax-loader.gif');
  122. }
  123. }
  124. </style>