监听视频是否加载完毕
背景是最近我们在上线一个需求后,发现用户在发送AI指令获取视频的时候,打点显示部分用户(45%左右)都触发了发送指令,但是没有进行视频播放,所以就开始排查这个问题
排查后发现是没有触发视频的ready枚举,导致没有上报视频开始播放的点位,实际视频已经开始播放了只是没有上报而已
于是就开始看监听视频的hooks代码
import { useState, useEffect, useMemo } from 'react';export const playStatusEnum = {idle: 'idle', // 未加载loading: 'loading', // 加载中ready: 'ready', // 可以播放// loaded: 'loaded', // 加载完成playing: 'playing', // 播放中paused: 'paused', // 暂停中ended: 'ended', // 播放结束buffering: 'buffering', // 缓冲中error: 'error' // 播放错误
};export default function useVideoStatus(videoRef) {const [status, setStatus] = useState('idle');useEffect(() => {const video = videoRef.current;if (!video) return;const handleLoadStart = () => setStatus(playStatusEnum.loading);const handleCanPlay = () => setStatus(playStatusEnum.ready);const handlePlaying = () => setStatus(playStatusEnum.playing);const handlePause = () => setStatus(playStatusEnum.paused);const handleEnded = () => setStatus(playStatusEnum.ended);const handleWaiting = () => setStatus(playStatusEnum.buffering);const handleError = () => setStatus(playStatusEnum.error);video.addEventListener('loadstart', handleLoadStart);video.addEventListener('loadeddata', handleCanPlay);video.addEventListener('playing', handlePlaying);video.addEventListener('pause', handlePause);video.addEventListener('ended', handleEnded);video.addEventListener('waiting', handleWaiting);video.addEventListener('error', handleError);return () => {video.removeEventListener('loadstart', handleLoadStart);video.removeEventListener('loadeddata', handleCanPlay);video.removeEventListener('playing', handlePlaying);video.removeEventListener('pause', handlePause);video.removeEventListener('ended', handleEnded);video.removeEventListener('waiting', handleWaiting);video.removeEventListener('error', handleError);};}, [videoRef]);return useMemo(() => {return {playerStatus: status,isPlaying: [playStatusEnum.ready, playStatusEnum.playing, playStatusEnum.buffering].includes(status)};}, [status]);
}
控制视频切换状态为ready主要是这一行
video.addEventListener('loadeddata', handleCanPlay);
查了各种资料最后发现这里的 useVideoStatus
在 iOS Safari 上 永远监听不到 ready
,
在 iOS Safari 中,视频的事件触发顺序跟桌面端不一样:
桌面 Chrome/Edge/Firefox 通常会触发:
loadstart → loadeddata → canplay → canplaythrough
。iOS Safari 有时 不会触发
loadeddata
,特别是远程视频或者流式资源,只会触发canplay
。
所以在 iOS或者部分 上根本没机会进入 setStatus(playStatusEnum.ready)
。
于是多加了两种监听方式
video.addEventListener('canplay', handleCanPlay); //兼容部分手机浏览器video.addEventListener('loadedmetadata', handleCanPlay); //兼容部分手机浏览器
本地测试后看是可以触发了 ,提测后也是成功解决了 down~