diff --git a/packages/taro-components/package.json b/packages/taro-components/package.json index 536c25e81bba..68f3eba5cf44 100644 --- a/packages/taro-components/package.json +++ b/packages/taro-components/package.json @@ -41,6 +41,7 @@ "@tarojs/taro": "3.4.7", "better-scroll": "^1.14.1", "classnames": "^2.2.5", + "hls.js": "^1.1.5", "intersection-observer": "^0.7.0", "omit.js": "^1.0.0", "resolve-pathname": "^3.0.0", diff --git a/packages/taro-components/src/components/video/utils.ts b/packages/taro-components/src/components/video/utils.ts index 30c51ba14d46..1bd0476568a2 100644 --- a/packages/taro-components/src/components/video/utils.ts +++ b/packages/taro-components/src/components/video/utils.ts @@ -1,7 +1,7 @@ -export const formatTime = (time: number): string => { - if (time === null) return '' - const sec = Math.round(time / 1000 % 60) - const min = Math.floor((time - sec) / 1000 / 60) +export const formatTime = (time?: number): string => { + if (!time) return '' + const sec = Math.round(time % 60) + const min = Math.round((time - sec) / 60) return `${min < 10 ? `0${min}` : min}:${sec < 10 ? `0${sec}` : sec}` } @@ -72,7 +72,7 @@ export const screenFn = (function () { ] let i = 0 const l = fnMap.length - const ret = {} + const ret: Record = {} // This for loop essentially checks the current document object for the property/methods above. for (; i < l; i++) { val = fnMap[i] @@ -96,3 +96,5 @@ export const screenFn = (function () { // and the fn variable is set to this returned value. return ret })() + +export const isHls = url => /\.(m3u8)($|\?)/i.test(url) diff --git a/packages/taro-components/src/components/video/video-control.tsx b/packages/taro-components/src/components/video/video-control.tsx index caf2f2a0b660..1625564b5b54 100644 --- a/packages/taro-components/src/components/video/video-control.tsx +++ b/packages/taro-components/src/components/video/video-control.tsx @@ -12,7 +12,7 @@ export class VideoControl implements ComponentInterface { private isDraggingProgressBall = false private hideControlsTimer: NodeJS.Timeout private percentage = 0 - private progressDimentions = { + private progressDimensions = { left: 0, width: 0 } @@ -89,10 +89,10 @@ export class VideoControl implements ComponentInterface { } calcPercentage = (pageX: number): number => { - let pos = pageX - this.progressDimentions.left + let pos = pageX - this.progressDimensions.left pos = Math.max(pos, 0) - pos = Math.min(pos, this.progressDimentions.width) - return pos / this.progressDimentions.width + pos = Math.min(pos, this.progressDimensions.width) + return pos / this.progressDimensions.width } onDragProgressBallStart = () => { @@ -148,8 +148,8 @@ export class VideoControl implements ComponentInterface { ref={ref => { if (!ref) return const rect = ref.getBoundingClientRect() - this.progressDimentions.left = rect.left - this.progressDimentions.width = rect.width + this.progressDimensions.left = rect.left + this.progressDimensions.width = rect.width }}>
{ + @Watch('src') + watchSrc () { + this.init() + } + + analyzeGesture = (e: TouchEvent) => { const obj: { type: string dataX?: number @@ -263,7 +272,7 @@ export class Video implements ComponentInterface { if (this.lastTouchScreenX === undefined || this.lastTouchScreenY === undefined) return if (await this.controlsRef.getIsDraggingProgressBall()) return - const gestureObj = this.analyseGesture(e) + const gestureObj = this.analyzeGesture(e) if (gestureObj.type === 'adjustVolume') { this.toastVolumeRef.style.visibility = 'visible' const nextVolume = Math.max(Math.min(this.lastVolume - gestureObj.dataY!, 1), 0) @@ -305,6 +314,37 @@ export class Video implements ComponentInterface { this.lastTouchScreenY = undefined } + loadNativePlayer = () => { + if (this.videoRef) { + this.videoRef.src = this.src + this.videoRef.load() + } + } + + init = () => { + const { src, videoRef } = this + + if (isHls(src)) { + if (Hls.isSupported()) { + if (this.hls) { + this.hls.destroy() + } + this.hls = new Hls() + this.hls.loadSource(src) + this.hls.attachMedia(videoRef) + this.hls.on(Hls.Events.MANIFEST_PARSED, () => { + this.autoplay && this.play() + }) + } else if (videoRef.canPlayType('application/vnd.apple.mpegurl')) { + this.loadNativePlayer() + } else { + console.error('该浏览器不支持 HLS 播放') + } + } else { + this.loadNativePlayer() + } + } + handlePlay = () => { this.isPlaying = true this.isFirst = false @@ -478,7 +518,6 @@ export class Video implements ComponentInterface { render () { const { - src, controls, autoplay, loop, @@ -488,8 +527,6 @@ export class Video implements ComponentInterface { isFirst, isMute, isFullScreen, - duration, - _duration, showCenterPlayBtn, isPlaying, _enableDanmu, @@ -498,7 +535,8 @@ export class Video implements ComponentInterface { showFullscreenBtn, nativeProps } = this - const durationTime = formatTime(duration || _duration || null) + const duration = this.duration || this._duration + const durationTime = formatTime(duration) return (