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

阿里巴巴淘系技术团队官网博客 阿里巴巴淘系技术团队官网博客     2022-11-30     525

关键词:

本文基于对家装家居内容短视频无尽流的开发实践,总结出了一套适应于该场景及衍生场景的前端开发指南,通过阅读本文可以快速了解短视频无尽流的前端开发。

前言

短视频无尽流是当下比较热门的一种业务场景,在日常生活中随处可见。本文基于对家装家居内容短视频无尽流的开发实践,总结出了一套适应于该场景及衍生场景的前端开发指南,通过阅读本文可以快速了解短视频无尽流的前端开发。

短视频无尽流介绍

短视频有着“短、平、快”的特点,用户可以通过短视频快速获得一些输入。在家装家居领域,可以通过几十秒到几分钟的短视频向用户输出装修干货经验、居家好物推荐等等。在短视频无尽流场景中,会基于引流内容以及相关算法推荐出更多内容,用户随着手势上滑可以持续浏览获得内容输入。

短视频无尽流结构拆解

短视频无尽流从结构上可以拆解为两层:滑动轮播容器、单张内容卡片。单张内容卡片又可以拆解为自定义控制栏的视频播放器(下文简称视频播放器)和内容相关信息两部分。

内容相关信息为业务呈现模块,不同的业务有各自的表达方式,本文不对该部分展开介绍。下面将基于react介绍滑动轮播容器和视频播放器的开发指南。

  视频播放器

家装家居内容短视频无尽流使用的是淘宝App内置的同层渲染播放器(VideoX桥接),本文为了增强普适性,直接采用HTML5 video标签作为播放器来介绍。

播放器自身的控制栏样式比较单一,往往不能满足业务诉求,需要实现自定义的控制栏。本小节将介绍如何实现播放器状态按钮和播放器进度条,以及播放器的激活和销毁,为应用在滑动轮播容器做前置准备。

  • 视频播放器状态按钮

常规来讲播放器需要展示出两种状态:暂停中、缓冲中,播放中有进度条在推进一般不需要做额外展示。状态按钮组件实现如下:

tips:将按钮状态内置在组件中,暴露修改状态的方法给父元素,可以避免在改变按钮状态时触发父元素的re-render。

// ...
const StatusButton = forwardRef<IStatusButtonRef>((_, ref) => 
  const [status, setStatus] = useState<EStatus>(EStatus.PLAY);


  useImperativeHandle(ref, () => (
    setStatus,
  ));


  return (
    <div className=styles.statusButton>
      (() => 
        switch (status) 
          case EStatus.PAUSE:
            return <div>/* 暂停Icon */</div>;
          case EStatus.WAITING:
            return <div>/* 缓冲Icon */</div>;
          default:
            return null;
        
      )()
    </div>
);
);


export default memo(StatusButton);
// ...
const VideoPlayer: FC<IVideoPlayer> = (props) => 
  const  source  = props;


  const videoPlayerRef = useRef<HTMLVideoElement | null>(null);
  const statusButtonRef = useRef<IStatusButtonRef | null>(null);


  const onPlay = () => 
    statusButtonRef.current?.setStatus(EPlayerStatus.PLAY);
  ;


  useEffect(() => 
    videoPlayerRef.current?.addEventListener('play', onPlay);
    // 暂停(pause)和缓冲(waiting)监听方法类似
    // ...


    return () => 
      videoPlayerRef.current?.removeEventListener('play', onPlay);
    ;
  , []);


  return (
    <div className=styles.videoPlayerContainer>
      /* 播放器 */
      <video
        ref=videoPlayerRef
        className=styles.item
        src=source
        playsInline
        autoPlay
      />
      /* 播放器状态按钮 */
      <StatusButton ref=statusButtonRef />
    </div>
  );
;


export default memo(VideoPlayer);
  • 视频播放器进度条

有两种情况会引起进度条“走动”:

  1. 视频正常播放,进度更新。

  2. 用户手动拖拽进度条。

对于1,进度条组件对父元素暴露更新进度的方法,父元素监听到播放器 timeupdate 时去调用该方法即可。

对于2,可以使用 @use-gesture/vanilla 实现跟手的拖拽效果,用户停止拖拽时去做播放器的跳帧操作:

// ...
useEffect(() => 
  const gesture = new DragGesture(
    // 拖拽“点”
    thumbRef.current,
    (state) => 
      if (state.first) 
        setIsDragging(true);
      


      const x = state.xy[0];


      let walked: number;
      // 判断是否超出边界
      if (x < 0) 
        walked = 0;
       else if (x > OVERALL_WIDTH) 
        walked = OVERALL_WIDTH;
       else 
        walked = x;
      


      setCurrentWalked(walked);


      if (state.last) 
        // 用户停止拖拽后,跳帧至当前时间
        const duration = Math.ceil((walked / OVERALL_WIDTH) * maxDuration);
        onChangeCurrentTime(duration);
        setIsDragging(false);
      
    ,
    
      axis: 'x',
      pointer:  touch: true ,
    ,
  );


  return () => 
    gesture.destroy();
  ;
, []);


return (
  <div ref=thumbRef />
);
  • 视频播放器激活及销毁

虽然该场景下存在n个内容卡片,但是我们只需要屏幕当中的那一个内容卡片渲染视频播放器,其余内容卡片仅保留封面图占位即可,减少内存占用。

// ...
const VideoPlayer = forwardRef<IVideoPlayerRef, IVideoPlayerProps>((props, ref) => 
  // 播放器状态 默认为非激活状态
  const [activeStatus, setActiveStatus] = useState<boolean>(false);
  // ...
  
  /**
   * 隐藏封面占位
   */
  const hidePoster = () => 
    posterRef.current?.hide();
  ;


  /**
   * 激活播放器
   */
  const activate = () => 
    setActiveStatus(true);
  ;
  /**
   * 销毁播放器
   */
  const inActivate = () => 
    setActiveStatus(false);
    // 销毁播放器时展示封面占位
    posterRef.current?.show();
  ;


  useImperativeHandle(ref, () => (
    activate,
    inActivate,
  ));


  useEffect(() => 
    // 监听视频首帧加载完成时再去隐藏封面占位,防止屏幕闪动
    videoPlayerRef.current?.addEventListener('loadeddata', hidePoster);
    // ...


    return () => 
      videoPlayerRef.current?.removeEventListener('loadeddata', hidePoster);
    ;
  , []);
  
  // ...
);


export default memo(VideoPlayer);

  滑动轮播容器

对于滑动轮播容器,采用swiper实现。swiper是强大的轮播组件,有丰富的内置能力,封装了react组件可以方便地使用。

  • 虚拟轮播

由于短视频无尽流有”无尽“的特性,用户单次可能会浏览几十篇内容,因此可以使用swiper的virtual能力减少内存占用,会随着手动轮播切换增删节点,仅保留视角内上下有限个swiper slide节点。如下图所示,当前需要用到500个slide,但是通过动态增删节点保证实际渲染出的节点数最多只有5个(个数可配置)。

swiper入参配置可参考:

// swiper 6.x版本 和 8.x版本 使用上会有一定区别,注释中会将不同点标注出来
import * as React from 'react';


// [swiper 8.x] 引入 swiper
import  Virtual  from 'swiper';


// [swiper 6.x] 引入 swiper
// import SwiperCore,  Virtual  from 'swiper';


import  Swiper, SwiperSlide  from 'swiper/react';


import type  FC  from 'react';
import type  IVideoCardItem  from '../../types';


import styles from './index.module.less';


// [swiper 6.x] 加载 Virtual 模块
// SwiperCore.use([Virtual]);


const VideoSwiper: FC = () => 
  return (
    <Swiper
      className=styles.videoSwiperContainer
      // 切换方向
      direction="vertical"
      // 初始索引
      initialSlide=0
      // 切换角度,防止误切
      touchAngle=30
      // [swiper 8.x] 加载 Virtual 模块
      modules=[Virtual]
      // virtual配置,如下配置会保证至多有5 slide
      virtual=
        // 在active的slide前多渲染1个slide
        addSlidesBefore: 1,
        // 在active的slide后多预渲染1个slide
        addSlidesAfter: 1,
      
    >
      /* ... */
    </Swiper>
  );
;

tips:移动端swiper切换时可能存在闪屏/抖动的异常情况,可以使用如下代码开启硬件加速,可以解决大部分异常情况。

.videoSwiperContainer :global 
  .swiper-wrapper 
    transform: translate3d(0, 0, 0);
    
    .swiper-slide 
      transform: translate3d(0, 0, 0);
    
  
  • 视频播放器实例管理

上述中提到只需要屏幕当中的那一个内容卡片渲染播放器,其余展示封面图占位即可。在轮播容器完成一次切换即 onTransitionEnd  时销毁上一个内容卡片的播放器,同时激活当前内容卡片的播放器,保证始终只有一个播放器处于激活状态。

tips:当前内容卡片的播放器激活后,由于还需要加载视频资源,因此切换后会有短暂的等待时间。为了提升用户体验,可以配合视频资源的预加载,优先使用端侧提供的预加载能力,若没有该支持,可以尝试使用blob等预加载方案。

底部悬浮loading条

无尽流场景不可避免的是加载loading,对于全屏幕的轮播容器,loading的出现/消失尽量避免产生布局偏移,如果loading过程中用户想去做一些点击操作,但刚好操作的瞬间loading结束了,若此时发生了布局偏移,会造成用户点到非预期的行动点,有损用户体验。可以采用类似此轻量级的悬浮式loading:

.loadingBar 
  &Container 
    position: fixed;
    left: 0;
    bottom: 0;
    z-index: 99;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    width: 100vw;
    height: 5rpx;
  


  &Item 
    height: 5rpx;
    background-color: #fd0;
    animation: loading 0.6s linear infinite;
  



@keyframes loading 
  0% 
    width: 0;
    opacity: 0;
  
  30% 
    width: 30vw;
    opacity: 1;
  
  70% 
    width: 70vw;
    opacity: 1;
  
  100% 
    width: 100vw;
    opacity: 0;
  

总结

本文通过对短视频无尽流结构的拆解,从各个功能点的角度介绍了如何实现并落地该场景。除了短视频无尽流外,还适用于其衍生场景,如图文卡片无尽流、直播无尽流、3D场景无尽流等等。针对于不同场景,不变的是轮播容器的构建,在此基础上根据不同场景构建单个场景卡片的逻辑即可。

团队介绍

我们是大淘宝-家装家居技术-前端团队,团队支撑大淘宝家居家装业务。旗下包括:每平每屋App、淘宝【极有家】频道。我们连通电商平台和商家店铺,覆盖居家生活、装修设计、线下市场,3D场景化展现居家生活,我们力求让每件单品都不再孤立呈现,置身其中,感受家的优选方案。期待与您一起共筑美好的理想家。

✿  拓展阅读

作者|胡少鹏(棣棠)

编辑|橙子君

聚焦短视频的开发难点,短视频开发的难度很大吗?

最近几年时间,短视频以迅雷不及掩耳之势火遍大江南北,以抖音、快手为首的发展极为迅速,侵占了中国的大半个市场,这些上市公司更是赚的盆满钵满,看到这你是不是也想了解一下短视频的开发呢?这件看起来容易的事情... 查看详情

被热捧的短视频背后,短视频软件开发的知识点你知道吗?

短视频虽然已经兴起很久了,但短视频软件的开发到现在来说也还是一个热潮。短视频作为娱乐信息传播的媒体,影响到越来越多人的社交生活体验。那么关于短视频软件开发知识点你知道的多吗,如何开发,开发时需要注意什... 查看详情

短视频社交|电影点播平台springboot+vue+elementui前后端分离(代码片段)

...介本项目基于Springboot+vue开发实现了一个电影点播和短视频分享平台,名为爱奇艺影视平台系统。系统开发采用前后端分离的模式开发实现,分为前端系统用户功能模块和后台系统用户功能模块。前端用户的主要功能&#... 查看详情

怎么开发直播短视频源码?

目前直播短视频源码已经跟我们的生活密切相连了,不管我们是做什么都会把手机拿出来看看直播刷刷短视频,在短视频加入直播功能后,短视频直播与其他直播平台一样,迎来了更多的用户关注。其实不难发现&... 查看详情

短视频矩阵管理助手,矩阵管理短视频账号

对于小程序开发者来说,我们是乙方。大家都一直在关注和改善“小程序员”们的开发体验,希望能够降低开发门槛,让小程序开发变成一件轻量的事情,甚至“让天下人都能够拥有自己的小程序”。连小朋友都可以开发自己的... 查看详情

短视频网站定制开发,视频分享网站开发,电影网站开发

绿茶视频系统是是绿茶科技旗下自主开发的视频系统,可??????以支持定制视频相关网站,动漫网站开发,影视导航系统,影视导航源码,电影网站源码,电影网站程序,视频网站源码,一套影视门户网站管理系统,电影、电视剧、综... 查看详情

短视频系统开发常用的推荐算法,各有什么优缺点

刷短视频似乎已经成为现代大多数年轻人茶余饭后必不可少的休闲娱乐方式,随着科技的发展,很多人发现短视频系统似乎有种神奇的魔力,仿佛能读懂人心,推荐的短视频内容越来越符合个人喜好。这与魔力其实没什么关系,... 查看详情

短视频系统开发面临的技术挑战,有压力才有动力

短视频系统之所以会成为近几年互联网发展的新风口,得益于它简单、便捷、全民可参与的玩法。尤其是随着5G的逐渐普及,越来越多人接受并认可了这种新型应用的便利和价值,但是短视频系统开发目前仍旧面临着巨大的技术... 查看详情

趣拍云:深耕细作打造最专业短视频开发平台

短视频是指视频长度不超过2分钟,通过短视频平台拍摄、编辑、上传、播放、分享、互动的,视频形态涵盖纪录短片、DV短片、视频剪辑、微电影、广告片段等的视频短片的统称,伴随着社交媒体的迅猛发展以及网络带宽、云技... 查看详情

直播短视频源码要如何开发?简单几步教你快速开发!

现如今,直播短视频跟我们的生活已经是密不可分了,无论我们是休闲,还是玩手机,都会拿手机出来刷刷短视频,看看直播。同时,在短视频加入直播功能之后,短视频直播与其他直播平台一样,... 查看详情

java仿短视频小程序全栈开发实战视频教程+课程代码

...库规划介绍第5章开发用户登录注册与用户信息第6章上传视频业务流程开发第7章视频展现页开发第8章开发视频的留言板第9章开发短视频后台办理体系第10章项目上线与发布下载地址:百度网盘 查看详情

华为开发者大会主题演讲:抖音短视频网络性能优化实践

...发者大会2021HMSCore6System技术论坛,主题演讲《抖音短视频网络性能优化实践》。演讲嘉宾:卡涛,抖音Android架构师大家好!我是来自字节跳动抖音体验团队的卡涛。我的分享主题是抖音短视频网络性能优化实践。... 查看详情

华为开发者大会主题演讲:抖音短视频网络性能优化实践

...发者大会2021HMSCore6System技术论坛,主题演讲《抖音短视频网络性能优化实践》。演讲嘉宾:卡涛,抖音Android架构师大家好!我是来自字节跳动抖音体验团队的卡涛。我的分享主题是抖音短视频网络性能优化实践。... 查看详情

萌颜短视频特效崛起短视频火速发展

...年代的熟人来说,现在更多的反而是“网友”而一个个短视频。不过短短十几秒的时间,能让人们之间的感情快速升温吗?小编不得不说的一点,人都是视觉动物,大街上看到帅哥美女大家也都会抬起头来看那么一两眼,而短视... 查看详情

无尽的视频播放 ios

】无尽的视频播放ios【英文标题】:endlessvideoplaybackios【发布时间】:2017-02-0810:11:18【问题描述】:我想播放一个视频作为我的视图的背景,所以我决定使用MPMoviePlayerController来播放无尽的视频,我做了这样的事情:NSString*pathForF... 查看详情

快手短视频怎么开发

参考技术A短视频APP的开发让用户可以随时随地通过视频的方式分享自己的生活,和传统的文字、图片分享相比,更加真实、丰富和有吸引力。一、短视频APP开发注意事项1、视频特效和素材视频特效是给视频加上不同级别的美颜... 查看详情

短视频行业竞争加码开发者点赞趣拍云感恩钜惠活动

一、短视频成为新的创业风口2016年,短视频超过了图文和组图,成为了今日头条最大的内容形态,日均播放次数超过了10亿次。继第二届头条号创作者大会上宣布对短视频作者投入10亿人民币,今日头条宣布已完成了对移动视频... 查看详情

手机短视频应用--用户行为分析和优化指南

根据趣拍云的数据统计分析,日前所有接入趣拍短视频SDK的App用户每天的鉴权请求平均在1300万次左右,见下图:   趣拍云目前监测到的App短视频拍摄应用,日均启动次数在131133次,日均拍摄完成次数40608次。见下图:   ... 查看详情