#  关于如何接入SDK离线回放功能

本文主要介绍如何接入SDK离线回放功能，包括两大部分，核心功能和其他功能

- [关于如何接入SDK离线回放功能](#关于如何接入sdk离线回放功能)
  - [1. 离线回放核心功能](#1-离线回放核心功能)
    - [1.1 离线回放数据的下载和解压](#11-离线回放数据的下载和解压)
    - [1.2 离线回放播放视频和文档](#12-离线回放播放视频和文档)
      - [1.2.1 主动调用api](#121-主动调用api)
      - [1.2.2 回调事件api](#122-回调事件api)
      - [1.2.3 关键代码示例](#123-关键代码示例)
      - [1.2.4 集成说明](#124-集成说明)
  - [2. 离线回放其他功能](#2-离线回放其他功能)
    - [2.1 聊天功能](#21-聊天功能)
    - [2.2 问答功能](#22-问答功能)
    - [2.3 广播功能](#23-广播功能)
    - [2.4 回放页面信息](#24-回放页面信息)


## 1. 离线回放核心功能

### 1.1 离线回放数据的下载和解压

相关下载CCR的逻辑可以自行实现也可以参照Demo.

解压逻辑请参照demo的localreplay功能，特别说明：

1. 解压时调用的方法为SupZipTool.decompressZipDec(String inputUrl, String outputUrl)。
2. 解压目录为必需的参数。
3. 使用SupZipTool时需要导入so文件：libsupzip.so。

### 1.2 离线回放播放视频和文档

#### 1.2.1 主动调用api

离线回放核心类代码在DWLiveLocalReplay.java（DWLiveLocalReplay为单例）如下

| 方法                                                         | 说明                                                      |
| ------------------------------------------------------------ | --------------------------------------------------------- |
| setReplayParams(DWLiveLocalReplayListener replayListener, DWReplayPlayer player, DocView docView, String dir) | 设置回调、视频、文档、解压路径                            |
| setReplayParams(DWLiveLocalReplayListener replayListener, DWReplayPlayer player, DocView docView, String dir, String pcmToken, String videoId) | 设置回调、视频、文档、解压路径、加密视频token、加密视频id |
| setSpeed(float speed)                                        | 设置倍速播放                                              |
| start()                                                      | 开始播放                                                  |
| stop()                                                       | 停止播放                                                  |
| pause()                                                      | 暂停播放                                                  |
| resume()                                                     | 恢复播放                                                  |
| onDestroy()                                                  | 释放资源                                                  |

播放器核心代码在DWReplayPlayer.java中，调用方法如下

| 方法                                                         | 说明                 |
| ------------------------------------------------------------ | -------------------- |
| DWReplayPlayer(Context context)                              | 构造方法             |
| updateSurface(Surface surface)                               | 更新Surface          |
| start()                                                      | 开始播放             |
| pause()                                                      | 暂停播放             |
| stop()                                                       | 停止播放             |
| reset()                                                      | 重置播放器           |
| release()                                                    | 释放                 |
| destroy()                                                    | 完全释放             |
| setOnPreparedListener(OnPreparedListener listener)           | 设置准备回调         |
| setOnErrorListener(IMediaPlayer.OnErrorListener listener)    | 设置失败回调         |
| setOnInfoListener(OnInfoListener listener)                   | 设置播放状态信息回调 |
| setOnVideoSizeChangedListener(OnVideoSizeChangedListener listener) | 设置视频尺寸信息回调 |

#### 1.2.2 回调事件api

回调事件同在线回放

#### 1.2.3 关键代码示例

设置视频展示布局

```xml
<TextureView
   android:id="@+id/video_view"
   android:layout_width="match_parent"
   android:layout_height="match_parent" />
```

设置文档展示的控件布局：

```xml
<com.bokecc.sdk.mobile.live.widget.DocView
    android:id="@+id/doc_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
```

初始化播放器并设置播放参数

```java
...
DWLiveLocalReplay dwLiveReplay
TextureView video_view;  
DocView doc_view;        
Surface mSurface;        
DWReplayPlayer mPlayer;  
...
 mPlayer = new DWReplayPlayer(this);
 // 1. 设置Surface的回调                                                                   
 video_view.setSurfaceTextureListener(surfaceListener);                                
 // 2. 获取单例                                                                               
 dwLiveReplay = DWLiveLocalReplay.getInstance();    
 // 获取解压路径
 String playPath FileUtil.getUnzipFileName(path)
 // 3. 设置离线回放回调、视频文档控件、解压路径、（加密视频需要传递pcmToken和videoId，从openApi获取）
 dwLiveReplay.setReplayParams(dwLiveLocalReplayListener, mPlayer, docView, playPath);   
 // 4. 设置播放器事件监听    
 mPlayer.setPlayerEvent(playerEvent)    
...
```

获取Surface

下面是通过实现SurfaceTextureListener回调获得

```java
private SurfaceTexture mSurfaceTexture; 
// surface回调                                                                           
TextureView.SurfaceTextureListener surfaceListener = new TextureView.SurfaceTextureListener() {      
     @Override                                                                           
     public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1){ 
         if (mSurfaceTexture != null) {                         
             mVideoContainer.setSurfaceTexture(mSurfaceTexture);
          } else {                                               
             mSurfaceTexture = surfaceTexture;                  
             mSurface = new Surface(surfaceTexture);    
             // 将surface设置给播放器
             mPlayer.setSurface(mSurface);                       
          }                                                                                
     }                                                                                   
     @Override                                                                           
     public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {}                                                                                   
     @Override                                                                           
     public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {           
         mSurface = null;                                                                 
         return false;                                                                   
     }
     @Override                                                                           
     public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {                 
     }                                                                                   
 };                                                                                                                                                                                           
```

#### 1.2.4 集成说明

完成上面的步骤后，基本上我们就能够观看到离线回放的视频画面和文档画面了，也就基本完成了获得场景视频离线回放的核心功能的集成，即观看回放视频和观看回放文档的功能。

## 2. 离线回放其他功能

功能使用时相关的核心类：DWLiveLocalReplayListener（离线回放回调接口类），DWLiveLocalReplay（离线回放核心类）。

### 2.1 聊天功能

离线回放的聊天功能只包括公共聊天内容，此功能为方法回调功能，相关类DWLiveLocalReplayListener，相关方法如下：

| 方法                                                 | 说明             |
| ---------------------------------------------------- | ---------------- |
| onChatMessage(TreeSet<ReplayChatMsg> replayChatMsgs) | 收到回放聊天信息 |

其中回调回来的对象ReplayChatMsg属性信息如下

```java
// 聊天消息内容
private String content;  
// 聊天消息时间 秒
private int time;        
// 发送人用户名
private String userName;     
// 发送人userId
private String userId;     
// 发送人头像
private String avatar;                                                                   
```

### 2.2 问答功能

离线回放的问答的功能包括已公开回答问答和已发布的答案，此功能为方法回调功能，相关类DWLiveReplayListener相关方法如下：

| 方法                                          | 说明             |
| --------------------------------------------- | ---------------- |
| onQuestionAnswer(TreeSet<ReplayQAMsg> qaMsgs) | 收到回放问答信息 |

返回对象ReplayQAMsg包含问题和回答列表，如何操作该类消息，请查看demo

### 2.3 广播功能

离线回放的广播的功能是直播时发布的广播信息列表，此功能为方法回调功能，相关类DWLiveLocalReplayListener，相关方法如下：

| 方法                                                         | 说明         |
| ------------------------------------------------------------ | ------------ |
| onBroadCastMessage(ArrayList<ReplayBroadCastMsg> broadCastMsgList) | 收到广播信息 |

返回对象ReplayBroadCastMsg属性信息如下

```java
// 广播内容   
private String content;                                 
//  广播时间（单位：秒）                                                                     
private int time;                                
// 发广播的人的ID                                                                     
private String publisherId;                           
// 发广播的人的名字                                                                    
private String publisherName;                          
 // 发广播的人的角色                                                                     
//主讲（publisher）、助教（teacher）、主持人（host）、学生或观众（student）、其他没有角色（unknow）
private String publisherRole;                        
```

### 2.4 回放页面信息

离线回放页面信息是通过回调返回给上层调用，此功能为回调功能，相关类是DWLiveLocalReplayListener，相关方法如下

| 方法                                                         | 说明               |
| ------------------------------------------------------------ | ------------------ |
| onPageInfoList(ArrayList<ReplayPageInfo> infoList)           | 回放页面信息       |
| onPageChange(String docId, String docName, int docWidth ,int docHeight, int pageNum, int docTotalPage); | 回调当前翻页的信息 |

返回列表对象ReplayPageInfo属性信息如下：

```java
// 当前文档名称               
private String docName;
// 当前文档页面的标题  
private String pageTitle;
// 当前文档页面的链接 
private String url; 
// 当前文档页面的翻页时间（单位：S） 
private int time;       
```

### 2.5 离线回放字幕加载

离线回放页面的字幕加载方式如下图

![subtitle](../image/subtitle.png)

| 获取字幕是否更新的方法                                       | 说明                                                   |
| ------------------------------------------------------------ | ------------------------------------------------------ |
| DWLiveLocalReplay.getInstance().getReplaySubtitle(accountId, replayId, callback); | 账户id和回放id是必传参数，异步返回字幕对象SubtitleData |

| SubtitleData对象说明 | 说明                                                   | 类型         |
| -------------------- | ------------------------------------------------------ | ------------ |
| defaultSubtitle      | 账户id和回放id是必传参数，异步返回字幕对象SubtitleData | int          |
| subtitlemodel        | 字幕显示模式 0默认字号 1自适应字号                     | int          |
| subtitle             | 字幕1                                                  | SubtitleItem |
| Subtitle2            | 字幕2                                                  | SubtitleItem |

| SubtitleItem对象说明 | 说明                         | 类型   |
| -------------------- | ---------------------------- | ------ |
| url                  | 下载地址，修改字幕地址会变化 | string |
| font                 | 字体                         | string |
| size                 | 字体大小                     | string |
| color                | 字体颜色                     | string |
| surroundColor        | 字体环绕颜色                 | string |
| bottom               | 距底部百分比                 | string |
| code                 | 字幕文件编码                 | string |
| subtitleName         | 字幕名称                     | string |

使用注意：

1.字幕文件的下载，管理均由App自行管理；

2.字幕更新原则，当本地存储的字幕下载地址和接口返回不一致即视为字幕有更新；

3.演示Demo中可参考LocalReplayRoomLayout.java及BaseReplayRoomLayout.java两个视图类；