阿里云视频点播

1、视频播放

  • mixin混入 采用sts方式播放
  • accessKeyId accessKeySecret securityToken region 均为后端crypto加密配置,进行解密
  • skinLayout为皮肤配置栏,可删除对应组件,使用自定义组件components
  • 更多配置可查看阿里云播放器SDK--web播放器--属性和接口说明

1-1、main.js

//main.js
Vue.mixin({
  methods: {
    //创建视频
    $createPlayer(id, key, vid, picUrl) {
      key.accessKeyId = decrypt(key.accessKeyId)
      key.accessKeySecret = decrypt(key.accessKeySecret)
      key.securityToken = decrypt(key.securityToken)
      key.region = decrypt(key.region)
      return new Aliplayer({
        id,
        autoplay: false,
        width: "100%",
        //支持播放地址播放,此播放优先级最高
        // source,
        //播放方式四:使用STS方式播放
        vid,
        region: key.region,
        controlBarVisibility: "always",
        // vid: '10c0875db475494b891a8fc7f9b259d2',
        accessKeyId: key.accessKeyId,
        accessKeySecret: key.accessKeySecret,
        securityToken: key.securityToken,
        isLive: false,
        defaultDefinition: 'LD',
        cover: picUrl,
        controlBarVisibility: 'always',
        components: [{
          name: 'RateComponent',
          type: AliPlayerComponent.RateComponent,
        }, ],
        // https://help.aliyun.com/document_detail/62948.html#-
        skinLayout: [{
            name: 'bigPlayButton',
            align: 'blabs',
            x: 328,
            y: '50%'
          },
          {
            name: 'H5Loading',
            align: 'cc',
          },
          {
            name: 'errorDisplay',
            align: 'tlabs',
            x: 0,
            y: 0
          },
          {
            name: 'infoDisplay'
          },
          {
            name: 'tooltip',
            align: 'blabs',
            x: 0,
            y: 56
          }, // 悬浮在按钮上的提示
          {
            name: 'thumbnail'
          },
          {
            name: 'controlBar',
            align: 'blabs',
            x: 0,
            y: 0, // 控制视频的控件
            children: [{
                name: 'progress',
                align: 'blabs',
                x: 0,
                y: 44
              }, // 进度
              {
                name: 'playButton',
                align: 'tl',
                x: 15,
                y: 12
              }, // 播放按钮
              {
                name: 'timeDisplay',
                align: 'tl',
                x: 10,
                y: 7
              }, // 时间线
              // {
              //   name: 'fullScreenButton',
              //   align: 'tr',
              //   x: 10,
              //   y: 12
              // }, // 全屏按钮按钮
              // {name:"subtitle", align:"tr",x:5, y:12},                // 字幕
              // {name:"setting", align:"tr",x:15, y:12},                // 设置
              {
                name: 'volume',
                align: 'tr',
                x: 5,
                y: 10
              }, // 音量
              // {name: "snapshot", align: "tr", x: 5, y: 12 }
            ],
          },

        ],
        // components: [{
        //   name: 'ProgressComponent',
        //   type: ProgressComponent
        // }, ]
      }, )
    },
  }
})

1-2、相关页面播放(进度条不是很流畅,后期手写进度条videoProgress.js)

//相关页面播放
 if (this.player) {
        this.player.dispose() //销毁
        this.player = null
      }
      let list =this.videoList[this.videoIndex]
      this.videoKey = storage.get('videosts')
      this.player = this.$createPlayer('my_video', this.videoKey, list.videoId, list.picUrl)
      this.player.on('ended', (e) => {
        if (item) item.canClick = true
      })
      let progressPlaied = document.querySelector('.prism-progress-played')
      let currentText = document.querySelector('.prism-time-display .current-time')
      //快进快退10s
      document.onkeydown = (e) => {
        let videotimes = this.player.getDuration() //视频时长
        let playnum = Math.ceil(this.player.getCurrentTime()) //视频当前时间,单位:s
        if (e && e.keyCode === 37) {
          // 按 向左键
          playnum = parseInt(playnum - 10)
          if (playnum >= 0) {
            this.player.seek(playnum)
            progressPlaied.style.width = `${((playnum / videotimes) * 100).toFixed(6)}%`
          } else {
            this.player.seek(0)
            progressPlaied.style.width = 0
            currentText.innerText = '00:00'
          }
        } else if (e && e.keyCode === 39) {
          // 按 向右键
          playnum = parseInt(playnum + 10)
          if (playnum <= videotimes) {
            this.player.seek(playnum)
            progressPlaied.style.width = `${((playnum / videotimes) * 100).toFixed(6)}%`
          } else {
            this.player.seek(Math.ceil(videotimes))
            progressPlaied.style.width = `100%`
          }
        }
      }

2、富文本编辑器上传视频 (未完)

2-1、扩展视频按钮

// html
    <input
      type='file'
      style='display: none;'
      id='getVideoFile'
      @change="selectVideoSource($event)"
      multiple
      accept='video/*'
    >

// js 初始化编辑器中
      // 扩展视频按钮
      class InsertVideoMenu extends BtnMenu {
        constructor(editor) {
          const $elem = E.$(`<div class="w-e-menu" data-title="插入视频">
              <i class="iconfont">&#xe6c3;</i>
          </div>`);
          super($elem, editor);
        }
        // 菜单点击事件
        clickHandler() {
          var aPlayers = self.$refs.wangEditorContainer.getElementsByClassName('aliyun-video-player');
          if(aPlayers.length >= 10){
            self.$message.error('最多可添加10个视频')
          }else{
            document.getElementById('getVideoFile').click()
          }
        }
        tryChangeActive() {

        }
      }

3、上传视频

3-1、需求

  • 后台管理系统上传视频(可多个),上传时显示进度,上传完成显示视频标题。hover时可以选择删除
初始状态

视频上传中

上传成功

3-2、代码

html

  <el-form-item class="video-form-item" label="视频文件:">
          <div ref="videoBox" id="video-box">
            <!-- 添加的视频 -->
            <div class="item flex-box" v-for="(item, idx) in videoList" :key="idx">
              <div class="aliyun-video-player">
                <div v-if="item.progress == 100 || item.progress > 100">
                  <i class="el-icon-video-play"></i>
                  <div class="video-name">{{ item.videoName }}</div>
                  <div class="edit-player-tip">此处不支持视频播放</div>
                  <div class="edit-player-masker"></div>
                  <div class="aliyun-video-close-btn" @click="deleteVideo(item, idx)">
                    <span class="iconfont iconguanbi4"></span>
                  </div>
                </div>
                <div class="aliyun-video-progress-box" v-else>
                  <div class="current">{{ item.progress }}%</div>
                  <div class="aliyun-video-progress-total"><div class="aliyun-video-progress-current" :style="{ width: item.progress + '%' }"></div></div>
                </div>
              </div>
            </div>
            <!-- 视频上传 (input file的样式修改麻烦 uploadClick用于点击这个隐藏的input)-->
            <div class="upload-div" @click="uploadClick">
              <i class="el-icon-plus"></i>
              <p>点击上传视频</p>
            </div>
            <input type="file" style="display: none" id="getVideoFile" multiple accept="video/*" @change="selectVideoSource($event)" />
          </div>
        </el-form-item>

js

/*
*  上传SDK 详见官网 https://help.aliyun.com/document_detail/52204.html 视频信息,进度等均可以在回调中拿到
*   paramData -- 可以携带自己想要的信息 title:"标题",CateId:"分类ID", 
*   videoMap:判断所有上传是否结束的对象 { uid:boolean }
*/ 
// mounted 中根据正式环境的不同选择不同的分类
mounted() {
    this.CateId = window.location.host == '正式环境host' ? '2057' : '2056'
  },
// 上传视频
    selectVideoSource(e, insertVideoFn) {
      var file = e.target.files
      if (file.length > 0) {
        var large = file.length
        this.setJavascriptUpload(file, large)
        e.target.value = ''
      }
    },
    setJavascriptUpload(file, large) {
      // 初始化上传 
      this.toAliyunUpload()

      // 添加文件
      for (let i = 0; i < large; i++) {
        if (file[i].type.indexOf('video') < 0 && file[i].type.indexOf('flash') < 0) {
          this.$message.error('有一个文件格式不对')
          continue
        }
        // 视频文件过大
        if (file[i].size / 1024 / 1024 > 1 * 1024) {
          this.$message.error('有一个文件过大')
          continue
        }
        var uid = Math.random().toString().slice(2)
        var paramsData = {
          Vod: {
            Title: file[i].name,
            CateId: this.CateId, // 分类id
            uid: uid,
            TemplateGroupId: 'c9f0925ae6b5386c8681729d19985f47', // 指定转码模板组
          },
        }
        this.videoMap[uid] = false
        this.uploader.addFile(file[i], '', '', '', JSON.stringify(paramsData))
        let obj = {
          uid,
          progress: 0,
          videoName: '',
        }
        this.videoList.push(obj)
      }
      this.uploader.startUpload()
    },
    toAliyunUpload() {
      var self = this
      this.uploader = new AliyunUpload.Vod({
        userId: '245578911051344621',
        region: 'cn-shenzhen',
        //分片大小默认1 MB,不能小于100 KB
        partSize: 1048576,
        //并行上传分片个数,默认5
        parallel: 10,
        //网络原因失败时,重新上传次数,默认为3
        retryCount: 3,
        //网络原因失败时,重新上传间隔时间,默认为2秒
        retryDuration: 2,
        //是否上报上传日志到视频点播,默认为true
        enableUploadProgress: true,
        //开始上传
        onUploadstarted: function (uploadInfo) {
          //获取STSToken
          self.$api
            .getVideoStsToken()
            .then((res) => {
              if (res.data) {
                if (res.data.code == 200 && res.data.data) {
                  var data = res.data.data
                  self.sts = {
                    accessKeyId: decrypt(data.accessKeyId, ''),
                    accessKeySecret: decrypt(data.accessKeySecret, ''),
                    secretToken: decrypt(data.securityToken, ''),
                  }
                  self.uploader.setSTSToken(uploadInfo, self.sts.accessKeyId, self.sts.accessKeySecret, self.sts.secretToken)
                } else {
                  var uid = uploadInfo.videoInfo.uid
                  self.videoMap[uid] = true
                  self.videoList.forEach((item, idx) => {
                    if (item.uid == uid) {
                      self.videoList.splice(idx, 1)
                    }
                  })
                  self.$message.error(res.data.msg || '获取STSToken失败')
                }
              } else {
                var uid = uploadInfo.videoInfo.uid
                self.videoMap[uid] = true
                self.videoList.forEach((item, idx) => {
                  if (item.uid == uid) {
                    self.videoList.splice(idx, 1)
                  }
                })
                self.$message.error('一个视频上传失败')
              }
            })
            .catch((err) => {
              console.log(err)
              var uid = uploadInfo.videoInfo.uid
              self.videoMap[uid] = true
              self.videoList.forEach((item, idx) => {
                if (item.uid == uid) {
                  self.videoList.splice(idx, 1)
                }
              })
              self.$message.error(JSON.stringify(err) || '获取STSToken失败')
            })
        },
        //文件上传成功
        onUploadSucceed: function (uploadInfo) {
          var uid = uploadInfo.videoInfo.uid
          self.videoMap[uid] = true
          self.videoList.forEach((item) => {
            if (item.uid == uid) {
              item['videoId'] = uploadInfo.videoId
              item.videoName = uploadInfo.file.name
            }
          })
          self.$message.success('您有一个视频已上传完成')
        },
        //文件上传失败
        onUploadFailed: function (uploadInfo, code, message) {
          self.$message.error('一个视频上传失败')
          var uid = uploadInfo.videoInfo.uid
          self.videoList.forEach((item, idx) => {
            if (item.uid == uid) {
              self.videoList.splice(idx, 1)
            }
          })
        },
        //文件上传进度,单位:字节
        onUploadProgress: function (uploadInfo, totalSize, loadedPercent) {
          var uid = uploadInfo.videoInfo.uid
          self.videoList.forEach((item) => {
            if (item.uid == uid) {
              item.progress = Math.ceil(loadedPercent * 100)
            }
          })
        },
        //STS token超时
        onUploadTokenExpired: function (uploadInfo) {
          //重新获取STS token,恢复上传
          self.$axios
            .get('/kd-group/medio/stsToken')
            .then((res) => {
              if (res && res.data.code == 200 && res.data.data) {
                var data = res.data.data
                self.sts = {
                  accessKeyId: decrypt(data.accessKeyId, ''),
                  accessKeySecret: decrypt(data.accessKeySecret, ''),
                  secretToken: decrypt(data.securityToken, ''),
                }
                self.uploader.setSTSToken(uploadInfo, self.sts.accessKeyId, self.sts.accessKeySecret, self.sts.secretToken)
              } else {
                self.$message.error(res.data.msg || '获取STSToken失败')
              }
            })
            .catch((err) => {
              self.$message.error(JSON.stringify(err) || '获取STSToken失败')
            })
        },
        //全部文件上传结束
        onUploadEnd: function (uploadInfo) {
          // console.log("onUploadEnd: uploaded all the files");
        },
      })
    },
    showVideoLoading() {
      var flag = true
      for (var key in this.videoMap) {
        if (!this.videoMap[key]) {
          flag = false
          return
        }
      }
      return flag
    },

3-3、关于官网的配置

  • 入口


    注册开通

    视频点播入口

    模块
  • 分类管理 所谓CateId (区分生产环境和测试环境视频存放的位置)


    分类管理 1.png

    分类管理 2.png
  • 转码模板组 (格式、清晰度等)


    转码模板组
  • 回调设置


    回调设置.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容