当前位置: 首页 > 科技观察

短视频无尽流前端开发指南

时间:2023-03-21 19:11:40 科技观察

前言短视频无尽流是一种流行的业务场景,在日常生活中随处可见。本文基于家装内容短视频层出不穷的开发实践,总结出一套适用于该场景及其衍生场景的前端开发指南。通过阅读本文,你可以快速了解短视频层出不穷的前端开发。短视频EndlessStream简介短视频具有“短、平、快”的特点,用户可以通过短视频快速获得一些输入。在家装领域,可以通过几十秒到几分钟的短视频向用户输出装修干货体验、家居好品推荐等。在短视频无尽流场景下,会根据引流内容和相关算法推荐更多内容,用户可以通过向上滑动的手势继续浏览获取内容输入。短视频EndlessStream结构拆解短视频EndlessStream在结构上可以拆解成两层:滑动轮播容器和单内容卡片。单个内容卡片可以拆解成两部分:自定义控制栏的视频播放器(以下简称视频播放器)和内容相关信息。内容相关信息是一个业务展现模块,不同的业务有自己的表现方式,这部分内容本文不做介绍。下面将介绍基于React的滑动轮播容器和视频播放器的开发指南。?视频播放器家装内容短视频无尽流使用淘宝App内置的同层渲染播放器(VideoX桥)。为了增强普适性,本文直接使用HTML5video标签作为播放器进行介绍。播放器自带的控件条样式比较简单,往往不能满足业务需求,需要实现自定义控件条。本节将介绍如何实现播放器状态按钮和播放器进度条,以及播放器的激活和销毁,为滑动轮播容器中的应用做准备。视频播放器状态按钮一般来说,播放器需要显示两种状态:暂停、缓冲、播放时进度条在前进。通常,不需要额外的显示器。状态按钮组件实现如下:tips:将按钮状态构建到组件中,并将修改状态的方法暴露给父元素,可以避免改变按钮状态时触发父元素的重新渲染。//...constStatusButton=forwardRef((_,ref)=>{const[status,setStatus]=useState(EStatus.PLAY);useImperativeHandle(ref,()=>({setStatus,}));return({(()=>{switch(status){caseEStatus.PAUSE:return

{/*暂停图标*/>
;caseEStatus.WAITING:return
{/*滚冲图标*/}
;默认:returnnull;}})()}
);});exportdefaultmemo(StatusButton);//...constVideoPlayer:FC=(props)=>{const{source}=props;constvideoPlayerRef=useRef(空);conststatusButtonRef=useRef(空);constonPlay=()=>{statusButtonRef.current?.setStatus(EPlayerStatus.PLAY);};useEffect(()=>{videoPlayerRef.cur租金?.addEventListener('播放',onPlay);//Pause(暂停)和buffer(等待)的监听方法类似//...return()=>{videoPlayerRef.current?.removeEventListener('play',onPlay);};},[]);return({/*player*/}{/*播放器状态按钮*/}
);};导出默认备忘录(VideoPlayer);视频播放进度条有两种情况会导致进度条“走动”:视频正常播放,进度更新,用户手动拖动进度条。对于1,进度条组件暴露的方法将进度更新到父元素,父元素可以在监听播放器的timeupdate时调用该方法。对于2,可以使用@use-gesture/vanilla来实现手的拖动效果。当用户停止拖动时,播放器将跳过帧://...useEffect(()=>{constgesture=newDragGesture(//拖动“point”thumbRef.current,(state)=>{if(state.first){setIsDragging(true);}constx=state.xy[0];letwalked:number;//判断是否越界if(x<0){walked=0;}elseif(x>OVERALL_WIDTH){walked=OVERALL_WIDTH;}else{walked=x;}setCurrentWalked(walked);if(state.last){//用户停止拖动后,跳转到当前时间constduration=Math.ceil((walked/OVERALL_WIDTH)*maxDuration);onChangeCurrentTime(duration);setIsDragging(false);}},{轴:'x',pointer:{touch:true},},);return()=>{gesture.destroy();};},[]);返回();视频播放器被激活和销毁虽然这个场景有n张内容卡,但是我们只需要在画面中有一张内容卡来渲染视频播放器,其余的内容卡只需要保留封面图就可以减少内存占用.//...constVideoPlayer=forwardRef((props,ref)=>{//播放器状态默认不活动const[activeStatus,setActiveStatus]=useState(false);//.../***隐藏封面帖子*/consthidePoster=()=>{posterRef.current?.hide();};/***激活播放器*/constactivate=()=>{setActiveStatus(true);};/***销毁播放器*/constinActivate=()=>{setActiveStatus(false);//显示封面posterRef.current?.show();};useImperativeHandle(ref,()=>({activate,inActivate,}));useEffect(()=>{//监控视频第一帧加载时,隐藏覆盖,防止画面闪烁videoPlayerRef.current?.addEventListener('loadeddata',hidePoster);//...return()=>{videoPlayerRef.current?.removeEventListener('loadeddata',hidePoster);};},[]);//...});导出默认备忘录(VideoPlayer);?滑动轮播容器对于滑动轮播容器,使用swiper实现。Swiper是一个强大的轮播组件,内置丰富的功能,并且封装了React组件,方便使用。虚拟轮播由于短视频endlessstream具有“无尽”的特性,用户一次可以浏览几十个内容,所以可以利用swiper的虚拟能力减少内存占用,并会通过手动轮播切换来增删节点,只保持视角范围内上下滑动节点数量有限。如下图,当前需要500张幻灯片,但是通过动态增删节点,实际渲染的节点数最多为5个(数量可配置)。swiper参数配置请参考://swiper6.x和8.x版本会有一些差异,差异会在注释中标注import*asReactfrom'react';//[swiper8.x]importswiperimport{Virtual}from'swiper';//[swiper6.x]importswiper//importSwiperCore,{Virtual}from'swiper';从'swiper/react'导入{Swiper,SwiperSlide};importtype{FC}from'react';importtype{IVideoCardItem}from'../../types';importstylesfrom'./index.module.less';//[swiper6.x]加载虚拟模块//SwiperCore.use([Virtual]);constVideoSwiper:FC=()=>{return({/*...*/});};tips:移动端开启滑动可能会出现闪烁/抖动异常情况。可以使用如下代码开启硬件加速,可以解决大部分异常情况。videoSwiperContainer:global{.swiper-wrapper{transform:translate3d(0,0,0);.swiper-slide{转换:translate3d(0,0,0);}}}视频播放器实例管理如上所述,只需要屏幕中的一张内容卡来渲染播放器,其余显示封面图像的地方。当轮播容器完成一次切换(onTransitionEnd)时,销毁上一个内容卡的播放器,同时激活当前内容卡的播放器,这样一直只有一个播放器处于活动状态。提示:当前内容卡的播放器激活后,切换后会有短暂的等待时间,因为视频资源还需要加载。为了提升用户体验,可以配合视频资源的预加载,优先使用设备侧提供的预加载能力。如果没有这种支持,可以尝试使用blob等预加载方案。底部浮动加载栏层出不穷的场景是不可避免的加载加载。对于全屏轮播容器,loading的出现/消失要尽量避免布局偏移。如果在加载过程中用户想做一些点击操作,但是操作刚好瞬间加载就结束了。如果此时布局发生偏移,会导致用户点击一个意想不到的动作点,损害用户体验。您可以像这样使用轻量级浮动加载:.loadingBar{&Container{position:fixed;左:0;底部:0;z-指数:99;显示:弹性;对齐项目:居中;证明内容:flex-end;宽度:100vw;高度:5rpx;}&Item{高度:5rpx;背景色:#fd0;动画:加载0.6s线性无限;}}@keyframesloading{0%{宽度:0;不透明度:0;}30%{宽度:30vw;不透明度:1;}70%{宽度:70vw;不透明度:1;}100%{宽度:100vw;不透明度:0;解决方案,从各个功能点的角度,这个场景如何实现和落地。除了短视频无尽推流外,还适用于其衍生场景,如显卡无尽推流、直播无尽推流、3D场景无尽推流等。针对不同的场景,不变的是轮播的构建容器。在此基础上,根据不同的场景构建单个场景卡片的逻辑就足够了。团队介绍我们是淘宝-家装技术-前端团队,团队支持淘宝家装业务。旗下有:天天平天天App、淘宝【极友家】频道。我们连接电商平台和商户店铺,涵盖家居生活、装修设计、线下市场,3D场景展示家居生活。我们努力让每一件单品不再孤立,置身其中,感受最适合家的解决方案。期待与您共建美好理想家园。