您可以通过阿里云SDK使用短视频列表播放器,本文提供了搭建Android系统与iOS系统短视频列表播放器的操作步骤、示例及说明。

效果示例

注意 目前列表播放器只对MP4的视频做了优化,播放HLS视频不建议使用此列表播放器,而是建议使用多个播放器的实现方式。

Android端关键实现

  1. 创建列表播放器。
    创建列表播放器,并设置相关参数。示例如下:
    private AliListPlayer mVideoListPlayer;
    ……
    //创建播放器(必须)
    mVideoListPlayer = AliPlayerFactory.createAliListPlayer(mContext);
    //开启硬解
    mVideoListPlayer.enableHardwareDecoder(true);
    //设置播放器参数
    PlayerConfig config = mVideoListPlayer.getConfig();
    //停止之后清空画面。防止画面残留(建议设置)
    config.mClearFrameWhenStop = true;
    mVideoListPlayer.setConfig(config);
    //开启循环播放。短视频一般都是循环播放的
    mVideoListPlayer.setLoop(true);
    //开启自动播放。
    mVideoListPlayer.setAutoPlay(true);
    //设置预加载个数。此时会加载3个视频。(当前播放、已经播放、未播放)
    mVideoListPlayer.setPreloadCount(1);
  2. 添加多个播放数据源。
    列表播放器支持URL、点播Vid的数据源(STS方式)。示例如下:
    //使用点播服务的视频源
     mVideoListPlayer.addVid("点播视频vid", "视频唯一标识");
    //或者直接使用URL
    mVideoListPlayer.addUrl("视频URL", "视频唯一标识");
    注意 在列表播放器内部,视频是通过视频唯一标识区分的。如果添加的视频源的唯一标识一样,会导致播放错乱。请确保每次添加数据源的视频唯一标识都不一样。
  3. 开始播放视频。
    播放器提供了以下接口,实现基本的定位播放功能。示例如下:
    //直接跳转到某个视频播放
    mVideoListPlayer.moveTo("视频唯一标识",STS信息) //点播Vid源(STS方式)
    mVideoListPlayer.moveTo("视频唯一标识") //URL源
    //播放上一个视频
    mVideoListPlayer.moveToPrev("视频唯一标识",STS信息) //点播Vid源(STS方式)
    mVideoListPlayer.moveToPrev("视频唯一标识") //URL源
    //播放下一个视频
    mVideoListPlayer.moveToNext("视频唯一标识",STS信息) //点播Vid源(STS方式)
    mVideoListPlayer.moveToNext("视频唯一标识") //URL源
  4. TextureView与播放器的配合使用。
    多数列表播放使用了TextureView。正确的使用,可以避免退后台返回黑屏的问题,优化播放体验。
    1. TextureView的基本设置。示例如下:
      TextureView mTextureView = null;
      SurfaceTexture mSurfaceTexture = null;
      Surface mSurface = null;
      ……
      mTextureView = findViewById(R.id.textureView);
      mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
                  @Override
                  public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) {
                    //缓存SurfaceTexture,在退后台再进时使用
                      mSurfaceTexture = surfaceTexture;
                      mSurface = new Surface(surface);
                      //设置播放的surface
                          mVideoListPlayer.setSurface(mSurface);
                    //重绘界面,立即刷新界面
                          mVideoListPlayer.redraw();
                  }
                  @Override
                  public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
                    //画面大小变化的时候重绘界面,立即刷新界面
                          mVideoListPlayer.redraw();
                  }
                  @Override
                  public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
                    //这里一定要return false。这样SurfaceTexture不会被系统销毁
                      return false;
                  }
                  @Override
                  public void onSurfaceTextureUpdated(SurfaceTexture surface) {
                  }
              });
    2. 退后台重进界面
      在onResume中处理退后台再进的情况。示例如下:
      public void onResume() {
            ……
            if (mVideoListPlayer != null && mSurface != null) {
                  mVideoListPlayer.setSurface(mSurface);
                  mVideoListPlayer.redraw();
            }
            ……
      }
  5. 封面的隐藏时机
    播放视频时,隐藏列表播放封面隐藏。示例如下:
    mVideoListPlayer.setOnRenderingStartListener(new IPlayer.OnRenderingStartListener() {
                @Override
                public void onRenderingStart() {
                   //视频第一帧开始渲染。此时可以隐藏封面
                }
            });
  6. 销毁播放器
    播放器使用完后,需要释放播放器,否则会有内存泄漏。示例如下:
    //释放surface
    mVideoListPlayer.setSurface(null);
    //如果按照第4步使用了TextureView,那么还需要释放缓存的surface
    if (mSurface != null) {
                mSurface.release();
    }
    if (mSurfaceTexture != null) {
                mSurfaceTexture.release();
    }
    //释放播放器
    mVideoListPlayer.release();

iOS端关键实现

  1. 创建列表播放器
    创建列表播放器,并设置相关参数。示例如下:
    //创建播放器(必须)
    self.listPlayer = [[AliListPlayer alloc]init];
    //开启硬解
    self.listPlayer.enableHardwareDecoder = YES;
    //循环播放
    self.listPlayer.loop = YES;
    //自动播放
    self.listPlayer.autoPlay = YES;
    //渲染模式
    self.listPlayer.scalingMode = AVP_SCALINGMODE_SCALEASPECTFIT;
    //代理设置
    self.listPlayer.delegate = self;
    //预加载的清晰度
    self.listPlayer.stsPreloadDefinition = @"FD";
    //显示view
    self.listPlayer.playerView = self.simplePlayScrollView.playView;
    //设置预加载个数。此时会加载3个视频。当前播放的,和上下1个。
    mVideoListPlayer.setPreloadCount(1);
  2. 添加多个播放数据源
    列表播放器支持URL、点播Vid的数据源(STS方式)。示例如下:
    //使用点播服务的视频源
    [self.listPlayer addVidSource:点播视频vid uid:"视频唯一标识"];
    //或者直接使用URL
    [self.listPlayer addUrlSource:"视频URL" uid: "视频唯一标识"];
    注意 在列表播放器内部,视频是通过视频唯一标识区分的。如果添加的视频源的唯一标识一样的话,会导致播放错乱。请确保每次添加数据源的视频唯一标识都不一样。
  3. 开始播放视频
    播放器提供了以下接口,实现基本的定位播放功能。示例如下:
    //直接跳转到某个视频播放
    [self.listPlayer moveTo:"视频唯一标识"]; //URL源
    [self.listPlayer moveTo:"视频唯一标识" accId:accId accKey:accKey token:token region:region]; //点播Vid源(STS方式)
    //播放上一个视频
    [self.listPlayer moveToPrev:"视频唯一标识"]; //URL源
    [self.listPlayer moveToPrev:"视频唯一标识" accId:accId accKey:accKey token:token region:region]; //点播Vid源(STS方式)
    //播放下一个视频
    [self.listPlayer moveToNext:"视频唯一标识"]; //URL源
    [self.listPlayer moveToNext:"视频唯一标识" accId:accId accKey:accKey token:token region:region]; //点播Vid源(STS方式)
  4. 滑动控制操作
    1. 点击暂停和播放。示例如下:
      - (void)tap {
          if ([self.delegate respondsToSelector:@selector(AVPSimplePlayScrollViewTapGestureAction:)]) {
              [self.delegate AVPSimplePlayScrollViewTapGestureAction:self];
          }
      }
      - (void)AVPSimplePlayScrollViewTapGestureAction:(AVPSimplePlayScrollView *)simplePlayScrollView {
          if (self.playerStatus == AVPStatusStarted) {
              //如果是播放,则暂停
              [self.listPlayer pause];
          }else if (self.playerStatus == AVPStatusPaused) {
              //如果是暂停,则播放
              [self.listPlayer start];
          }
      }
    2. 滑动控制
      如果列表滑动速度较快,滑动的位置超过一个,则直接调用moveTo接口列表滑动后的回调中去判定。示例如下:
      - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
          CGFloat indexFloat = scrollView.contentOffset.y/self.frame.size.height;
          NSInteger index = (NSInteger)indexFloat;
          .......
            //往下滑动一格
             if (index - self.currentIndex == 1) {
                  if ([self.delegate respondsToSelector:@selector(AVPSimplePlayScrollView:motoNextAtIndex:)]) {
                      [self.delegate AVPSimplePlayScrollView:self motoNextAtIndex:index];
                  }
              }
              //往上滑动一格
              else if (self.currentIndex - index == 1){
                  if ([self.delegate respondsToSelector:@selector(AVPSimplePlayScrollView:motoPreAtIndex:)]) {
                      [self.delegate AVPSimplePlayScrollView:self motoPreAtIndex:index];
                  }
              }
              //滑动多格
              else {
                  if ([self.delegate respondsToSelector:@selector(AVPSimplePlayScrollView:scrollViewDidEndDeceleratingAtIndex:)]) {
                      [self.delegate AVPSimplePlayScrollView:self scrollViewDidEndDeceleratingAtIndex:index];
                  }
              }
      }
      /**
       滚动事件,移动位置超过一个
       @param simplePlayScrollView simplePlayScrollView
       @param index 移动到第几个
       */
      - (void)AVPSimplePlayScrollView:(AVPSimplePlayScrollView *)simplePlayScrollView scrollViewDidEndDeceleratingAtIndex:(NSInteger)index {
          //找到第几个
          AVPDemoResponseVideoListModel *model = [self findModelFromIndex:index];
          //MoveTo到当前
          [self moveToCurrentModel];
      }
  5. 封面的隐藏时机
    播放视频时,隐藏列表播放封面隐藏。示例如下:
    -(void)onPlayerEvent:(AliPlayer*)player eventType:(AVPEventType)eventType {
        switch (eventType) {
            case AVPEventPrepareDone: {
            }
                break;
            case AVPEventFirstRenderedStart: {
                //隐藏封面图
                [self.simplePlayScrollView showPlayView];
            }
                break;
            default:
                break;
        }
    }
  6. 销毁播放器
    播放器使用完后,需要释放播放器,否则会有内存泄漏。示例如下:
    [self.listPlayer stop];
    [self.listPlayer destroy];
    self.listPlayer = nil;