当前位置:   article > 正文

Vue项目使用Video.js播放m3u8格式音(视)频流_vue video.js 播放m3u8

vue video.js 播放m3u8

记录工作中遇到的问题

需求:点击播放按钮显示弹层,在弹层上播放m3u8格式的音频流 

效果如下:

点击父组件的播放按钮

弹层显示出来,播放音频流(背景图片是我自己加的)

使用步骤: 

1.安装video.js和videojs-contrib-hls

  1. npm i video.js
  2. npm i videojs-contrib-hls

2.组件中引入

  1. import videojs from 'video.js'
  2. import 'video.js/dist/video-js.css'
  3. import 'videojs-contrib-hls'

3.准备一个video容器

  1. <video
  2. id="my-video"
  3. class="video-js vjs-default-skin vjs-big-play-centered"
  4. controls
  5. preload="auto"
  6. style='width: 100%;height: auto'
  7. :poster="poster"
  8. ></video>

4.初始化video.js(此处可以进行播放器的配置网上有很多)

  1. methods:{
  2. // 初始化videojs
  3. getVideo () {
  4. this.myVideo = videojs(
  5. 'my-video',
  6. {
  7. // autoplay: false, // 自动播放
  8. // loop: true, // 循环播放
  9. controls: true, // 控制元件
  10. width: 500, // 视频播放器显示的宽度
  11. height: 300, // 视频播放器显示的高度
  12. preload: 'none',
  13. bigPlayButton: true,
  14. posterImage: false,
  15. textTrackDisplay: false,
  16. errorDisplay: false,
  17. controlBar: true,
  18. sources: [{
  19. src: this.audioSrc,
  20. type: 'application/x-mpegURL'
  21. }]
  22. },
  23. function () {
  24. this.play()
  25. }
  26. )
  27. }
  28. }
  29. // 一进来就调用方法初始化video.js
  30. mounted() {
  31. this.getVideo()
  32. }

我的代码 :

1.子组件(弹层)代码

  1. <template>
  2. <!-- 此处显示隐藏使用v-show,不要用v-if -->
  3. <div class="modal-bg" v-show="show">
  4. <div class="modal-container">
  5. <div class="modal-header">音频播放</div>
  6. <hr />
  7. <div class="modal-main">
  8. <slot>
  9. <!-- 默认数据 -->
  10. <video id="my-video" class="video-js vjs-default-skin"></video>
  11. </slot>
  12. </div>
  13. <hr />
  14. <div class="modal-footer">
  15. <button @click="hideModal">关闭</button>
  16. </div>
  17. </div>
  18. </div>
  19. </template>
  20. <script>
  21. // 需要用video.js 和 hls
  22. import videojs from 'video.js'
  23. import 'video.js/dist/video-js.css'
  24. import 'videojs-contrib-hls'
  25. import StreamApi from '@/api/stream'
  26. export default {
  27. props: {
  28. show: {
  29. type: Boolean,
  30. default: false
  31. }
  32. },
  33. data () {
  34. return {
  35. // 配置项
  36. myVideo: null,
  37. audioSrc: 'http://208.241.129.64:8080/live/output.m3u8'
  38. }
  39. },
  40. methods: {
  41. async getUrl () {
  42. const { data } = await StreamApi.GetUrl.post()
  43. console.log('获取流地址: ', data.streamUrl)
  44. },
  45. // 取消
  46. hideModal () {
  47. // 关闭弹层,销毁videojs
  48. this.$emit('hideModal')
  49. this.myVideo.dispose()
  50. },
  51. // 初始化videojs
  52. getVideo () {
  53. this.myVideo = videojs(
  54. 'my-video',
  55. {
  56. // autoplay: false, // 自动播放
  57. // loop: true, // 循环播放
  58. controls: true, // 控制元件
  59. width: 500, // 视频播放器显示的宽度
  60. height: 300, // 视频播放器显示的高度
  61. preload: 'none',
  62. bigPlayButton: true,
  63. posterImage: false,
  64. textTrackDisplay: false,
  65. errorDisplay: false,
  66. controlBar: true,
  67. sources: [{
  68. src: this.audioSrc,
  69. type: 'application/x-mpegURL'
  70. }]
  71. },
  72. function () {
  73. this.play()
  74. }
  75. )
  76. }
  77. }
  78. }
  79. </script>
  80. <style lang="less" scoped>
  81. // 弹层样式
  82. /deep/ #my-video {
  83. background-image: url('~@/assets/audio-img.png');
  84. background-repeat: no-repeat;
  85. background-size: contain;
  86. /*兼容浏览器版本*/
  87. -webkit-background-size: contain;
  88. -o-background-size: contain;
  89. background-size: contain;
  90. z-index: 99;
  91. }
  92. // 隐藏掉一个报错按钮不让点击
  93. /deep/ .vjs-picture-in-picture-control {
  94. display: none !important;
  95. }
  96. // 遮罩
  97. .modal-bg {
  98. position: fixed;
  99. top: 0;
  100. left: 0;
  101. width: 100%;
  102. height: 100%;
  103. background: rgba(0, 0, 0, 0.5);
  104. z-index: 10;
  105. }
  106. // 内容
  107. .modal-container {
  108. position: fixed;
  109. top: 50%;
  110. left: 50%;
  111. transform: translate(-50%, -50%);
  112. background: #fff;
  113. border-radius: 6px;
  114. overflow: hidden;
  115. // min-width: 710px;
  116. // min-height: 520px;
  117. }
  118. .modal-header {
  119. padding-left: 30px;
  120. height: 55px;
  121. line-height: 60px;
  122. font-size: 16px;
  123. }
  124. .modal-footer {
  125. display: flex;
  126. align-items: center;
  127. padding-left: 480px;
  128. height: 55px;
  129. }
  130. .modal-footer button {
  131. margin-bottom: 10px;
  132. width: 80px;
  133. height: 33px;
  134. }
  135. .modal-main {
  136. min-height: 366px;
  137. padding: 33px 55px;
  138. }
  139. </style>

2.父组件代码

  1. <!-- 音频播放按钮 -->
  2. <a @click="play()">播放</a>
  1. <!-- 音频播放组件(弹层) -->
  2. <AudioModal ref="audio" :show="show" title="音频播放" @hideModal="show = false">
  3. <div ref="myBox"></div>
  4. </AudioModal>
  1. methods: {
  2. // 播放
  3. play () {
  4. // 打开弹层
  5. this.show = true
  6. // 准备video容器
  7. this.$refs.myBox.innerHTML = '<video id="my-video" class="video-js vjs-default-skin"></video>'
  8. // 点击时调用子组件内的方法,初始化video.js
  9. this.$refs.audio.getVideo()
  10. // 调用方法获取流地址
  11. this.$refs.audio.getUrl()
  12. }
  13. }

我遇到的报错:Uncaught (in promise) TypeError: The element or ID supplied is not valid. (videojs)

在我们正常使用的时候都是完全可以使用的,但是当我们有的时候需要把视频放在弹窗el-dialog里面显示时,可能会出现这个报错问题。

原因:刚进来时页面未找到相应组件,此时调用初始化video.js的方法就报错

解决:使用setTimeout延迟加载。如下:

  1. let _that = this;
  2. setTimeout(() => {
  3. _that.getVideo();
  4. }, 300);

但是在使用他的方法后我的问题并没有解决。

然后我就自己找了个简单的弹层,将弹层的显示隐藏改为v-show,然后在父组件播放按钮的点击事件里调用子组件的初始化video.js的方法 getVideo()。

 参考文章:范特西是只猫https://blog.csdn.net/qq_36410795/article/details/107109514

lucky-peachhttps://blog.csdn.net/little__SuperMan/article/details/89203270

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/79554
推荐阅读
相关标签
  

闽ICP备14008679号