UNPKG

ps-tcplayer

Version:

Tencent Cloud Player component with Vue2/Vue3 compatibility

180 lines (149 loc) 5.09 kB
import snapshotHtml from './index.html' import './index.scss' import { parseDom } from '../../utils' /** * 视频截图组件 */ export default class SnapshotComponent { /** * @constructor 视频截图组件构造函数 */ constructor(player) { this.player = player this.html = parseDom(snapshotHtml) } createEl(el) { const controlBar = el.querySelector('.vjs-control-bar'); if (controlBar) { const tcpVideoQualitySwitcher = controlBar.querySelector('.vjs-fullscreen-control') controlBar.insertBefore(this.html, tcpVideoQualitySwitcher.previousSibling) } else { console.warn('找不到播放器控制栏,尝试添加到根元素'); el.appendChild(this.html); } } ready() { // 设置视频跨域属性 this.setupVideoForSnapshot() // 添加点击事件监听器 this.html.addEventListener('click', () => { this.captureSnapshot() }) } /** * 设置视频元素支持跨域截图 */ setupVideoForSnapshot() { const video = this.player.tech_.el_ if (video && !video.crossOrigin) { // 设置跨域属性 video.crossOrigin = 'anonymous' video.setAttribute('crossOrigin', 'anonymous') } } /** * 捕获当前视频帧并下载 */ captureSnapshot() { const player = this.player const video = player.tech_.el_ if (!video) { console.error('视频元素不存在') this.showErrorMessage('视频元素不存在') return } const canvas = document.createElement('canvas') canvas.width = video.videoWidth || video.clientWidth canvas.height = video.videoHeight || video.clientHeight const ctx = canvas.getContext('2d') try { // 绘制视频帧到 canvas ctx.drawImage(video, 0, 0, canvas.width, canvas.height) // 尝试导出图片数据 const imageData = canvas.toDataURL('image/png') const link = document.createElement('a') link.href = imageData const timestamp = new Date().toISOString().replace(/[:.]/g, '-') const title = player.el_.getAttribute('title') || 'video' const filename = `${title}_${timestamp}.png` link.download = filename document.body.appendChild(link) link.click() document.body.removeChild(link) console.log('截图成功:', filename) } catch (error) { console.error('截图失败:', error) if (error.name === 'SecurityError') { // this.showErrorMessage('截图失败:视频跨域限制,请联系管理员配置 CORS 头部') // 尝试使用替代方案 this.tryAlternativeSnapshot(video) } else { this.showErrorMessage('截图失败:' + error.message) } } } /** * 尝试替代截图方案 */ tryAlternativeSnapshot(video) { try { // 方案1: 尝试重新加载视频并设置跨域 const videoSrc = video.src || video.currentSrc if (videoSrc) { console.log('尝试重新加载视频并设置跨域属性...') // 创建新的视频元素用于截图 const tempVideo = document.createElement('video') tempVideo.crossOrigin = 'anonymous' tempVideo.muted = true tempVideo.style.display = 'none' tempVideo.addEventListener('loadeddata', () => { tempVideo.currentTime = video.currentTime }) tempVideo.addEventListener('seeked', () => { this.captureFromTempVideo(tempVideo) document.body.removeChild(tempVideo) }) document.body.appendChild(tempVideo) tempVideo.src = videoSrc tempVideo.load() } } catch (altError) { console.error('替代方案也失败了:', altError) this.showErrorMessage('所有截图方案都失败了,请检查视频源的 CORS 配置') } } /** * 从临时视频元素截图 */ captureFromTempVideo(video) { const canvas = document.createElement('canvas') canvas.width = video.videoWidth canvas.height = video.videoHeight const ctx = canvas.getContext('2d') ctx.drawImage(video, 0, 0, canvas.width, canvas.height) try { const imageData = canvas.toDataURL('image/png') const link = document.createElement('a') link.href = imageData const timestamp = new Date().toISOString().replace(/[:.]/g, '-') const title = this.player.el_.getAttribute('title') || 'video' const filename = `${title}_${timestamp}.png` link.download = filename document.body.appendChild(link) link.click() document.body.removeChild(link) } catch (error) { console.error('替代方案截图失败:', error) this.showErrorMessage('替代方案截图失败') } } /** * 显示错误消息 */ showErrorMessage(message) { // if (typeof window !== 'undefined' && window.alert) { // alert(message) // } console.warn('[SnapshotComponent]', message) } }