Jelajahi Sumber

解决rtmp视频播放问题

liuwei 4 tahun lalu
induk
melakukan
d394563eed
4 mengubah file dengan 253 tambahan dan 20 penghapusan
  1. 1 0
      package.json
  2. 18 20
      src/renderer/components/BigShow.vue
  3. 229 0
      src/renderer/components/player.vue
  4. 5 0
      yarn.lock

+ 1 - 0
package.json

@@ -54,6 +54,7 @@
   "dependencies": {
     "axios": "^0.19.2",
     "element-ui": "^2.13.0",
+    "mux.js": "^5.6.2",
     "pubsub-js": "^1.7.0",
     "video.js": "^7.7.6",
     "videojs-flash": "^2.2.1",

+ 18 - 20
src/renderer/components/BigShow.vue

@@ -30,8 +30,9 @@
             >
                 <div ref="signal">
                     <video-player
+                            class="videostyle"
                             :options="playerOptions"
-                            style="width:100%;height:100%;object-fit: fill"
+                            :playsinline="true"
                     >
 
                     </video-player>
@@ -50,12 +51,11 @@
     import {mapState} from 'vuex'
     import draggable from 'vuedraggable'
     import VueDragResize from 'vue-drag-resize'
-    import 'video.js/dist/video-js.css'
-    import { videoPlayer } from 'vue-video-player'
 
     import '../assets/less/splitscreen.less'
     import {getElementLeft, getElementTop, getStaticFile} from "../../utils/tools"
     import {reqRefreshView} from "../api"
+    import VideoPlayer from "./player.vue"
 
     export default {
         data() {
@@ -63,29 +63,27 @@
                 isDragging: false, // 是否可拖动标志
                 divArr:[],// 默认大屏中盒子的数组
                 streamWindows:[], // 传递出去的信号源位置信息
-                playerOptions: { // 视频播放配置
-                    notSupportMessage: '此视频暂无法播放',
-                    fluid: true,
-                    playbackRates: [0.7, 1.0, 1.5, 2.0],
-                    sources: [
-                        /*{
-                            src: 'http://img-ys011.didistatic.com/static/didiglobal/do1_pcUZZjSG7vFlMbdr8fA6',
-                            type: 'video/mp4'
-                        },*/
-                        {
-                            src: 'rtmp://58.200.131.2:1935/livetv/hunantv',
-                            type: 'rtmp/flv'
-                        }
-                    ]
-                },
                 bigScreenJson:[],
+                playerOptions: {
+                    sources: [{
+                        type: "rtmp/flv",
+                        src: "rtmp://58.200.131.2:1935/livetv/hunantv"
+                    }],
+                    techOrder: ['flash'],
+                    autoplay: true,
+                    controls: true,
+                    fluid:true,
+                    preload: 'auto',
+                    notSupportedMessage: '此视频暂无法播放,请稍后再试',
+                    width: document.documentElement.clientWidth,
+                }
             }
         },
 
         components: {
             draggable,
             VueDragResize,
-            videoPlayer,
+            "video-player": VideoPlayer
         },
 
         async beforeCreate() {
@@ -162,7 +160,7 @@
                 this.streamWindows = newStreamWindows
                 // 调用大屏开窗接口
                 await reqRefreshView(data)
-            }
+            },
         },
 
         computed: {

+ 229 - 0
src/renderer/components/player.vue

@@ -0,0 +1,229 @@
+<template>
+  <div class="video-player" v-if="reseted">
+    <video class="video-js" ref="video"></video>
+  </div>
+</template>
+
+<script>
+  // lib
+  import _videojs from 'video.js'
+  const videojs = window.videojs || _videojs
+  import "videojs-flash"
+
+  // pollfill
+  if (typeof Object.assign != 'function') {
+    Object.defineProperty(Object, 'assign', {
+      value(target, varArgs) {
+        if (target == null) {
+          throw new TypeError('Cannot convert undefined or null to object')
+        }
+        const to = Object(target)
+        for (let index = 1; index < arguments.length; index++) {
+          const nextSource = arguments[index]
+          if (nextSource != null) {
+            for (const nextKey in nextSource) {
+              if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
+                to[nextKey] = nextSource[nextKey]
+              }
+            }
+          }
+        }
+        return to
+      },
+      writable: true,
+      configurable: true
+    })
+  }
+
+  // as of videojs 6.6.0
+  const DEFAULT_EVENTS = [
+    'loadeddata',
+    'canplay',
+    'canplaythrough',
+    'play',
+    'pause',
+    'waiting',
+    'playing',
+    'ended',
+    'error'
+  ]
+
+  // export
+  export default {
+    name: 'video-player',
+    props: {
+      start: {
+        type: Number,
+        default: 0
+      },
+      crossOrigin: {
+        type: String,
+        default: ''
+      },
+      playsinline: {
+        type: Boolean,
+        default: false
+      },
+      customEventName: {
+        type: String,
+        default: 'statechanged'
+      },
+      options: {
+        type: Object,
+        required: true
+      },
+      events: {
+        type: Array,
+        default: () => []
+      },
+      globalOptions: {
+        type: Object,
+        default: () => ({
+          // autoplay: false,
+          controls: true,
+          // preload: 'auto',
+          // fluid: false,
+          // muted: false,
+          controlBar: {
+            remainingTimeDisplay: false,
+            playToggle: {},
+            progressControl: {},
+            fullscreenToggle: {},
+            volumeMenuButton: {
+              inline: false,
+              vertical: true
+            }
+          },
+          techOrder: ['html5'],
+          plugins: {}
+        })
+      },
+      globalEvents: {
+        type: Array,
+        default: () => []
+      }
+    },
+    data() {
+      return {
+        player: null,
+        reseted: true
+      }
+    },
+    mounted() {
+      if (!this.player) {
+        this.initialize()
+      }
+    },
+    beforeDestroy() {
+      if (this.player) {
+        this.dispose()
+      }
+    },
+    methods: {
+      initialize() {
+
+        // videojs options
+        const videoOptions = Object.assign({}, this.globalOptions, this.options)
+
+        // ios fullscreen
+        if (this.playsinline) {
+          this.$refs.video.setAttribute('playsinline', this.playsinline)
+          this.$refs.video.setAttribute('webkit-playsinline', this.playsinline)
+          this.$refs.video.setAttribute('x5-playsinline', this.playsinline)
+          this.$refs.video.setAttribute('x5-video-player-type', 'h5')
+          this.$refs.video.setAttribute('x5-video-player-fullscreen', false)
+        }
+
+        // cross origin
+        if (this.crossOrigin !== '') {
+          this.$refs.video.crossOrigin = this.crossOrigin
+          this.$refs.video.setAttribute('crossOrigin', this.crossOrigin)
+        }
+
+        // emit event
+        const emitPlayerState = (event, value) => {
+          if (event) {
+            this.$emit(event, this.player)
+          }
+          if (value) {
+            this.$emit(this.customEventName, { [event]: value })
+          }
+        }
+
+        // avoid error "VIDEOJS: ERROR: Unable to find plugin: __ob__"
+        if (videoOptions.plugins) {
+          delete videoOptions.plugins.__ob__
+        }
+
+        // videoOptions
+        // console.log('videoOptions', videoOptions)
+
+        // player
+        const self = this
+        this.player = videojs(this.$refs.video, videoOptions, function() {
+
+          // events
+          const events = DEFAULT_EVENTS.concat(self.events).concat(self.globalEvents)
+
+          // watch events
+          const onEdEvents = {}
+          for (let i = 0; i < events.length; i++) {
+            if (typeof events[i] === 'string' && onEdEvents[events[i]] === undefined) {
+              (event => {
+                onEdEvents[event] = null
+                this.on(event, () => {
+                  emitPlayerState(event, true)
+                })
+              })(events[i])
+            }
+          }
+
+          // watch timeupdate
+          this.on('timeupdate', function() {
+            emitPlayerState('timeupdate', this.currentTime())
+          })
+
+          // player readied
+          self.$emit('ready', this)
+        })
+      },
+      dispose(callback) {
+        if (this.player && this.player.dispose) {
+          if (this.player.techName_ !== 'Flash') {
+            this.player.pause && this.player.pause()
+          }
+          this.player.dispose()
+          this.player = null
+          this.$nextTick(() => {
+            this.reseted = false
+            this.$nextTick(() => {
+              this.reseted = true
+              this.$nextTick(() => {
+                callback && callback()
+              })
+            })
+          })
+          /*
+          if (!this.$el.children.length) {
+            const video = document.createElement('video')
+            video.className = 'video-js'
+            this.$el.appendChild(video)
+          }
+          */
+        }
+      }
+    },
+    watch: {
+      options: {
+        deep: true,
+        handler(options, oldOptions) {
+          this.dispose(() => {
+            if (options && options.sources && options.sources.length) {
+              this.initialize()
+            }
+          })
+        }
+      }
+    }
+  }
+</script>

+ 5 - 0
yarn.lock

@@ -5886,6 +5886,11 @@ mux.js@5.5.1:
   resolved "https://registry.yarnpkg.com/mux.js/-/mux.js-5.5.1.tgz#5bd5d7b2e5e5560da8126928e93af3c532e08372"
   integrity sha512-5VmmjADBqS4++8pTI6poSRJ+chHdaoI4XErcQPM5w4QfwaDl+FQlSI0iOgWbYDn6CBCbDRKaSCcEiN2K5aHNGQ==
 
+mux.js@^5.6.2:
+  version "5.6.2"
+  resolved "https://registry.yarnpkg.com/mux.js/-/mux.js-5.6.2.tgz#1fd08042382b527750fbb5960129e92f838612bb"
+  integrity sha512-66+0HevBv12gJHmoMTbkQssPyiCOJNnm2XarYgUC6nj1DJ8WG0wLdinzMFq5vrbBmDxNNYYh+03Rp/QVzGiSQg==
+
 nan@^2.12.1:
   version "2.14.0"
   resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"