# VOD SDK 使用文档
## 一、概述
### SDK 介绍
VodSDK 是专门为鸿蒙平台设计的音视频点播播放 SDK，用于实现展动平台点播内容的播放。适用于需要集成点播回放功能的各类鸿蒙应用，如在线教育等场景。

### 特性列表
- **点播在线播放**：在线播放展动平台的点播视频。
- **点播离线下载**：离线下载、播放展动平台的视频。
- **文档显示**：支持回看录制过程中展示文档资料。
- **聊天历史**：支持回看历史聊天功能。
-  **问答历史**：支持回看历史问答功能。

### 支持的环境
- **操作系统**：HarmonyOS
- **编程语言**：ArkTS
- **最低版本要求**：5.0.1(13)
- **依赖项**：
    - `"@ohos/axios": "2.2.6"` 需要添加到根目录或者是sdk同级目录的`oh-package.json5`中
 
-  **依赖方式**：

	将`genseesdk.har`放到lib目录或者其他目录下，通过`file:路径/genseesdk.har`进行依赖。
	示例：
  ```ts
    "dependencies": {
      "@gensee/playersdk": "file:libs/genseesdk.har"
    }
  ```
    

## 二、快速开始

### 1. 引入 SDK
确保在项目中正确引入 `@gensee/playersdk` 模块，可通过如下方式引入：

```typescript
import { VodSDK } from '@gensee/playersdk'
```

### 2. 初始化 SDK
在使用 VodSDK 之前，需要先进行初始化操作：

```ts
const vodsdk = new VodSDK()
vodsdk.init()
```

### 3. 输入参数获取点播信息
```typescript
// 创建初始化参数对象
let initParam = new InitParam()
// 设置域名或ip(必填)
initParam.domain = this.vodDomin
// 设置点播 ID（必填)
initParam.number = this.vodId
// 设置昵称（必填)
initParam.nickName = this.nickname
// 设置加入密码
initParam.joinPwd = this.passcode
// 设置traning或webcast
initParam.serviceType = this.serviceType
// 设置自定义用户ID
initParam.userId = this.userId
// 设置站点登录账号
initParam.loginAccount = this.userAccountName
// 设置站点登录密码
initParam.loginPwd = this.userAccountPW
// 设置认证 K 值
initParam.k = this.kValue
// 设置用户自定义参数
initParam.userData = this.userExtraData

// 使用初始化参数进行认证获取点播信息
vodsdk.getVodObject(initParam).then((result:VodParam) => {
    // 认证成功，获取到点播信息
    showToast("获取成功")
}).catch((e: BusinessError | GSError) => {
    // 处理认证失败的情况
    if (e instanceof GSError) {
        showToast(e.errMsg)
    } else {
        showToast("未知错误：" + e.message)
    }
})
```
### 4. 开始播放
先创建一个播放器对象，然后调用其`play`方法，示例如下：

```ts
// 设置点播消息通知回调监听
vodsdk.setVodListener(this.vodListener)
// 创建一个player，用于视频的控制，需要传入获取到的点播信息
this.vodPlayer = vodsdk.createPlayer(getContext(), this.vodParam!)
// 开始播放
this.vodPlayer.play()
```
调用`play`方法后，SDK会自动开始下载、缓存点播视频，当一切就绪会回调`VodListener`的`onInit`方法，随后就会自动开始播放。


## 三、各个模块及 API 使用
### VODSDK 主功能

#### 1. 初始化
在使用 VODSDK 的所有功能之前，必须先调用此方法进行初始化，完成日志工具、环境的初始化以及启动心跳机制。

```ts
const vodSDK = new VodSDK();
vodSDK.init();
```
#### 2. 获取点播件完整信息
这是观看点播的第一步，根据提供的初始化参数，获取点播件的完整信息。

```ts

const initParam: InitParam = {
  // 初始化参数
};
try {
  const vodParam:VodParam = await vodSDK.getVodObject(initParam);
  console.log('获取到的点播参数:', vodParam);
} catch (error) {
  if (error instanceof GSError) {
    console.error('获取点播信息失败:', error.errMsg);
  }
}
```

#### 3. 创建视频播放器对象
创建一个视频播放器对象，调用该播放器的 `play` 方法后，SDK就开始进行获取点播视频流程。后续对视频的暂停、播放、倍速、停止等方法均需要通 `VodPlayer` 该类控制。
`createPlayer`方法需要传入从`getVodObject`方法中获取的`VodParam`对象或者是离线下载后的`VodDownLoadEntity`对象。如果传入的是`VodDownLoadEntity`，那么则是离线播放，过程不需要网络。

- **API**：

```ts
/**
 * 创建视频播放器对象，在调用播放器的play后，点播相关的回调才会正常回调
 * @param context
 * @param vodparam 从getVodObject获取的对象
 * @param cacheDir 可选，指定的缓冲存放目录，默认在cache目录下
 * @returns
 */
createPlayer(context:Context,vodparam:VodParam,cacheDir:string = ""):VodPlayer
```
示例：

```ts

const vodParam = await vodSDK.getVodObject(initParam);
console.log('获取到的点播参数:', vodParam);
try {
  const vodPlayer = vodSDK.createPlayer(context, vodParam);
  // 使用 vodPlayer 进行播放操作
} catch (error) {
  console.error('创建播放器失败:', error);
}
```

#### 4. 设置点播事件回调
设置用于处理点播事件的监听器，当发生初始化完成、视频桢回调、开始缓冲等事件，会调用监听器中的对应方法。

```ts
const myListener: VodListener = {
  onInit: (bHaveVideo, dwTotalLength) => {
    console.log('初始化完成');
  }
  // 其他回调...
};
vodSDK.setVodListener(myListener);
```

#### 5. 绑定文档管理器
将文档视图的管理器与 SDK 绑定，绑定后文档才能在播放器中正常显示。

```ts
const docManager = new DocManager();
vodSDK.bindDocManager(docManager);
```
将创建的`docManager`传入到`DocView`中，SDK的文档数据便可传输到`DocView`中



#### 6. 获取离线下载管理器对象
获取用于离线下载的管理器对象，离线下载、播放操作均通过该管理器进行。

```ts
const context = getContext();
try {
  const downloaderManager = await vodSDK.getDownloaderManager(context);
  // 使用 downloaderManager 进行下载操作
  downloaderManager.startDownload(vodParam!).then(()=>{
    // 已添加到下载队列
  })
} catch (error) {
  console.error('获取下载管理器失败:', error);
}
```



#### 7. 获取交互相关的操作类
获取用于处理交互操作（如聊天、问答等）的操作类。

```ts
const discussionApi = vodSDK.getDiscussionApi();
// 使用 discussionApi 进行交互操作

// 获取历史聊天
discussionApi.getChatHistory(vodParam,0)
// 获取历史问答
discussionApi.getQAHistory(vodParam,0)
```

#### 8. 释放 SDK
不用SDK时，需主动释放SDK所占用的资源，需要在每次退出点播的时候进行清理。清理后如果再次进入点播，不需要重新创建VodSDK对象，直接复用即可。
**如果当前有正在进行中的下载任务，那么调用该方法也会停止下载任务。**

```ts
vodsdk.releaseSDK()
```


### 视频播放
#### 视频播放概述
视频播放我们提供了一个UI控件 `VideoView`,直接将其添加到UI中，当有视频桢时即可自动绘制显示

#### 实例代码
```typescript
VideoView()
    .alignRules({
        top: { anchor: 'title', align: VerticalAlign.Bottom },
        middle: { anchor: '__container__', align: HorizontalAlign.Center }
    })
    .id("Player")
    .width('100%')
    .height('500lpx')
```

### 视频播放控制

#### 概述
视频播放控制模块提供了一系列方法来控制视频的播放，包括开始播放、暂停、恢复、停止、设置播放速度、快进等功能。
`VodPlayer`是通过`VodSDK`的`createPlayer`方式创建。

#### 相关 API 使用

##### 设置视频播放器相关的监听
设置一个监听器，用于处理视频播放过程中的各种事件。

```ts
const listener: VodPlayerListener = {
  onPlayStop: () => {
    console.log('视频播放停止');
  },
  // 实现回调
};
vodPlayer.setListener(listener);
```

##### 开始播放
根据点播参数开始播放视频，可以选择纯音频播放模式。

- **API 方法**：

```ts
/**
 * 开始播放
 * @param isAudioOnly 纯音频播放
 */
play(isAudioOnly: boolean = false)
```
- **参数说明**：
  - `isAudioOnly`：类型为 `boolean`，可选参数，默认为 `false`，表示是否开启纯音频播放模式。
- **使用示例**：

```ts
vodPlayer.play(); // 正常播放
vodPlayer.play(true); // 纯音频播放
```


##### 暂停视频
暂停正在播放的视频。

```ts
const isPaused = vodPlayer.pause();
if (isPaused) {
  console.log('视频已暂停');
} else {
  console.log('暂停失败');
}
```

##### 从暂停状态中恢复播放
恢复暂停的视频继续播放。

```ts
const isResumed = vodPlayer.resume();
if (isResumed) {
  console.log('视频已恢复播放');
} else {
  console.log('恢复播放失败');
}
```

##### 停止播放
停止正在播放的视频

```ts
vodPlayer.stop();
```

##### 3.4 设置倍速播放
设置视频的播放速度。

- **API 方法**：

```ts
/**
 * 设置倍速播放
 * @param speed 播放速率
 */
setSpeed(speed: PlaySpeed)
```
- **参数说明**：
  - `speed`：类型为 `PlaySpeed`，表示播放速率。
- **使用示例**：

```ts
vodPlayer.setSpeed(PlaySpeed.SPEED_200); // 设置为 2 倍速播放
```


##### 快进到某个时间点
将视频快进到指定的时间点。

- **API 方法**：

```ts
/**
 * 快进到某个时间点
 * @param timestamp 单位：毫秒
 */
seekTo(timestamp: number)
```
- **参数说明**：
  - `timestamp`：单位：毫秒，表示要快进的时间点。
- **返回值**：无
- **使用示例**：

```ts
const timestamp = 60000; // 快进到 60000 毫秒处
vodPlayer.seekTo(timestamp);
```

##### 静音视频
将视频静音。

```ts
vodPlayer.mute();
```

##### 取消静音
取消视频的静音状态。

```ts
vodPlayer.unmute();
```


### 文档

#### 文档模块概述
为了方便客户使用，我们直接封装了一个 `DocView` 用于显示文档，在创建 `DocView` 的时候需要传入一个 `DocManager` 对象，并且这个对象需要一并设置给VodSDK，这样即可实现文档的显示。

#### 相关 API 使用

##### 绑定文档管理器
通过 `vodsdk.bindDocManager` 方法将文档管理器与 `vodsdk` 进行绑定，确保文档能够正常显示。

```typescript
private docManager = new DocManager()
        
vodsdk.bindDocManager(this.docManager)
```
##### 显示文档视图
在UI组件中，使用 `DocView` 组件来显示文档。

```typescript
TabContent() { // 父控件随意，这里只是演示
  DocView({manager:this.docManager})
    .width('100%')
    .height('100%')
}
.tabBar('文档')
```
**参数说明**：
- `manager`：`DocManager` 类型的实例，用于管理文档的显示和切换。

### 互动聊天

#### 概述
互动聊天模块提供了获取点播中聊天消息和问答列表的功能，包括在线点播的聊天历史和离线下载点播件的聊天信息。

#### 相关 API 使用

##### 获取点播中全部的聊天消息
根据提供的点播信息和页码，获取指定页的聊天历史记录。

- **API 方法**：

```ts
/**
 * 获取点播中全部的聊天消息
 * @param vodParam 点播信息
 * @param pageIndex 第几页
 * @returns 获取到的聊天信息
 */
getChatHistory(vodParam: VodParam, pageIndex: number): Promise<VodChatMsg[]>
```
- **返回值**：
  - 成功时返回一个 `VodChatMsg` 数组，包含获取到的聊天信息；失败时抛出相应的错误。
- **使用示例**：

```ts
const discussionApi = vodSDK.getDiscussionApi();
const pageIndex = 1;
discussionApi.getChatHistory(vodParam, pageIndex)
 .then((chatMessages) => {
    console.log('获取到的聊天消息:', chatMessages);
  })
 .catch((error) => {
    console.error('获取聊天消息失败:', error);
  });
```

##### 获取离线下载的点播件的聊天信息
该方法用于获取离线下载后的点播中的聊天历史记录。在离线下载成功后，可以无网络使用。

- **API 方法**：

```ts
/**
 * 获取离线下载的点播件的聊天信息
 * @param entity 离线下载的点播信息
 * @returns
 */
getOfflineChatHistory(entity: VodDownLoadEntity): Promise<VodChatMsg[]>
```
- **参数说明**：
  - `entity`：类型为 `VodDownLoadEntity`，包含了离线下载的点播相关信息。
- **返回值**：
  - 成功时返回一个 `VodChatMsg` 数组，包含获取到的聊天信息；失败时抛出相应的错误。
- **使用示例**：

```ts

const discussionApi = vodSDK.getDiscussionApi();
let entitys = await downloadM.getDownloadList()
// 例子中就已下载列表第一个点播为例，但是这里其实要判断该点播件是否下载完成，可能处于下载中的状态
discussionApi.getOfflineChatHistory(entitys[0])
 .then((chatMessages) => {
    console.log('获取到的离线聊天消息:', chatMessages);
  })
 .catch((error) => {
    console.error('获取离线聊天消息失败:', error);
  });
```

##### 获取点播中的问答列表
根据提供的点播信息和页码，获取指定页的问答历史记录。
离线点播也需要通过这个方法进行获取问答信息，此方法必须**联网获取**。

- **API 方法**：

```ts
/**
 * 获取点播中的问答列表
 * @param vodParam
 * @param pageIndex
 * @returns
 */
getQAHistory(vodParam: VodParam, pageIndex: number): Promise<VodQaMsgResult>
```
- **参数说明**：
  - `vodParam`：类型为 `VodParam`，点播信息。
  - `pageIndex`：类型为 `number`，要获取的页码。
- **返回值**：
  - 成功时返回一个`VodQaMsgResult`对象，其中包含 `QaMsg` 数组，包含获取到的问答信息；失败时抛出相应的错误。
  
```ts
export class VodQaMsgResult{
  /**
   * 当前页码
   */
  pageIndex:number = 0
  /**
   * 问答数据
   */
  msgList:QaMsg[] = []
  /**
   * 是否有更多的问答数据
   */
  isMore:boolean = false
}
```
- **使用示例**：

```ts
const discussionApi = vodSDK.getDiscussionApi();
const pageIndex = 1;
discussionApi.getQAHistory(vodParam, pageIndex)
 .then((result) => {
    console.log('获取到的问答消息:', result.msgList);
  })
 .catch((error) => {
    console.error('获取问答消息失败:', error);
  });
```
### 离线下载

#### 概述
离线下载模块提供了用于管理和控制点播视频的离线下载任务，包括开始下载、停止下载、删除下载任务等操作。

#### API 列表

##### 获取下载的 vod 列表
根据用户 ID 获取下载的 vod 列表。如果传入指定的用户 ID，则只会返回该用户 ID 的下载数据；若不传入，则返回所有下载数据。
用户ID的作用是用于区分可能存在的相同设备多账号登录的情况，如不考虑多账号登录的情况，那么不需要传入userID

```ts
const downloadList = downloaderManager.getDownloadList("user123");
```

##### 开始下载
根据传入的 `VodParam` 开始下载任务。如果当前已有下载任务，新任务将被加入未下载队列；如果没有当前任务，则开始下载新任务。

```ts
await downloaderManager.startDownload(vodParam);
```

##### 停止下载
停止所有下载任务，包括当前正在下载的任务和未下载队列中的任务。

```ts
downloaderManager.stopDownload();
```

##### 删除 vod 下载任务
删除指定的 vod 下载任务。如果该任务正在下载，会先停止下载。

```ts
const vodEntity: VodDownLoadEntity = xxx;
downloaderManager.deleteVod(vodEntity);
```

##### 更改下载目录
如果想特殊指定点播的下载地址，那么更改点播下载后的存储位置，需要在 `startDownload` 前调用。

```ts
downloaderManager.changeDownloadDir("/new/download/dir");
```

##### 设置下载监听器
设置一个监听器，用于处理下载过程中的各种事件，如准备下载、开始下载、下载完成、下载停止等。

```ts
const listener: DownloaderListener = {
  onDownloadPrepare: (downloadEntity) => {
    console.log('下载准备:', downloadEntity);
  },
  // 实现其他监听器方法
};
downloaderManager.setDownloadListener(listener);
```

## 四、各个回调监听说明

### 核心监听 VodListener

```ts
export interface VodListener {

  /**
   * 初始化完成
   * @param haveVideo 是否有视频
   * @param duration 点播时长
   */
  onInit : (haveVideo: boolean, duration: number) => void


  /**
   * 点播同步的聊天消息
   * 聊天消息会依据其发送时间，在视频播放进度播放至对应时刻时触发该调用。
   * @param chatMsgs 聊天消息列表
   */
  onChat:(chatMsg: ChatMsg)=> void;

  /**
   * 文档章节信息更新
   * @param list 章节列表，等同于onInit返回的docInfos
   */
  onDocInfo:(list: Array<DocInfo>) => void;
  
  /**
   * 点播广播消息回调
   * @param bcMsgs 广播消息列表
   */
  onBroadCastMsg:(msg: string,msgId:string,sender:string,timestamp:number)=> void;

  /**
   * 播放器布局设置
   * @param timeStamp 时间戳
   * @param layout 布局类型
   */
  onLayoutSet:(timeStamp: number, layout: number)=> void;

  /**
   * 录制信息回调
   * @param startTime 点播录制的实际时间
   * @param storage 点播占用存储大小，单位Byte
   * @param duration 点播总时长，单位毫秒
   */
  onRecordInfo:(startTime: number, storage: number, duration: number)=> void;

  /**
   * 播放错误
   * @param errCode 错误码
   */
  onError:(errCode: ErrCode)=> void;

}

```

### 播放相关回调 VodPlayerListener

```ts
export interface VodPlayerListener{
  /**
   * 播放完成停止通知
   */
  onPlayStop:() => void;

  /**
   * 暂停通知
   */
  onPlayPause:() => void;

  /**
   * 恢复通知
   */
  onPlayResume:() => void;

  /**
   * 进度通知
   * @param position 当前播放进度
   */
  onPosition:(position: number) => void;

  /**
   * 视频分辨率变化通知
   * @param position 当前播放进度
   * @param videoWidth 变化后的视频宽
   * @param videoHeight 变化后的视频高
   */
  onVideoSize:(position: number, videoWidth: number, videoHeight: number) => void;

  /**
   * 任意位置定位播放响应
   * @param position 快进、快退或拖动后的播放进度
   */
  onSeek:(position: number) => void;

  /**
   * 音频电平值
   * @param level 电平大小
   */
  onAudioLevel:(level: number)=> void;

  /**
   * 缓冲状态
   * @param isCaching true表示正在缓冲，false表示缓冲完成
   */
  onCaching:(isCaching: boolean)=> void;

  /**
   * 视频开始播放
   */
  onVideoStart:()=> void;

  /**
   * 视频播放结束
   */
  onVideoEnd:()=> void;

}
```

### 下载相关的回调 DownloaderListener

```ts
export interface DownloaderListener{

  /**
   * 准备开始下载，已经加入到了下载队列
   * @param vodId
   */
  onDownloadPrepare:(downloadEntity:VodDownLoadEntity)=>void
  /**
   * 已经获取到点播的信息
   * @param vodId
   */
  onRecordInfo:(downloadEntity:VodDownLoadEntity)=>void
  /**
   * 开始下载
   * @param downloadEntity
   */
  onDownloadStart:(downloadEntity:VodDownLoadEntity)=>void
  /**
   * 下载暂停
   * @param downloadEntity
   */
  onDownloadStop:(downloadEntity:VodDownLoadEntity)=>void
  /**
   * 下载结束
   * @param downloadEntity
   */
  onDownloadFinish:(downloadEntity:VodDownLoadEntity)=>void
  /**
   * 下载发生错误
   * @param downloadEntity
   * @param errorCode 错误码
   * @param errorMsg 错误信息
   */
  onError:(downloadEntity:VodDownLoadEntity,errorCode:number,errorMsg:string)=>void
  /**
   * 下载中
   * @param downloadEntity
   * @param percent 下载进度0～100
   */
  onDownloading:(downloadEntity:VodDownLoadEntity,percent:number)=>void
}
```