vue hls 视频播放及跨域解决

备注:个人笔记
项目需要把增加一个 hls 流的视频播放,网上参考了其他博主的 (https://www.jianshu.com/p/ed997ac5ea12)
封装一个组件 hls-video.vue

<template>
    <div class="ali-player">
        <div class="main">
            <div class="video-center">
                <div v-if="!sourceUrls && !loadingVideo" class="tips">请选择视频源</div>
                <div v-if="waiting" class="tips">获取视频中,请稍等...</div>
                <div v-if="!hls" class="video" v-loading="loadingVideo" style="background-color: #0c0b0b"></div>
                <video v-show="hls" id="video" v-loading="loadingVideo" controls class="video" ref="video" style="background-color: #0c0b0b"></video>
            </div>
        </div>
    </div>
</template>
//    "hls.js": "^1.0.11", package.json 我用的版本
// 下载 npm install --save hls@1.0.11
import Hls from 'hls.js'; // 引入hls
export default {
    name: '',
    components: {},
    props: {
        sourceUrl: {
            type: String,
            default: '',
        },
        height: {
            type: String,
            default: '550px',
        },
    },
    data() {
        return {
            hls: null,
            sourceUrls: this.sourceUrl, //如果不赋值,在加载组件时会报错
            loadingVideo: false,
            waiting: false,
            reloadPlayTime: null, //当视频流获取超时定时器
        }
    },
    computed: {},
    watch: {
        sourceUrl: {
            handler(newVal, oldVal) {
                if (this.reloadPlayTime) {
                    //重新播放或者播放新视频时,清空定时器
                    console.log('清空定时器...')
                    this.videoPause()
                    clearTimeout(this.reloadPlayTime)
                }
                if (newVal && newVal !== oldVal) {
                    this.waiting = true
                    this.sourceUrls = newVal
                    this.playVideo()
                }
            },
            // 代表在wacth里声明了firstName这个方法之后立即先去执行handler方法
            immediate: false,
        },
    },
    created() {},
    mounted() {},
    methods: {
        playVideo() {
            this.$nextTick(() => [(this.loadingVideo = false)])
            if (Hls.isSupported()) {
                this.hls = new Hls()
                this.hls.loadSource(this.sourceUrls)
                this.hls.attachMedia(this.$refs.video)

                this.hls.on(Hls.Events.MANIFEST_PARSED, (event, data) => {
                    console.log(event, data)
                    console.log('playing...')
                    this.loadingVideo = false
                    this.waiting = false
                    this.$emit('playStatus', true) // 当点位存在播放地址时,可以截图
                    this.$refs.video.play()
                    /*  playSetTime = setTimeout(()=>{
                            clearTimeout(this.reloadPlayTime);
                        },3000)*/
                    //当正在播放时,取消定时器
                })
                let timerArr = []
                let delay = 5000
                this.hls.on(Hls.Events.ERROR, (event, data) => {
                    delay += 1000
                    console.log(event, data)
                    if (data.type === 'networkError') {
                        //网络故障
                        console.log('网络故障了...')
                        this.reloadPlayTime = setTimeout(() => {
                            this.$message.warning('获取视频失败,请重新播放...')
                            this.sourceUrls = ''
                            this.loadingVideo = false
                            this.waiting = false
                            this.disabledShot = true
                            this.$emit('playStatus', false)
                            this.videoPause()
                            // 监听出错事件
                        }, delay)
                        timerArr.push(this.reloadPlayTime)

                        if (timerArr.length > 1) {
                            //当视频播放中无法播放时,会多次执行Hls.Events.ERROR,因此需要处理一下定时器触发问题
                            for (let i = 1; i < timerArr.length; i++) {
                                clearTimeout(timerArr[i])
                                timerArr.splice(i, 1)
                            }
                        }
                        console.log(timerArr)
                    } else if (data.type === 'mediaError') {
                        //推流失败
                        //                            console.log("播放流断了....");
                    }
                })
            } else if (this.$refs.video.canPlayType('application/vnd.apple.mpegurl')) {
              
            }
        },
        // 停止流
        videoPause() {
            if (this.hls) {
                this.$refs.video.pause()
                this.hls.destroy()
                this.hls = null
            }
        },
    },
    beforeDestroy() {
        clearTimeout(this.reloadPlayTime)
        this.hls = null
    },
}

组件调用

<template>
	<HlsVideo :sourceUrl="hlsUrl1" v-if='isHls'/>
</template>
<script>
import { queryAll, getCamreaHls } from '@admin/api/kanban.js'
import HlsVideo from './hls-video/hls-video.vue'
import Hls from 'hls.js'

export default {
    name: 'monitoring-video',
    components: { HlsVideo },
    data() {
        return {
          	isHls1: false, // 左侧是否为 hls
            hlsUrl1: '',

        }
    },
    mounted() {
        this.init()
    },
    methods: {
        changeVal(val) {
            console.log(val)
        },
        async init() {
        	// 自己的请求等等
        	// 上面做完了但是不知道视频是否正常播放,网上找了好多 hls在线播放的地址都不能播,
        	// http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8
            this.hlsUrl1= 'iphone/iphone/samples/bipbop/bipbopall.m3u8',//这里本地开发做了个转发代理
        },
    },
    beforeDestroy() {
        this.isHls1 = false// 不清除组件会一直加载资源
    },
}

</script>

做了个本地代理的 vueconfig.js

module.exports = {
	devServer:{
		   proxy: {
          '/iphone': {
              target: 'http://devimages.apple.com/', //这里后台的地址模拟的;应该填写你们真实的后台接口
              ws: true,
              changOrigin: true, //允许跨域
              pathRewrite: {
                  '^/iphone': '/',
              },
          },
      },
	}
}

// http://10.133.99.99:8011/ 生产环境 地址
// 地址为 : http://10.128.241.299:83/openUrl/gbzWtzi/live.m3u8 这个是生产正式的 地址
以为已经搞定了 但是生产地址 和 视频地址又不一样 那就配置ng了

// 线上我的地址
 function getCaption(obj) {
                var index = obj.lastIndexOf('openUrl')
                obj = obj.substring(index, obj.length)
                return obj
            } // 字符串截取
 // 播放地址要重组
 this.sourceUrl = 'http://110.133.99.99:8011/' + getCaption(data)

nginx.conf

    server{
        listen 8011;
        server_name  localhost;
            location /openUrl{
            proxy_pass http://10.128.241.245:299;
                types {
                    application/vnd.apple.mpegurl m3u8;
                    video/mp2t ts;
                }
                alias temp/hls;  
                expires -1; 
                add_header Access-Control-Allow-Headers X-Requested-With;
                add_header Access-Control-Allow-Methods GET,POST,OPTIONS; 
                add_header Access-Control-Allow-Origin *;
            }
    }

如有问题请提出,菜鸡一枚,自己记录好翻阅!

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值