赞
踩
记录工作中遇到的问题
需求:点击播放按钮显示弹层,在弹层上播放m3u8格式的音频流
效果如下:
点击父组件的播放按钮
弹层显示出来,播放音频流(背景图片是我自己加的)
1.安装video.js和videojs-contrib-hls
- npm i video.js
- npm i videojs-contrib-hls
2.组件中引入
- import videojs from 'video.js'
- import 'video.js/dist/video-js.css'
- import 'videojs-contrib-hls'
3.准备一个video容器
- <video
- id="my-video"
- class="video-js vjs-default-skin vjs-big-play-centered"
- controls
- preload="auto"
- style='width: 100%;height: auto'
- :poster="poster"
- ></video>
4.初始化video.js(此处可以进行播放器的配置网上有很多)
- methods:{
- // 初始化videojs
- getVideo () {
- this.myVideo = videojs(
- 'my-video',
- {
- // autoplay: false, // 自动播放
- // loop: true, // 循环播放
- controls: true, // 控制元件
- width: 500, // 视频播放器显示的宽度
- height: 300, // 视频播放器显示的高度
- preload: 'none',
- bigPlayButton: true,
- posterImage: false,
- textTrackDisplay: false,
- errorDisplay: false,
- controlBar: true,
- sources: [{
- src: this.audioSrc,
- type: 'application/x-mpegURL'
- }]
- },
- function () {
- this.play()
- }
- )
- }
- }
-
- // 一进来就调用方法初始化video.js
- mounted() {
- this.getVideo()
- }

1.子组件(弹层)代码
- <template>
- <!-- 此处显示隐藏使用v-show,不要用v-if -->
- <div class="modal-bg" v-show="show">
- <div class="modal-container">
- <div class="modal-header">音频播放</div>
- <hr />
- <div class="modal-main">
- <slot>
- <!-- 默认数据 -->
- <video id="my-video" class="video-js vjs-default-skin"></video>
- </slot>
- </div>
- <hr />
- <div class="modal-footer">
- <button @click="hideModal">关闭</button>
- </div>
- </div>
- </div>
- </template>
-
- <script>
- // 需要用video.js 和 hls
- import videojs from 'video.js'
- import 'video.js/dist/video-js.css'
- import 'videojs-contrib-hls'
- import StreamApi from '@/api/stream'
-
- export default {
- props: {
- show: {
- type: Boolean,
- default: false
- }
- },
- data () {
- return {
- // 配置项
- myVideo: null,
- audioSrc: 'http://208.241.129.64:8080/live/output.m3u8'
- }
- },
- methods: {
- async getUrl () {
- const { data } = await StreamApi.GetUrl.post()
- console.log('获取流地址: ', data.streamUrl)
- },
- // 取消
- hideModal () {
- // 关闭弹层,销毁videojs
- this.$emit('hideModal')
- this.myVideo.dispose()
- },
- // 初始化videojs
- getVideo () {
- this.myVideo = videojs(
- 'my-video',
- {
- // autoplay: false, // 自动播放
- // loop: true, // 循环播放
- controls: true, // 控制元件
- width: 500, // 视频播放器显示的宽度
- height: 300, // 视频播放器显示的高度
- preload: 'none',
- bigPlayButton: true,
- posterImage: false,
- textTrackDisplay: false,
- errorDisplay: false,
- controlBar: true,
- sources: [{
- src: this.audioSrc,
- type: 'application/x-mpegURL'
- }]
- },
- function () {
- this.play()
- }
- )
- }
- }
- }
- </script>
-
- <style lang="less" scoped>
- // 弹层样式
- /deep/ #my-video {
- background-image: url('~@/assets/audio-img.png');
- background-repeat: no-repeat;
- background-size: contain;
- /*兼容浏览器版本*/
- -webkit-background-size: contain;
- -o-background-size: contain;
- background-size: contain;
- z-index: 99;
- }
- // 隐藏掉一个报错按钮不让点击
- /deep/ .vjs-picture-in-picture-control {
- display: none !important;
- }
- // 遮罩
- .modal-bg {
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background: rgba(0, 0, 0, 0.5);
- z-index: 10;
- }
- // 内容
- .modal-container {
- position: fixed;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- background: #fff;
- border-radius: 6px;
- overflow: hidden;
- // min-width: 710px;
- // min-height: 520px;
- }
- .modal-header {
- padding-left: 30px;
- height: 55px;
- line-height: 60px;
- font-size: 16px;
- }
- .modal-footer {
- display: flex;
- align-items: center;
- padding-left: 480px;
- height: 55px;
- }
- .modal-footer button {
- margin-bottom: 10px;
- width: 80px;
- height: 33px;
- }
- .modal-main {
- min-height: 366px;
- padding: 33px 55px;
- }
- </style>

2.父组件代码
- <!-- 音频播放按钮 -->
- <a @click="play()">播放</a>
- <!-- 音频播放组件(弹层) -->
- <AudioModal ref="audio" :show="show" title="音频播放" @hideModal="show = false">
- <div ref="myBox"></div>
- </AudioModal>
- methods: {
- // 播放
- play () {
- // 打开弹层
- this.show = true
- // 准备video容器
- this.$refs.myBox.innerHTML = '<video id="my-video" class="video-js vjs-default-skin"></video>'
- // 点击时调用子组件内的方法,初始化video.js
- this.$refs.audio.getVideo()
- // 调用方法获取流地址
- this.$refs.audio.getUrl()
- }
- }
我遇到的报错:Uncaught (in promise) TypeError: The element or ID supplied is not valid. (videojs)
在我们正常使用的时候都是完全可以使用的,但是当我们有的时候需要把视频放在弹窗
el-dialog
里面显示时,可能会出现这个报错问题。原因:刚进来时页面未找到相应组件,此时调用初始化video.js的方法就报错
解决:使用
setTimeout
延迟加载。如下:
- let _that = this;
- setTimeout(() => {
- _that.getVideo();
- }, 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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。