admin管理员组

文章数量:1666532

m3u8视频文件夹COS上传及播放(无论是TCplayer 还是video.js在手机浏览器端都无法兼容, 特别是ios端)

  • 创作的背景: 原来使用的mp4来进行视频上传 播放和下载, 由于腾讯云视频流量高峰期一周的收费达到5000元左右, 特提出优化方案, 上传视频的时候上传mp4 和 m3u8 各一份, 视频在线播放使用TCplayer或videojs 进行m3u8视频播放, 下载时下载mp4格式视频, 以此方案来减少腾讯云流量来减少支出
  • 经过多篇文章的阅读无果后又与腾讯客服反复沟通实现前端上传mp4转换成的m3u8视频文件夹, 并实现m3u8视频播放

1. 找到项目的index.html入口文件引入下边样式和js, 放入标签内即可

  <!--播放器样式文件-->
  <link async href="https://web.sdk.qcloud/player/tcplayer/release/v4.2.2/tcplayer.min.css" rel="stylesheet" />
  <!--现代浏览器中通过 H5 播放 HLS 格式的视频,需要在 tcplayer.v4.2.2.min.js 之前引入 hls.min.0.13.2m.js。-->
  <script async src="https://web.sdk.qcloud/player/tcplayer/release/v4.2.2/libs/hls.min.0.13.2m.js"></script>
  <!--播放器脚本文件-->
  <script async src="https://web.sdk.qcloud/player/tcplayer/release/v4.2.2/tcplayer.v4.2.2.min.js"></script>

2. mp4文件上传常规上传即可, 在此特别说明m3u8文件夹cos上传

  • 2.1 cos.js 封装
var COS = require("cos-js-sdk-v5")
import uuid from 'uuid'
let Bucket = "" /* 存储桶 */
let Region = "" /* 存储桶所在地域,必须字段 */
import fetch from "@/utils/request";
import { ElLoading } from 'element-plus'
let serviceModl = '/content'
let loadingOptions = {
  text: "正在努力上传,请稍等...",
  lock: true,
  spinner: "el-icon-loading",
  background: "rgba(255, 255, 255, 0.5)",
};
let filePath = '/digital-admin/'; // 存储目录(自定义)
//获取cos凭证
export function getCosSTS (data) {
  return fetch({
    url: '自己的后端接口地址',
    method: "POST",
    data: data
  })
}
//初始化 Cos
export function initCos () {
  return new Promise((resolve) => {
    getCosSTS().then(res => {
      Bucket = res.data.bucketName;
      Region = res.data.endpoint;
      let cosObj = {
        TmpSecretId: res.data.credentials.tmpSecretId,
        TmpSecretKey: res.data.credentials.tmpSecretKey,
        SecurityToken: res.data.credentials.sessionToken,
        // 建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误
        StartTime: res.data.startTime, // 时间戳,单位秒,如:1580000000
        ExpiredTime: res.data.expiredTime, // 时间戳,单位秒,如:1580000900
      };
      let client = new COS({
        getAuthorization: function (options, callback) {
          callback(cosObj);
        }
      })
      resolve(client)
    })
  })
}
//文件夹上传文件至cos
export async function uploadFilesToCos (files, fileName, size, cos) {
  let filesArr = []
  for (var key in files) {
    if (files[key].size) {
      filesArr.push({
        Bucket: Bucket, /* 填入您自己的存储桶,必须字段 */
        Region: Region,  /* 存储桶所在地域,例如ap-beijing,必须字段 */
        Key: filePath + files[key].name,  /* 存储在桶里的对象键(例如1.jpg,a/b/test.txt),必须字段 */
        Body: files[key], /* 必须,上传文件对象,可以是input[type="file"]标签选择本地文件后得到的file对象 */
        onTaskReady: function (taskId) {
          /* taskId可通过队列操作来取消上传cos.cancelTask(taskId)、停止上传cos.pauseTask(taskId)、重新开始上传cos.restartTask(taskId) */
          // console.log(taskId);
        },
        // 支持自定义headers 非必须
        Headers: {
          'x-cos-meta-test': 123
        }
      })
    }
  }
  return new Promise(resolve => {
    ElLoading.service(loadingOptions);
    cos.uploadFiles(
      {
        files: filesArr,
        // SliceSize 分片上传值要大于m3u8文件夹的ts文件大小, 否则会报错 被禁止 403
        SliceSize: 1024 * 1024 * 1024,    /* 设置大于1G采用分块上传 */
      },
      function (err, data) {
        ElLoading.service(loadingOptions).close();
        console.log('data', data)
        if (data.files && data.files.length > 0) {
          data.files.forEach(item => {
            let ary = item.data.Location.split('.')
            let type = ary[ary.length - 1]
            if (type === 'm3u8') {
              // 整个文件夹上传成功后, 只需要保存后缀是m3u8文件的访问地址(mp4转成m3u8的时候.m3u8文件与ts文件已经有了对应的索引关系, m3u8视频文件夹里的所有文件必须上传到同一个文件夹内, 否则访问不了)
              let fileData = {
                url: filePath + fileName, // 不包含访问前缀
                // url: 'https://' + item.data.Location, // 全路径
                size: size,
                name: fileName,
                key: filePath + fileName,
              }
              resolve(fileData)
            }
          })
        }
      }
    )
  })
}
  • 2.2 html中插入文件夹上传代码
  <!-- 上传m3u8 -->
  <el-button type="primary"  @click="m3u8Upload" style="margin-left: 30px;">上传m3u8</el-button>
  <!-- 要想上传文件夹, input 需指定 type类型为 file, webkitdirectory为true 上传文件夹 -->
  <input type="file" id="m3u8Upload" webkitdirectory style="position: absolute; left: 1000000px" @change="m3u8UploadChange($event)">
import {onMounted, ref, reactive, watch} from 'vue'
import { uploadFilesToCos } from "@/api/cos.js";
const cosClient = null
const fileList = ref([])
onMounted(() => {
	//初始cos
	initOss().then(res=>{
	  cosClient = res;
	})
})
// 在这里说明下 用的vue3框架, <script setup></script>
const m3u8Upload = () => {
  let element = document.getElementById('m3u8Upload')
  element.value = null  // 清空上一次的上传
  element.click() // 触发input的上传事件
}
const m3u8UploadChange = ($event) => {
   console.log($event)
   let fileName = ''
   let size = 0
   let files = $event.target.files
   if (files) {
     for (let key in files) {
       if (files[key].type) {
         fileName = files[key].name
       }
       if (typeof files[key].size === 'number') {
         size += files[key].size
       }
     }
     if (size > 1024 * 1024 * 1024) {
       return ElMessage.error('附件大小不可超过1G')
     }
     uploadFilesToCos(files, fileName, size, cosClient).then(res=>{
       if(res && res.url){
         console.log('res', res)
         fileList.value.push({
           name: res.name,
           url: res.url
         })
       }
     })
   }
}
// 文件夹上传成功后, 调用后端接口保存访问地址数组即可

3. 播放m3u8 视频

  • 3.1 使用TCplayer进行视频播放(上边第一步index.html导入的css和js就是TCplayer播放插件
<!--id为自定义id-->
<video id="player-container-id" width="800" height="450" preload="auto" playsinline webkit-playsinline></video>
let player = ref(null)
// url 为m3u8视频的全路径
// 播放m3u8视频
function m3u8Player(url) {
	setTimeout(() => { // 倒计时是为了video元素渲染完成才能拿到该元素
      // player-container-id 为播放器容器 ID,必须与 html 中一致
      player.value = TCPlayer(document.getElementById('player-container-id'), {
        reportable: false,
      })
      player.value.src(url); // url 播放地址, 全路径
      console.log('player', player.value)
    },100)
}
// 关闭m3u8视频播放, 并清楚 player
function m3u8Close() {
	if (player.value) {
		player.value.pause()
		player.value = null
	}
}
  • 3.2 使用video.js进行m3u8格式视频播放
//安装 3个插件对应版本如下
npm install video.jst@7.13.3 videojs-contrib-hls@5.15.0 videojs-flash@2.2.1
	<div class="video-box play-box" ref="videoBox" v-if="showPlayer">
	    <video  
	         id="videoPlayer"
	         ref='videoPlayer'
	         disablePictureInPicture
	         controlsList="nodownload"
	         class="play-back video-js vjs-default-skin vjs-big-play-centered"
	         controls
	         preload="none">
	     </video>
   </div>
	import Videojs from "video.js"
	const myPlayer = ref(null)
	// 关闭视频播放
	function closeVideo () {
	  myPlayer.value.dispose()
	},
	// 初始化播放
	async function initVideo(url) {
	  // 这些options属性也可直接设置在video标签上,见 muted
	  let options = {
	    autoplay: true, // 设置自动播放
	    controls: true, // 显示播放的控件
	    sources: [
	      // 注意,如果是以option方式设置的src,是不能实现 换台的 (即使监听了url也没实现)
	      {
	        src: url, // 视频文件的全路径
	        type: "application/x-mpegURL" // 告诉videojs,这是一个hls流
	      }
	    ]
	  };
	  // videojs的第一个参数表示的是,文档中video的id
	 myPlayer.value = Videojs("videoPlayer", options);
	},

本文标签: 文件夹上传视频cos