提交 328cc5a4 编写于 作者: C ccfriend 提交者: cheng

update docs

Signed-off-by: Ncheng <chengcheng14@huawei.com>
......@@ -48,9 +48,6 @@
- 分布式媒体会话
- [分布式媒体会话概述](distributed-avsession-overview.md)
- [使用分布式媒体会话](using-distributed-avsession.md)
- 音视频投播
- [音视频投播概述](avcastpicker-overview.md)
- [使用音视频投播](using-avcastpicker.md)
- 相机
- [相机开发概述](camera-overview.md)
- 相机开发指导
......
# 音视频投播概述
OpenHarmony提供了统一的应用内音视频投播功能设计,通过提供投播组件和标准的接口,帮助开发者可以简单高效地实现将音视频资源投放到其他设备播放,即实现跨端投播。
同时,系统提供默认投播协议Cast+,可以有效提升投播体验。
使用系统提供的投播组件和接口,应用只需要设置对应的资源信息、监听投播中的相关状态,以及应用主动控制的行为(如:播放、暂停)。其他动作包括图标切换、设备的发现、连接、认证等,均由系统完成。
## 基本概述
- **媒体会话(AVSession)**
音视频管控服务,用于对系统中所有音视频行为进行统一的管理。
本地播放时,应用需要向媒体会话提供播放的媒体信息(如正在播放的歌曲、歌曲的播放状态等),并接收和响应播控中心发出的控制命令(如暂停、下一首等)。具体请参考[本地媒体会话](using-avsession-developer.md)
投播时,通过AVSession,应用可以投播能力的设置和查询,并创建投播控制器。
- **投播组件[AVCastPicker](../reference/arkui-ts/ohos-avcastpicker.md)**
系统级的投播组件,可嵌入应用界面的UI组件。当用户点击该组件后,系统将进行设备发现、连接、认证等流程,应用仅需要通过接口获取投播中相关的回调信息。
- **投播控制器[AVCastController](../reference/apis/js-apis-avsession.md#avcastcontroller10)**
在投播后,由应用发起的对远端播放控制的接口,包括播放、暂停、调节音量、设置播放模式、设置播放速度等能力。
- **后台长时任务**
应用实现后台播放,需申请后台长时任务,避免应用在投播后被系统后台清理或冻结。具体参考[长时任务开发指导](../task-management/continuous-task-dev-guide.md)
## 分布式投播交互过程
![](figures/cast-interaction-diagram.png)
1. 用户在应用界面上点击AVCastPicker组件,触发系统发现可用于投播的设备。用户在设备列表中选择对应设备后,系统连接对应设备。
2. 应用通过AVSession监听设备的连接情况,监听到设备已连接后,创建一个AVCastController用于发送控制命令(如播放、暂停、下一首等)。
3. 在本端(包括应用内和播控中心)控制播放时,控制命令将通过AVCastController发送,本端和远端基于Cast+的能力进行数据传输和信息同步,然后更新远端系统预置播放器的状态。
4. 用户同样可以在远端直接控制播放,会直接修改远端播放器的状态。
5. 当远端播放器状态变更后,会触发回调,将状态信息返回到本端。应用可以通过AVCastController监听到远端播放器的状态变化。
## 接入说明
### 基本原则
应用需要接入AVSession,才可以使用系统提供的统一投播能力,由系统进行设备发现和管理。系统不额外提供音视频设备发现的接口给应用进行选择和切换设备。
使用系统提供的统一投播组件,应用无需关注设备的发现连接过程,仅需关注设备在远端是否可用。当用户通过投播组件,选择了某个远端设备并连接成功,应用将通过回调获取到信息,然后可以创建一个AVCastController,用于控制远端设备的播放。
当进入到远端设备投播状态时,应用也可以对应用界面进行重新绘制,比如界面变更为一个遥控器,可控制远端播放。建议应用在进入远端投播时,停止本地的播放器,避免本端和远端设备同时播放的情况,提升用户体验。
### 音视频投播与分布式媒体会话的关联与差异
1. 分布式会话是基于分布式软总线的能力在双端设备之间进行会话信息的同步;投播能力基于Cast+的能力进行数据传输和信息同步,支持的设备类型更丰富。
2. 分布式会话投播音频,需要由用户先进行双端设备的连接,投播成功后,应用在本端设备的控制和本地播放类似;而投播能力支持在远端设备进行播放的展示,体验上会更有优势。
3. 分布式会话仅支持音频投播,不支持视频投播;投播能力后续会扩展,将支持视频投播。
\ No newline at end of file
# 使用音视频投播
通过本开发指导,完成一次音频跨设备投播。
## 接口说明
对于每个异步调用的API均提供了callback函数和Promise函数,以下示例均采用callback函数。详细的API接口说明,请参考[AVCastPicker组件参考](../reference/arkui-ts/ohos-avcastpicker.md)[AVCastController API参考文档](../reference/apis/js-apis-avsession.md#avcastcontroller10)
| 接口 | 说明 |
| -------- | -------- |
| getAVCastController(callback: AsyncCallback\<AVCastController\>): void | 获取远端投播时的控制接口。|
| on(type: 'outputDeviceChange', callback: (state: ConnectionState, device: OutputDeviceInfo) => void): void | 注册设备变化的回调,同时包含了设备的连接状态。|
| sendControlCommand(command: AVCastControlCommand, callback: AsyncCallback\<void\>): void | 投播会话的控制接口,用于进行投播中的各种播控指令 |
| prepare(item: AVQueueItem, callback: AsyncCallback\<void>): void | 准备播放,进行资源加载和缓冲,不会触发真正的播放 |
| start(item: AVQueueItem, callback: AsyncCallback\<void>): void | 开始播放媒体资源 |
| on(type: 'playbackStateChange', filter: Array\<keyof AVPlaybackState\> \| 'all', callback: (state: AVPlaybackState) => void) | 注册播放状态变化的回调 |
| on(type: 'mediaItemChange', callback: AsyncCallback\<AVQueueItem\>): void | 注册当前播放内容更新的回调,返回当前播放的内容的信息。|
>**说明:**
>
> AVCastController由系统获取并返回,在设备连接成功后获取,在设备断开后不能继续使用,否则会抛出异常。
## 开发步骤
1. 创建播放器,并创建AVSession。
通过AVSessionManager创建并激活媒体会话。
```ts
import AVSessionManager from '@ohos.multimedia.avsession'; //导入AVSession模块
// 创建session
async createSession() {
let session: AVSessionManager.AVSession = await AVSessionManager.createAVSession(this.context, 'SESSION_NAME', 'audio');
session.activate();
console.info(`session create done : sessionId : ${session.sessionId}`);
}
```
2. 在需要投播的播放界面创建投播组件AVCastPicker。
```ts
// 创建组件,并设置大小
build() {
Row() {
Column() {
AVCastPicker()
.width('40vp')
.height('40vp')
.border({ width: 1, color: Color.Red })
}
}
}
```
3. 设置AVSession的信息,注册AVSession的回调。用于感知投播连接。
```ts
async setListenerFromController() {
let session: AVSessionManager.AVSession = ALLREADY_CREATE_A_SESSION;
// 监听设备连接状态的变化
session.on("outputDeviceChange", (state, device) => {
if (state == AVCastState.STATE_CONNECTED) { // 设备连接成功
global.avcastcontroller = avsession.getAVCastController();
console.info('get a cast controller successfully');
console.info(`device connected ` + ${JSON.stringify(device)});
// 设置播放参数,开始播放
var playItem = {
itemId: 0,
description: {
mediaId: '12345',
mediaName: 'song1',
mediaType: 'AUDIO',
mediaUri: 'http://resource1_address',
mediaSize: 12345,
startPosition: 0,
duration: 1000,
artist: 'mysong',
albumTitle: 'song1_title',
albumCoverUri: "http://resource1_album_address",
lyricUri: "http://resource1_lyric_address",
iconUri: "http://resource1_icon_address",
appName: 'MyMusic'
}
};
// 准备播放,这个不会触发真正的播放,会进行加载和缓冲
global.avcastcontroller.prepare(playItem, () => {
console.info('prepare done');
});
// 启动播放
global.avcastcontroller.start(playItem, () => {
console.info('play done');
});
// 列表里的第一首歌曲投播的时候,本端的Player要停止
this.localplayer.stop();
// 本端投播后的应用界面由应用进行专辑图、歌手等信息的刷新
// 远端状态的回调,这个回调需要应用进行界面刷新,而不需要执行控制操作
// 回调包括播放状态,播放位置,播放速度,播放模式等
global.avcontroller.on('playbackStateChange', filter: 'all', (state) => {
console.info('playbackStateChange ' + state);
});
// 用于响应远端进行上一首、下一首
global.avcontroller.on('playNext', () => {
// 应用根据列表顺序,更新新的资源进行播放
var nextPlayItem = {
itemId: 2,
description: {
mediaId: '12345',
mediaName: 'song2',
mediaType: 'AUDIO',
mediaUri: 'http://resource2_address',
mediaSize: 12345,
startPosition: 0,
duration: 2000,
artist: 'mysong',
albumTitle: 'song2_title',
albumCoverUri: "http://resource2_album_address",
lyricUri: "http://resource2_lyric_address",
iconUri: "http://resource2_icon_address",
appName: 'MyMusic'
}
};
// 准备播放
global.avcastcontroller.prepare(nextPlayItem, () => {
console.info('prepare done');
});
// 启动播放
global.avcastcontroller.start(nextPlayItem, () => {
console.info('play done');
});
});
}
}
// 可以通过getOutputDevice接口主动查询连接的设备
session.getOutputDevice((device) => {
console.info(`current routing device` + ${JSON.stringify(device)});
});
}
```
4. 通过AVSession获取投播控制器AVCastController,用于控制应用内的播放。
```ts
async sendCommandToSessionByController() {
// 记录从avsession获取的远端控制器
// 下发播放命令
let avCommand: AVSessionManager.AVCastControlCommand = {command:'play'};
global.avcontroller.sendControlCommand(avCommand);
// 下发暂停命令
let avCommand: AVSessionManager.AVCastControlCommand = {command:'pause'};
global.avcontroller.sendControlCommand(avCommand);
// 播放、暂停等的操作,可以通过状态的回调接口获取到,然后进行本端界面的刷新
}
```
5. 申请投播长时任务,避免应用在投播进入后台时被系统冻结,导致无法持续投播。
```ts
import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';
import wantAgent from '@ohos.app.ability.wantAgent';
function startContinuousTask() {
let wantAgentInfo = {
// 点击通知后,将要执行的动作列表
wants: [
{
bundleName: "com.example.myapplication",
abilityName: "EntryAbility",
}
],
// 点击通知后,动作类型
operationType: wantAgent.OperationType.START_ABILITY,
// 使用者自定义的一个私有值
requestCode: 0,
// 点击通知后,动作执行属性
wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
};
// 通过wantAgent模块的getWantAgent方法获取WantAgent对象
try {
wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj) => {
try {
backgroundTaskManager.startBackgroundRunning(mContext,
backgroundTaskManager.BackgroundMode.MULTI_DEVICE_CONNECTION, wantAgentObj).then(() => {
console.info("Operation succeeded");
}).catch((error) => {
console.error(`Operation failed. code is ${error.code} message is ${error.message}`);
});
} catch (error) {
console.error(`Operation failed. code is ${error.code} message is ${error.message}`);
}
});
} catch (error) {
console.error(`Operation getWantAgent failed. code is ${error.code} message is ${error.message}`);
}
}
```
6. 音频焦点的处理。请参考[多音频并发处理](audio-playback-concurrency.md)
在应用进入投播后,当前应用需要去注册焦点处理,以免被其他应用的焦点申请而影响。
**当前投播支持全局切换,后续如果规格变更,再同步调整方案说明。**
7. 结束投播。
当远端设备断开的时候,应用会收到事件,系统会自动断开连接。
应用也可以使用断开投播的接口,主动进行投播连接的断开。
```ts
async release() {
// 一般来说,应用退出时,而不希望继续投播,可以主动结束
await global.avsession.stopCasting();
}
```
......@@ -157,7 +157,7 @@
- [OffscreenCanvasRenderingContext2D对象](ts-offscreencanvasrenderingcontext2d.md)
- [Path2D对象](ts-components-canvas-path2d.md)
- 高级组件
- [@ohos.avcastpicker (投播组件)](ohos-avcastpicker.md)
- [@ohos.multimedia.avcastpicker (投播组件)](ohos-multimedia-avcastpicker.md)
- 动画
- [属性动画](ts-animatorproperty.md)
- [显式动画](ts-explicit-animation.md)
......
......@@ -33,7 +33,7 @@ AVCastPicker()
## 示例
投播功能的示例说明请参考[音视频投播](../../media/avcastpicker-overview.md)
投播功能的示例说明参考如下
```ts
import AVCastPicker from '@ohos.multimedia.avCastPicker'
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册