web前端(Vue2.x)接收H264实时视频码流(二进制)进行播放

发布时间 2023-10-28 21:10:23作者: yw3692582

1、安装 jmuxer

npm install jmuxer@2.0.5

2、.vue文件中使用

<template>
 <div>
  <video id="dom_id" muted="muted" controls class="video_box"></video>
  <div
   v-if="!has_data"
   v-loading="!has_data && player"
   element-loading-text="加载中"
   element-loading-spinner="el-icon-loading"
   element-loading-background="rgba(0, 0, 0, 1)"
   id="backgroud_color"
  ></div>
 </div>
</template>

<script>
import JMuxer from 'jmuxer'
export default {
 name: 'Video',
 data() {
  return {
   ws: null,
   video: null,
   player: null,
   has_data: false,
  }
 },
 methods: {
  // 初始化 websocket
  initWebSocket() {
   let wsuri = 'ws://127.0.0.1:8080'
   this.ws = new WebSocket(wsuri)
   this.ws.binaryType = 'arraybuffer'
   this.ws.onopen = this.websocketonopen
   this.ws.onmessage = this.websocketonmessage
   this.ws.onerror = this.websocketonerror
   this.ws.onclose = this.websocketclose
  },
  // 连接成功的回调
  websocketonopen() {
   console.log('连接成功')
   setTimeout(() => {
    this.handle_preview('start_preview')
   }, 300)
  },
  // 开始/结束预览
  handle_preview(cmd) {
   let send_data = {
    cmd,
    taskname: "测试",
   }
   this.init_player()
   this.ws.send(JSON.stringify(send_data))
  },
  // 接收到的数据
  websocketonmessage(e) {
   let re_msg = e.data
   if (re_msg instanceof Object) {
    // 二进制时往video中push
    console.log(`二进制`)
    try {
     this.player.feed({
      video: new Uint8Array(re_msg),
     })
    } catch (err) {}
   } else {
    // 判断是否成功
    re_msg = JSON.parse(re_msg)
    console.log('字符串')
    switch (re_msg.cmd) {
     case 'preview_status':
      if (re_msg.code != 200) return this.layer_msg(re_msg.msg)
      break
    }
   }
  },
  // 弹窗提示
  layer_msg(msg) {
   this.$notify({
    type: 'warning',
    showClose: true,
    title: '提示',
    dangerouslyUseHTMLString: true,
    message: msg,
    position: 'top-right',
    duration: 3000,
   })
  },
  // 初始化播放器
  init_player() {
   this.player = new JMuxer({
    node: "video_box",
    mode: 'video',
    flushingTime: 30,
    maxDelay: 16,
    clearBuffer: true,
    debug: false,
    onReady: () => {
     return this.get_paused()
    },
   })
  },
  // 获取是否在播放的状态
  get_paused() {
   this.video = document.getElementById("video_box")
   if (this.video.paused) {
    this.video.click()
    this.video.play()
    this.toggle_bg()
   } else {
    setTimeout(() => {
     return this.get_paused()
    }, 300)
   }
  },
  // 切换黑色背景显隐
  toggle_bg() {
   let timer = setInterval(() => {
    if (this.video.currentTime > 0) {
     clearInterval(timer)
     this.has_data = true
     this.video.currentTime = 0 // 不要去掉,作用重要
    } else {
     this.has_data = false
    }
   }, 1000)
  },
  // websocket 连接中断
  websocketonerror(e) {
   console.log('error', e)
  },
  //   websocket 断开
  websocketclose(e) {
   console.log('断开连接')
  },
  // 手动关闭ws
  close_ws() {
   console.log('关闭', this.ws)
   if (this.ws && this.ws.readyState == 1) {
    // 停止预览
    this.handle_preview('stop_preview')
    this.video.src = null
    this.player.destroy()
    this.player = null
    this.has_data = false
    this.ws.close()
    this.ws = null
   }
  },
 },
 mounted() {},
}
</script>

<style lang="scss" scoped>
.video_box {
 width: 100%;
 height: 480px;
 border-radius: 8px;
}
#backgroud_color {
 position: absolute;
 background: black;
 width: 100%;
 height: 480px;
 right: 0;
 top: 0;
 border-radius: 8px;
}
video::-webkit-media-controls {
 /*禁用播放器控制栏的样式*/
 display: none !important;
}
</style>