vue 过滤掉在移动端无法播放的视频

2022-09-06  本文已影响0人  八妹sss
<template>
  <div class='mat-video-wrapper' v-loading='loading'>
    <!-- 编辑区域 -->
    <section class='edit-body'>
      <!-- 添加图文 -->
      <div v-show="!videoFile" class="add-video">
        <div class='add-icon'>添加视频</div>
        <input
          class="video-uploader"
          type="file"
          @change="subVideo"
          ref="fileInput"
          accept="video/mp4">
      </div>
      <!-- 图文预览区域 -->
      <div
        class='prev-box'
        v-show="videoFile">
        <div class='prev-main'
          v-loading="loadingVideo"
          element-loading-spinner="el-icon-loading"
          element-loading-text="上传中"
          element-loading-background="rgba(0, 0, 0, 0.8)"
          :style="{backgroundImage:`url('${picUrl}')`}">
          <video class="video-dom" ref='videoDOM' :src="fileSrc"></video>
          <span class='prev-icon' @click='startPreview()'></span>
        </div>
        <div class='prev-title'>{{videoFile ? videoFile.name || '标题' : '标题'}}</div>
        <div class="del" @click="delVideo()">删除</div>
      </div>
    </section>
    <div class='video-tip'>
      提示: 视频素材大小控制在{{wechatAccord ? '10M' : '5G'}}以内,支持MP4(H264编码格式)
    </div>
    <!-- 按钮区域 -->
    <section class='edit-btn'>
      <el-button size="small" type="primary" @click="saveEdit">保 存</el-button>
      <el-button size="small" @click="cancelEdit">取 消</el-button>
    </section>
    <!-- 视频的预览 -->
    <previewVideo
      v-show="showVideoPreview"
      :videoSrc="fileSrc"
      @handleClose="closePreviewVideo()"/>
    <!-- 图片上传 -->
    <shardUploader ref='upload1' :showSuccMsg='false'/>
  </div>
</template>

<script>
import shardUploader from '@/public/shardUploader'
import previewVideo from '@/public/preview/previewVideo'
export default {
  name: 'matVideo',
  props: {
    mode: {
      type: String,
      default: 'create'
    },
    mat: {
      type: Object,
      default () {
        return {}
      }
    },
    // 是否按照威微信标准过滤素材列表
    wechatAccord: {
      type: Boolean,
      default: false
    }
  },
  components: {
    shardUploader,
    previewVideo
  },
  data () {
    return {
      loading: false,
      videoFile: null,
      fileSrc: '', // 视频本地播放地址
      loadingVideo: false, // 获取封面的loading
      picUrl: null, // 视频封面图
      videoDuration: null, // 视频播放时长
      videoDOM: null,
      showVideoPreview: false
    }
  },
  methods: {
    delVideo () {
      this.$refs.fileInput.value = ''
      this.videoFile = null
      this.picUrl = null
      this.videoDuration = null
    },
    subVideo () {
      let video = this.$refs.fileInput.files[0]
      if (video) {
        // 文件格式验证
        if (!/^video\//.test(video.type) || !/\.mp4$/.test(video.name)) {
          this.showWarning('视频文件只支持mp4格式')
          this.$refs.fileInput.value = ''
          return
        }
        // 大小验证, 用于微信消息则限制是10M,否则限制为5G
        let maxSize = this.wechatAccord ? 1024 * 1024 * 10 : 1024 * 1024 * 1024 * 5
        if (video.size > maxSize) {
          this.showWarning(`视频文件大小不能超过${this.wechatAccord ? '10M' : '5G'}`)
          this.$refs.fileInput.value = ''
          return
        }
        this.loading = true
        this.fileSrc = URL.createObjectURL(video)
        this.videoFile = video
        // this.loadingVideo = true
        // 截取视频的第一帧
        if (!this.videoDOM) {
          this.videoDOM = this.$refs.videoDOM
        }
        this.videoDOM.addEventListener('loadeddata', this.getVideoFirstImg(video))
      }
    },
    // 获取视频第一帧
    getVideoFirstImg (video) {
      this.videoDOM.removeEventListener('loadeddata', this.getVideoFirstImg)
      // 获取第一帧
      setTimeout(() => {
        // 获取视频时长
        this.videoDuration = this.videoDOM.duration
        if (!this.videoDuration) {
          this.loading = false
          return this.showWarning('视频格式或mp4编码格式不支持')
        }
        let canvas = document.createElement('canvas') // 创建一个画布
        canvas.width = this.videoDOM.videoWidth
        canvas.height = this.videoDOM.videoHeight
        canvas.getContext('2d').drawImage(this.videoDOM, 0, 0, canvas.width, canvas.height) // getContext:设置画布环境;drawImage:画画
        let imgDataUrl = canvas.toDataURL('image/png') // 获取图片的url
        // console.log('imgDataUrl: ', imgDataUrl)
        // 判断生成的base64是否符合格式
        if (!/;base64/.test(imgDataUrl)) {
          this.showWarning('视频格式或mp4编码格式不支持')
          this.loading = false
        } else {
          // 转换为图片file文件,并上传到服务器
          let imgFile = this.dataURLtoFile(imgDataUrl, new Date().getTime())
          this.$refs.upload1.uploadFile(imgFile, result => {
            this.loadingVideo = false
            this.picUrl = result.url
            this.loading = false
          })
        }
      }, 1000)
    },
    startPreview () {
      this.showVideoPreview = true
    },
    closePreviewVideo () {
      this.showVideoPreview = false
    },
    saveEdit () {
      // 验证视频的标题不能为空
      if (!this.videoFile) {
        this.loading = false
        return this.$message({ message: '请先上传视频素材', type: 'warning' })
      }
      if (!this.videoDuration) {
        this.loading = false
        return this.showWarning('获取视频长度失败, 请检查视频格式')
      }
      if (this.loading) {
        return false
      }
      // this.loading = true
      // 首先上传图片到服务器,获取图片链接
      this.$refs.upload1.uploadFile(this.videoFile, result => {
        setTimeout(() => {
          let formData = new FormData()
          formData.append('fileUrl', result.url)
          formData.append('fileName', result.name)
          formData.append('fileSize', result.size)
          formData.append('picUrl', this.picUrl)
          formData.append('duration', parseInt(this.videoDuration * 1000))
          let appid = sessionStorage.getItem('appid')
          let url = `${this.SERVICE_WECHAT}/upgrade/media/${appid}/video/upload`
          this.posts(url, formData).then(res => {
            if (res.data.code === 200) {
              this.showSucc(res.data.message)
              let data = res.data.data
              let info = {
                picUrl: this.picUrl,
                mediaName: this.videoFile.name
              }
              if (data) {
                info.id = data
              }
              this.$emit('success', info)
            }
            this.loading = false
          }).catch(e => {
            this.loading = false
            this.handleError(e)
          })
        }, 1000)
      })
    },
    cancelEdit () {
      this.$emit('cancel')
    }
  },
  created () {
    // console.log('wechatAccord: ', this.wechatAccord)
  }
}
</script>

<style lang="stylus" scoped>
.mat-video-wrapper
  min-height calc(100% - 70px)
  padding-bottom 70px
  position relative
  .edit-body
    padded_box(border-box,0 10px)
    display flex
    align-items center
    .add-video
      width 275px
      height 160px
      background #f2f2f6
      position relative
      .add-icon
        position absolute
        left 0
        right 0
        top 0
        bottom 0
        margin auto
        width 64px
        height: 21px;
        font-size: 14px;
        color: #5E5E66;
        line-height: 21px;
        padding-top 24px
        text-align center
        &:before, &:after
          content ''
          display block
          width 20px
          height 2px
          background: #ACAEBC;
          position absolute
          left 0
          right 0
          top 0
          margin auto
        &:after
          transform rotate(90deg)
      .video-uploader
        position absolute
        z-index 1
        left 0
        top 0
        width 100%
        height 100%
        opacity 0
        cursor pointer
      .video-box
        width 0
        height 0
        opacity 0
    .prev-box
      width 275px
      position relative
      .del
        line-height 18px
        font-size 14px
        color #4c84ff
        cursor pointer
        position absolute
        right -44px
        bottom 0px
      .prev-main
        position relative
        width 100%
        height 108px
        background-color #F7F7F7;
        background-position center
        background-repeat no-repeat
        background-size cover
        cursor pointer
        .video-dom
          object-fit cover
          width 100%
          height 100%
          position absolute
          top 0
          left 0
          visibility hidden
        .prev-icon
          position absolute
          left 0
          right 0
          top 0
          bottom 0
          background url('~assets/img/enterprise/video_ic_play@2x.png') no-repeat center / 30px
          z-index 4
      .prev-title
        height 50px
        line-height 50px
        border 1px solid #ddd
        padding 0 9px
        font-size 14px
        color #333
        no-wrap()
  .video-tip
    padding 15px 10px
    color #666
  .edit-btn
    position absolute
    left 0
    right 0
    bottom 0
    padding 20px 0
    text-align center
</style>
上一篇下一篇

猜你喜欢

热点阅读