视频自定义播放之闪屏问题与解决

920 阅读1分钟

视频组件自定义播放

  • 背景:视频在移动端微信打开(ios)中,不会自动播放,产品要求放一个播放按钮,替换掉原生的controls,点击后播放

准备一个按钮

{
  isMobile && showIcon && (
    <Icon onClick={videoCanPlay} className={styles['icon-play']} />
  );
}

video 标签处理

const ref = useRef < HTMLVideoElement > null;
const [showIcon, setShowIcon] = useState(true);
{
  isMobile && (
    <video
      ref={ref}
      src={resource}
      controls={false}
      autoPlay={false}
      loop
      preload={preload}
      playsInline
      muted
      style={{ width, height }}
      poster={poster}
    />
  );
}

css 居中

.video {
  position: relative;
}
.icon-play {
  font-size: 34px;
  color: rgba(255, 255, 255, 0.7);
  z-index: 99;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

点击按钮开始 play

const videoCanPlay = () => {
  ref.current && ref.current.play();
  setShowIcon(false);
};
  • 到这一步安卓是可以播放了,然后就提测了

问题

  • ios 系统打开,点击播放按钮,会闪屏
    • 经过查询发现 ios 有个机制-只有自动播放的视频才会预加载,因此就没有预加载,poster 和 video 之间有个间隙,会导致屏幕闪烁
    • 解决
     const videoCanPlay = () => {
         if (ref.current) {
              () =>{
                  ref.current?.load();
              }
             ref.current.onloadeddata = () => {
                 setTimeout(() => {
                     ref.current && ref.current.play()
                     setShowIcon(false);
                 }, 200);
             };
         }
     };
    

完整组件(主要)


...

const VideoSection = (props) => {
    const ref = useRef<HTMLVideoElement>(null);
    const [showIcon, setShowIcon] = useState(true);
    const videoCanPlay = () => {
        if (ref.current) {
            () =>{
                ref.current?.load();
            }
            ref.current.onloadeddata = () => {
                setTimeout(() => {
                    ref.current?.play()
                    setShowIcon(false);
                }, 200);
            };
        }
    };
    return (
        <section className='video'>
            {isMobile && showIcon && (
                <Icon onClick={videoCanPlay} className="icon-play"  />
            )}
            {isMobile && (
                <video
                    ref={ref}
                    src={resource}
                    controls={false}
                    autoPlay={false}
                    loop
                    preload={preload}
                    playsInline
                    muted
                    style={{ width, height }}
                    poster={poster}
                />
            )}
        </section>
    );
};
export default VideoSection;