vue-aliplayer 阿里云播放器适配 vue

阿里云播放器本身没对 vue 进行专门优化,以下借助 github 上一个库进行优化

官网

vue-aliplayer

插件源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
<template>
  <div class='prism-player' :id='playerId' :style='playStyle'></div>
</template>

<script>
  export default {
    name: 'Aliplayer',
    props: {
      playStyle: {
        type: String,
        default: ''
      },
      aliplayerSdkPath: {
        // Aliplayer 代码的路径
        type: String,
        default: '//g.alicdn.com/de/prismplayer/2.6.0/aliplayer-min.js'
      },
      autoplay: {
        type: Boolean,
        default: false
      },
      isLive: {
        type: Boolean,
        default: false
      },
      playsinline: {
        type: Boolean,
        default: false
      },
      width: {
        type: String,
        default: '100%'
      },
      height: {
        type: String,
        default: '320px'
      },
      controlBarVisibility: {
        type: String,
        default: 'always'
      },
      useH5Prism: {
        type: Boolean,
        default: false
      },
      useFlashPrism: {
        type: Boolean,
        default: false
      },
      vid: {
        type: String,
        default: ''
      },
      playauth: {
        type: String,
        default: ''
      },
      source: {
        type: String,
        default: ''
      },
      cover: {
        type: String,
        default: ''
      },
      format: {
        type: String,
        default: 'm3u8'
      },
      x5_video_position: {
        type: String,
        default: 'top'
      },
      x5_type: {
        type: String,
        default: 'h5'
      },
      x5_fullscreen: {
        type: Boolean,
        default: false
      },
      x5_orientation: {
        type: Number,
        default: 2
      },
      autoPlayDelay: {
        type: Number,
        default: 0
      },
      autoPlayDelayDisplayText: {
        type: String
      }
    },
    data () {
      return {
        playerId: 'aliplayer_' + Math.random() * 100000000000000000,
        scriptTagStatus: 0,
        instance: null
      }
    },
    created () {
      if (window.Aliplayer !== undefined) {
        // 如果全局对象存在,说明编辑器代码已经初始化完成,直接加载编辑器
        this.scriptTagStatus = 2
        this.initAliplayer()
      } else {
        // 如果全局对象不存在,说明编辑器代码还没有加载完成,需要加载编辑器代码
        this.insertScriptTag()
      }
    },
    mounted () {
      if (window.Aliplayer !== undefined) {
        // 如果全局对象存在,说明编辑器代码已经初始化完成,直接加载编辑器
        this.scriptTagStatus = 2
        this.initAliplayer()
      } else {
        // 如果全局对象不存在,说明编辑器代码还没有加载完成,需要加载编辑器代码
        this.insertScriptTag()
      }
    },
    methods: {
      insertScriptTag () {
        const _this = this
        let playerScriptTag = document.getElementById('playerScriptTag')
        // 如果这个tag不存在,则生成相关代码tag以加载代码
        if (playerScriptTag === null) {
          playerScriptTag = document.createElement('script')
          playerScriptTag.type = 'text/javascript'
          playerScriptTag.src = this.aliplayerSdkPath
          playerScriptTag.id = 'playerScriptTag'
          let s = document.getElementsByTagName('head')[0]
          s.appendChild(playerScriptTag)
        }
        if (playerScriptTag.loaded) {
          _this.scriptTagStatus++
        } else {
          playerScriptTag.addEventListener('load', () => {
            _this.scriptTagStatus++
            playerScriptTag.loaded = true
            _this.initAliplayer()
          })
        }
        _this.initAliplayer()
      },
      initAliplayer () {
        const _this = this
        // scriptTagStatus 为 2 的时候,说明两个必需引入的 js 文件都已经被引入,且加载完成
        if (_this.scriptTagStatus === 2 && _this.instance === null) {
          // Vue 异步执行 DOM 更新,这样一来代码执行到这里的时候可能 template 里面的 script 标签还没真正创建
          // 所以,我们只能在 nextTick 里面初始化 Aliplayer
          _this.$nextTick(() => {
            _this.instance = window.Aliplayer({
              id: _this.playerId,
              autoplay: _this.autoplay,
              isLive: _this.isLive,
              playsinline: _this.playsinline,
              format: _this.format,
              width: _this.width,
              height: _this.height,
              controlBarVisibility: _this.controlBarVisibility,
              useH5Prism: _this.useH5Prism,
              useFlashPrism: _this.useFlashPrism,
              vid: _this.vid,
              playauth: _this.playauth,
              source: _this.source,
              cover: _this.cover,
              x5_video_position: _this.x5_video_position,
              x5_type: _this.x5_type,
              x5_fullscreen: _this.x5_fullscreen,
              x5_orientation: _this.x5_orientation,
              autoPlayDelay: _this.autoPlayDelay,
              autoPlayDelayDisplayText: _this.autoPlayDelayDisplayText
            })
            // 绑定事件,当 AliPlayer 初始化完成后,将编辑器实例通过自定义的 ready 事件交出去
            _this.instance.on('ready', () => {
              this.$emit('ready', _this.instance)
            })
            _this.instance.on('play', () => {
              this.$emit('play', _this.instance)
            })
            _this.instance.on('pause', () => {
              this.$emit('pause', _this.instance)
            })
            _this.instance.on('ended', () => {
              this.$emit('ended', _this.instance)
            })
            _this.instance.on('liveStreamStop', () => {
              this.$emit('liveStreamStop', _this.instance)
            })
            _this.instance.on('m3u8Retry', () => {
              this.$emit('m3u8Retry', _this.instance)
            })
            _this.instance.on('hideBar', () => {
              this.$emit('hideBar', _this.instance)
            })
            _this.instance.on('waiting', () => {
              this.$emit('waiting', _this.instance)
            })
            _this.instance.on('snapshoted', () => {
              this.$emit('snapshoted', _this.instance)
            })
          })
        }
      },
      /**
       * 播放视频
       */
      play: function () {
        this.instance.play()
      },
      /**
       * 暂停视频
       */
      pause: function () {
        this.instance.pause()
      },
      /**
       * 重播视频
       */
      replay: function () {
        this.instance.replay()
      },
      /**
       * 跳转到某个时刻进行播放
       * @argument time 的单位为秒
       */
      seek: function (time) {
        this.instance.seek(time)
      },
      /**
       * 获取当前时间 单位秒
       */
      getCurrentTime: function () {
        return this.instance.getCurrentTime()
      },
      /**
       *获取视频总时长,返回的单位为秒
       * @returns 返回的单位为秒
       */
      getDuration: function () {
        return this.instance.getDuration()
      },
      /**
       获取当前的音量,返回值为0-1的实数ios和部分android会失效
       */
      getVolume: function () {
        return this.instance.getVolume()
      },
      /**
       设置音量,vol为0-1的实数,ios和部分android会失效
       */
      setVolume: function (vol) {
        this.instance.setVolume(vol)
      },
      /**
       *直接播放视频url,time为可选值(单位秒)目前只支持同种格式(mp4/flv/m3u8)之间切换暂不支持直播rtmp流切换
       *@argument url 视频地址
       *@argument time 跳转到多少秒
       */
      loadByUrl: function (url, time) {
        this.instance.loadByUrl(url, time)
      },
      /**
       * 设置播放速度
       *@argument speed 速度
       */
      setSpeed: function (speed) {
        this.instance.setSpeed(speed)
      },
      /**
       * 设置播放器大小w,h可分别为400px像素或60%百分比chrome浏览器下flash播放器分别不能小于397x297
       *@argument w 播放器宽度
       *@argument h 播放器高度
       */
      setPlayerSize: function (w, h) {
        this.instance.setPlayerSize(w, h)
      },
      /**
       * 目前只支持HTML5界面上的重载功能,暂不支持直播rtmp流切换m3u8)之间切换,暂不支持直播rtmp流切换
       *@argument vid 视频id
       *@argument playauth 播放凭证
       */
      reloaduserPlayInfoAndVidRequestMts: function (vid, playauth) {
        this.instance.reloaduserPlayInfoAndVidRequestMts(vid, playauth)
      }
    }
  }
</script>

<style>
  @import url(//g.alicdn.com/de/prismplayer/2.6.0/skins/default/aliplayer-min.css);
</style>

组件封装

  1. 插件本身属性过多,正常开发中不一定用得到,因此对插件进行再一次封装为组件,方便程序调用及适当扩展
  2. 该组件主要实现了一下功能
    1. 播放器高度自适应
    2. 自动获取视频播放地址,播放地址的实现参见 Java + jQuery 实现阿里云点播
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<template>
  <ali-player v-if="playAuth" :vid="vid" :playauth="playAuth" :height="height"></ali-player>
</template>

<script type="text/ecmascript-6">
  import aliPlayer from './ali-player/ali-player'

  export default {
    name: 'in-video',
    props: {
      vid: {
        type: String,
        default: '0'
      }
    },
    data () {
      return {
        playAuth: ''
      }
    },
    watch: {
      'vid' (val) {
        this._getPlayAuth(val)
      }
    },
    computed: {
      // 高度自适应
      height () {
        let width = document.documentElement.clientWidth

        return `${width / 1.7777778}px`
      }
    },
    methods: {
      // 获取视频鉴权地址
      _getPlayAuth (val) {
        this.$fetch.video.auth({
          videoId: val
        }).then((res) => {
          this.playAuth = res.data
        })
      }
    },
    components: {
      aliPlayer
    }
  }
</script>

<style lang="stylus" rel="stylesheet/stylus">

</style>