Files
SellyCloudSDK_Android_demo/docs/SellySDK_直播推拉流接入文档_Android.md

452 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Selly Live SDK 推拉流接入文档Android
> 统一 SDK 名称:**SellyCloudSDK**
> 本文档适用于 Android 客户端,面向对外集成方与内部使用。
---
## 1. 概述
Selly Live SDK 提供完整的音视频直播能力,支持 **推流(直播发布)****拉流(直播播放)** 两大核心场景,适用于泛直播、互动直播、实时音视频等业务。
### 主要能力
- 支持 **RTMP / RTC** 推流与播放模式
- 高性能音视频采集与编码
- 灵活的视频参数配置(分辨率 / 帧率 / 码率)
- 推流状态与统计回调
- 拉流播放状态与错误回调
- 支持视频帧处理(美颜 / 滤镜 / 水印)
- 基于 **Token 的安全鉴权机制**
- 支持 **RTMP H264 + AAC payload XOR 保护(可选)**
---
## 2. 系统要求
- Android 8.0+Demo `minSdk` 为 26
- 需真机运行(音视频采集限制)
- 需要摄像头 / 麦克风权限
---
## 3. SDK 集成
### 3.1 项目结构参考
- `example/`Android Demo 工程
- 推流示例:`example/src/main/java/com/demo/SellyCloudSDK/live/LivePushActivity.kt`
- 拉流示例:`example/src/main/java/com/demo/SellyCloudSDK/live/LivePlayActivity.kt`
- `example/libs/`:本地 AAR 依赖存放目录
### 3.2 Gradle 依赖方式(仅 AAR
```gradle
dependencies {
implementation files("libs/sellycloudsdk-1.0.0.aar")
}
```
> 若接入美颜等能力,请按业务侧 SDK 要求额外引入第三方美颜库Demo 使用 FaceUnity AAR
### 3.3 权限配置AndroidManifest.xml
```xml
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
```
> 如需截图保存且兼容 Android 9 及以下,可额外申请 `WRITE_EXTERNAL_STORAGE`。
---
## 4. Token 鉴权机制(重点)
### 4.1 Token 注入方式
| 场景 | 设置位置 |
| ---- | ---- |
| 推流 | `SellyLiveVideoPusher.token` |
| 拉流 | `SellyLiveVideoPlayer.token` |
说明:
- Token **不拼接到 URL**
- Token **不绑定 streamId**
- SDK 内部在建立连接时自动携带当前 Token
- 直接使用 RTMP 地址推/拉流不需要 Token可不设置
### 4.2 Token 设置时机(强约束)
#### 推流
必须在以下接口调用 **之前** 设置:
- `startLiveWithStreamId(...)`
#### 拉流
必须在以下接口调用 **之前** 设置:
- `prepareToPlay()`
- `play()`
> ⚠️ 在连接建立后修改 Token不会影响当前连接。
### 4.3 Token 刷新机制说明
- SDK **不提供自动刷新**
- 业务层可在任意时刻 **重新设置 token 属性**
推荐流程:
1. 业务侧向服务端获取新 Token
2. 调用 `pusher.token = newToken` / `player.token = newToken`
3. 停止并重新开始推流 / 拉流流程
### 4.4 RTMP Payload XOR 保护(可选)
用途:
- 防止他人拿到 RTMP 地址后直接播放、转码或截图
生效范围与约束:
- 仅对 **RTMP** 生效
- 仅支持 **H264 + AAC**(当前版本)
- 只处理 payload配置帧SPS/PPS、AAC Sequence Header保持不变
- 推流端与播放端必须使用**同一个 key**
Key 格式:
- `hex` 字符串,建议 16 或 32 字节(即 32/64 个 hex 字符)
- 支持 `0x` 前缀
- 长度必须为偶数
- 非法 key 会被忽略并关闭 XOR会输出 warning 日志)
时机要求:
- 推流:请在 `startLiveWithStreamId(...)` / `startLiveWithUrl(...)` 之前设置 key
- 拉流:请在 `initWithStreamId(...)` / `initWithUrl(...)` 创建播放器时传入 `xorKeyHex`
---
## 5. 推流接入详解
### 5.1 创建推流实例
```kotlin
val pusher = SellyLiveVideoPusher.initWithLiveMode(
context = this,
liveMode = SellyLiveMode.RTMP
)
pusher.delegate = object : SellyLiveVideoPusherDelegate {
override fun liveStatusDidChanged(status: SellyLiveStatus) {}
override fun onStatisticsUpdate(stats: SellyLivePusherStats) {}
override fun onError(error: SellyLiveError) {}
}
```
### 5.2 视频参数配置与预览
```kotlin
val config = SellyLiveVideoConfiguration.defaultConfiguration().apply {
videoSize = SellyLiveVideoResolution.RES_1280x720
videoFrameRate = 25
videoBitRate = 1000 * 1000
videoMinBitRate = 500 * 1000
outputImageOrientation = SellyLiveOrientation.PORTRAIT
}
pusher.attachPreview(previewContainer)
pusher.startRunning(
cameraPosition = SellyLiveCameraPosition.FRONT,
videoConfig = config,
audioConfig = null
)
```
### 5.3 设置推流 Token使用 streamId 时)
```kotlin
pusher.token = pushToken
```
#### RTMP Payload XOR可选
```kotlin
val xorKeyHex = "A1B2C3D4E5F6A7B8C9D0E1F2A3B4C5D6"
// 建议在 startLiveWith... 之前设置
pusher.setXorKey(xorKeyHex)
```
> 若在推流中修改 key需停止并重新开始推流后才会使用新 key。
### 5.4 开始/停止推流
```kotlin
pusher.startLiveWithStreamId(streamId)
```
```kotlin
pusher.stopLive()
```
#### 直接使用 RTMP 地址推流Demo 未覆盖)
```kotlin
val rtmpUrl = "rtmp://your.host/live/streamKey"
pusher.startLiveWithUrl(rtmpUrl)
```
> 直接使用 RTMP 地址推流不需要 Token可不设置。
#### 停止推流(带回调)
```kotlin
pusher.stopLive { error ->
if (error != null) {
// 处理停止失败
}
}
```
### 5.5 常用控制接口
- `setMuted(true/false)`:静音
- `switchCameraPosition(...)`:切换摄像头
- `switchCamera()`:前后摄像头切换(自动切换)
- `startCamera()` / `stopCamera()`:控制摄像头
- `startMicrophone()` / `stopMicrophone()`:控制麦克风
- `setCameraEnabled(true/false)`:关闭/开启摄像头
- `setStreamOrientation(...)`:切换推流方向
- `setVideoConfiguration(...)` + `changeResolution(...)`:动态调整分辨率
- `setBeautyEngine(...)` + `setBeautyEnabled(...)`:接入美颜
- `setBeautyLevel(level)`:设置美颜强度
- `setBitmapAsVideoSource(...)` / `restoreCameraVideoSource()`:背景图推流
### 5.6 生命周期建议
在宿主 Activity 中对齐生命周期:
- `onResume()``pusher.onResume()`
- `onPause()``pusher.onPause()`
- `onDestroy()``pusher.release()`
### 5.7 状态与统计回调
**状态枚举:**
- `Idle`
- `Connecting`
- `Publishing`
- `Reconnecting`
- `Stopped`
- `Failed`
**统计字段:**
- fps
- videoBitrateKbps / audioBitrateKbps
- rttMs
- cpu 使用率Demo 通过 `CpuUsage` 读取)
### 5.8 推流 API 速览(含 Demo 未覆盖)
初始化与预览:
- `initWithLiveMode(context, liveMode)`:创建推流实例
- `setPreviewView(view)`:设置预览 View
- `attachPreview(container)`:将预览 View 添加到容器
- `getPreviewView()`:获取当前预览 View
采集与推流:
- `startRunning(cameraPosition, videoConfig, audioConfig)`:开始采集预览
- `setVideoConfiguration(config)`:更新视频参数
- `setXorKey(hexKey)`:设置 RTMP payload XOR key可选
- `startLiveWithStreamId(streamId)`:使用 streamId 推流
- `startLiveWithUrl(url)`:使用完整 URL 推流
- `stopLive()` / `stopLive(callback)`:停止推流
设备与音视频控制:
- `switchCameraPosition(position)` / `switchCamera()`:切换摄像头
- `startCamera()` / `stopCamera()`:启动 / 停止摄像头
- `startMicrophone()` / `stopMicrophone()`:启动 / 停止麦克风
- `setMuted(true/false)`:静音推流音频
- `setCameraEnabled(true/false)`:开启 / 关闭摄像头
美颜与画面:
- `setBeautyEngine(engine)`:设置美颜引擎
- `setBeautyEnabled(true/false)`:启用 / 关闭美颜
- `setBeautyLevel(level)`:设置美颜强度
- `setStreamOrientation(orientation)`:设置推流方向
- `changeResolution(width, height)`:动态调整分辨率
- `setBitmapAsVideoSource(bitmap)` / `restoreCameraVideoSource()`:背景图推流
生命周期:
- `onPause()` / `onResume()` / `release()`:与 Activity 生命周期对齐
---
## 6. 拉流接入详解
### 6.1 创建播放器
```kotlin
val player = SellyLiveVideoPlayer.initWithStreamId(
context = this,
streamId = streamId,
liveMode = SellyLiveMode.RTC,
xorKeyHex = "" // RTC 场景可留空
)
// 或直接使用完整 URL
// val player = SellyLiveVideoPlayer.initWithUrl(this, playUrl, xorKeyHex = "A1B2...")
```
若需要指定 `vhost` / `appName`
```kotlin
val player = SellyLiveVideoPlayer.initWithStreamId(
context = this,
streamId = streamId,
liveMode = SellyLiveMode.RTMP,
vhost = "your-vhost",
appName = "live",
xorKeyHex = "A1B2C3D4E5F6A7B8C9D0E1F2A3B4C5D6"
)
```
> 使用 RTMP 加密流时,请在创建播放器时传入 `xorKeyHex`;后续如需换 key请重建播放器实例。
### 6.2 设置拉流 Token使用 streamId 时)
```kotlin
player.token = playToken
```
> 直接使用 RTMP 地址拉流不需要 Token可不设置。
### 6.3 播放流程
```kotlin
player.attachRenderView(renderContainer)
player.prepareToPlay()
player.play()
```
控制接口:
- `pause()`
- `stop()`
- `play()`
- `setMuted(true/false)`
- `release()`
补充接口Demo 未覆盖):
- `setRenderView(view)`:手动指定渲染 View
- `seekBy(deltaMs)`:播放进度跳转(仅在流支持快进/回放时有效)
### 6.4 播放回调
```kotlin
player.delegate = object : SellyLiveVideoPlayerDelegate {
override fun playbackStateChanged(state: SellyPlayerState) {}
override fun onFirstVideoFrameRendered() {}
override fun onFirstAudioFrameRendered() {}
override fun onLatencyChasingUpdate(update: SellyLatencyChasingUpdate) {}
override fun onLatencyChasingReloadRequired(latencyMs: Long) {}
override fun onError(error: SellyLiveError) {}
}
```
状态枚举:
- `Idle`
- `Connecting`
- `Playing`
- `Paused`
- `Stopped`
- `Reconnecting`
- `Failed`
### 6.5 播放 API 速览(含 Demo 未覆盖)
创建与渲染:
- `initWithStreamId(context, streamId, liveMode, vhost, appName, xorKeyHex)`:使用 streamId 创建播放器
- `initWithUrl(context, url, xorKeyHex)`:使用完整 URL 创建播放器
- `attachRenderView(container)` / `setRenderView(view)`:设置渲染 View
- `getRenderView()`:获取当前渲染 View
播放控制:
- `prepareToPlay()` / `play()` / `pause()` / `stop()`:播放流程控制
- `seekBy(deltaMs)`:播放进度跳转(流支持回放时有效)
- `isPlaying()`:查询播放状态
- `setMuted(true/false)`:静音播放
统计与释放:
- `setStatsListener { snapshot -> }`:播放统计回调
- `release()`:释放播放器资源
---
## 7. 错误处理与重试建议
### Token 错误
1. 停止当前推 / 拉
2. 获取新 Token
3. 重新设置 Token
4. 重新开始推流 / 拉流流程
### 网络错误
- 监听 `onStatisticsUpdate` 或播放器状态
- 弱网时适当降低分辨率 / 码率
- 必要时重启连接
---
## 8. 最佳实践
- 推流前先完成采集预览
- Token 即将过期前提前刷新
- 使用统计回调做质量监控
- 拉流失败避免无限重试
---
## 9. 常见问题FAQ
### Q1Token 可以拼接到 URL 吗?
**A** 不可以。
SDK 不解析 URL 中的鉴权信息,所有鉴权均通过 `token` 属性完成。
### Q2运行中修改 Token 是否生效?
**A**
运行中修改 Token **不会影响当前已建立的连接**
**下次重连或重新启动推流 / 拉流时会使用新的 Token**
### Q3播放器出现黑屏怎么办
**A** 可按以下步骤排查:
- 检查播放地址是否正确
- 确认当前网络连接正常
- 查看播放器回调中的错误信息
- 确认视频流格式是否被 SDK 支持
### Q4加密流播放花屏/噪音怎么办?
**A** 重点检查以下项:
- 推流端与播放端 `xorKeyHex` 是否完全一致
- key 格式是否为合法 hex偶数长度支持 `0x` 前缀)
- 当前是否为 RTMP + H264 + AAC
- 变更 key 后是否已重启推流 / 重建播放器