【HarmonyOS 6.0】AVSession Kit 新增私有数据发送能力详解
鸿蒙6.0新增跨设备私有数据发送能力,通过在AVSession、AVSessionController和AVCastController中新增sendCustomData方法,实现音视频应用、播控中心和投播控制器之间的双向数据传输。该功能支持传输任意键值对数据,满足直播弹幕、投播同步、歌词时间戳等场景需求。媒体应用可通过AVSession向控制方发送数据,播控中心通过AVSessionContro
文章目录

1 -> 概述
鸿蒙6.0(HarmonyOS 6.0)在 AVSession Kit(音视频播控服务)中新增了一项重要能力:跨设备私有数据发送。这一能力通过在三个核心类——AVSession、AVSessionController 和 AVCastController 中统一新增 sendCustomData 方法实现,支持在媒体应用(会话提供方)、播控中心(会话控制方)以及投播控制器之间发送自定义私有数据到远端设备。
这一特性的引入,标志着鸿蒙分布式媒体播控体系从“单向控制”向“双向数据互通”的演进。在此之前,AVSession 主要承载的是标准化的媒体信息(元数据)和播放控制命令(播放、暂停、下一首等)。但实际业务场景中,仅靠标准化数据远远不够——例如:
- 直播场景需要传输弹幕消息、礼物特效指令
- 投播场景需要同步播放列表、当前播放进度(精确到毫秒)
- 音乐播放器需要同步歌词同步时间戳、音效设置
- 视频应用需要传输字幕语言偏好、画质选择
新增的 sendCustomData 接口,为这些私有数据提供了一个直达远端设备的传输通道。
在鸿蒙的媒体会话体系中,主要涉及三类角色:
- 媒体会话提供方(
AVSession):音视频应用的会话实例,负责设置媒体元数据、播放状态等,并响应控制命令。媒体会话提供方通过AVSession对象调用sendCustomData,可以向所有已连接的媒体会话控制方(如播控中心)发送私有数据。 - 媒体会话控制方(
AVSessionController):播控中心等系统应用的控制器实例,负责监听会话状态、发送控制命令。媒体会话控制方通过AVSessionController对象调用sendCustomData,可以向指定的媒体会话提供方发送私有数据。 - 投播控制器(
AVCastController):投播场景中用于控制远端播放的接口。投播控制器通过AVCastController对象调用sendCustomData,可以在投播主控端与远端设备之间传输私有数据。
2 -> 功能解析
2.1 -> AVSession 会话提供方发送私有数据
媒体应用(会话提供方)通过 AVSession 实例的 sendCustomData 方法,可以向所有媒体会话控制方发送私有数据。
接口签名:
sendCustomData(customData: { [key: string]: Object }): Promise<void>
参数说明:
| 参数名 | 类型 | 说明 |
|---|---|---|
| customData | { [key: string]: Object } | 私有数据对象,以键值对形式传输,支持任意类型的数据 |
返回值: Promise<void>,异步操作结果。
系统能力: SystemCapability.Multimedia.AVSession.Core
使用示例:
import { avSession } from '@kit.AVSessionKit';
import { BusinessError } from '@kit.BasicServicesKit';
// 假设已有 AVSession 实例 currentAVSession
async function sendCustomDataFromSession() {
try {
const customData = {
type: 'lyric_sync',
timestamp: Date.now(),
lyricLine: '越过山丘 虽然已白了头',
position: 125000 // 播放位置,毫秒
};
await currentAVSession.sendCustomData(customData);
console.info('sendCustomData success');
} catch (err) {
let error = err as BusinessError;
console.error(`sendCustomData failed: code=${error.code}, message=${error.message}`);
}
}
应用场景: 音视频应用需要将自定义数据(如歌词同步信息、弹幕消息、播放列表变化)同步到播控中心或其他控制方时,使用此方法。
2.2 -> AVSessionController 会话控制方发送私有数据
播控中心等媒体会话控制方通过 AVSessionController 实例的 sendCustomData 方法,可以向指定的媒体会话提供方发送私有数据。
接口签名:
sendCustomData(customData: { [key: string]: Object }): Promise<void>
参数说明: 同 AVSession.sendCustomData。
错误码说明:
| 错误码ID | 错误信息 |
|---|---|
| 6600101 | Session service exception(会话服务异常) |
| 6600102 | The session does not exist(会话不存在) |
| 6600103 | The session controller does not exist(会话控制器不存在) |
使用示例:
import { avSession } from '@kit.AVSessionKit';
import { BusinessError } from '@kit.BasicServicesKit';
// 假设已有 AVSessionController 实例
async function sendCommandToSession() {
try {
const customData = {
action: 'volume_up',
step: 5,
requestId: Date.now().toString()
};
await avSessionController.sendCustomData(customData);
console.info('Control command sent');
} catch (err) {
let error = err as BusinessError;
console.error(`sendCustomData failed: ${error.message}`);
}
}
应用场景: 播控中心需要向音视频应用下发私有控制指令(如自定义音量调节、特效触发、画中画切换等),使用此方法。
2.3 -> AVCastController 投播控制器发送私有数据
投播场景中,应用通过 AVCastController 实例的 sendCustomData 方法,可以在投播主控端与远端设备之间传输私有数据。
接口签名:
sendCustomData(customData: { [key: string]: Object }): Promise<void>
参数说明: 同 AVSession.sendCustomData。
使用示例:
import { avSession } from '@kit.AVSessionKit';
import { BusinessError } from '@kit.BasicServicesKit';
// 获取 AVCastController 实例
async function sendCustomDataToRemote() {
try {
// 通过 AVSession 获取 AVCastController
const castController = await currentAVSession.getAVCastController();
const customData = {
type: 'playlist_sync',
playlistId: 'playlist_12345',
currentIndex: 3,
nextTrackId: 'track_67890'
};
await castController.sendCustomData(customData);
console.info('Custom data sent to remote device');
} catch (err) {
let error = err as BusinessError;
console.error(`sendCustomData to remote failed: ${error.message}`);
}
}
应用场景: 投播场景中,主控端需要将播放列表、用户偏好设置、画质选择等私有数据传输到远端设备,使用此方法。
3 -> 完整实现示例
以下是一个完整的媒体应用接入示例,涵盖 AVSession 创建、激活、私有数据发送与接收等完整流程。
3.1 -> 步骤一:导入模块与权限配置
module.json5 配置:
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.MEDIA_CONTROL"
},
{
"name": "ohos.permission.DISTRIBUTED_DATASYNC"
}
],
"abilities": [
{
"name": "EntryAbility",
"backgroundModes": ["audioPlayback", "dataTransfer"]
}
]
}
}
导入模块:
import { avSession } from '@kit.AVSessionKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';
3.2 -> 步骤二:创建并激活 AVSession
@Entry
@Component
struct MediaPlayerPage {
private tag: string = "MyMediaApp";
private currentAVSession?: avSession.AVSession;
private context = this.getUIContext().getHostContext();
async aboutToAppear(): Promise<void> {
await this.createAVSession();
}
async createAVSession(): Promise<void> {
try {
// 创建音频类型的 AVSession
this.currentAVSession = await avSession.createAVSession(
this.context,
this.tag,
"audio"
);
console.info(`AVSession created: ${this.currentAVSession.sessionId}`);
// 设置媒体元数据
const metadata: avSession.AVMetadata = {
assetId: "song_001",
title: "夜曲",
artist: "周杰伦",
album: "十一月的萧邦",
duration: 300000 // 5分钟,毫秒
};
await this.currentAVSession.setAVMetadata(metadata);
// 设置播放状态
const playbackState: avSession.AVPlaybackState = {
state: avSession.PlaybackState.PLAYBACK_STATE_PLAY,
position: 0,
speed: 1.0
};
await this.currentAVSession.setAVPlaybackState(playbackState);
// 激活会话
await this.currentAVSession.activate();
console.info("AVSession activated");
// 注册私有数据接收监听
this.registerCustomDataListener();
} catch (err) {
let error = err as BusinessError;
console.error(`createAVSession failed: code=${error.code}, message=${error.message}`);
}
}
registerCustomDataListener(): void {
if (!this.currentAVSession) return;
// 监听来自控制方的私有数据
this.currentAVSession.on('customDataReceive', (customData: { [key: string]: Object }) => {
console.info(`Received custom data: ${JSON.stringify(customData)}`);
this.handleReceivedCustomData(customData);
});
}
handleReceivedCustomData(customData: { [key: string]: Object }): void {
// 根据数据类型分发处理
switch (customData.type) {
case 'volume_control':
// 处理音量控制
break;
case 'lyric_sync_request':
// 处理歌词同步请求
break;
default:
console.info(`Unknown custom data type: ${customData.type}`);
}
}
async sendCustomDataToController(): Promise<void> {
if (!this.currentAVSession) return;
try {
const customData = {
type: 'playlist_update',
playlistId: 'playlist_123',
totalTracks: 15,
currentTrackId: 'track_005',
timestamp: Date.now()
};
await this.currentAVSession.sendCustomData(customData);
console.info('Custom data sent to controllers');
} catch (err) {
let error = err as BusinessError;
console.error(`sendCustomData failed: ${error.message}`);
}
}
build() {
Column() {
Text('媒体播放器')
.fontSize(20)
.margin(10)
Button('发送私有数据')
.onClick(() => this.sendCustomDataToController())
.margin(10)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
}
3.3 -> 步骤三:投播场景集成
// 投播功能扩展
async function setupCasting(): Promise<void> {
if (!currentAVSession) return;
try {
// 获取投播控制器
const castController = await currentAVSession.getAVCastController();
// 监听设备变化
castController.on('castDeviceChange', (state: avSession.AVCastDeviceState, device: avSession.AVCastDeviceInfo) => {
console.info(`Device ${device.deviceId} state changed: ${state}`);
if (state === avSession.AVCastDeviceState.DEVICE_STATE_CONNECTED) {
// 设备已连接,同步播放状态到远端
syncPlaybackStateToRemote(castController);
}
});
// 监听远端私有数据
castController.on('customDataReceive', (customData: { [key: string]: Object }) => {
console.info(`Remote custom data: ${JSON.stringify(customData)}`);
});
} catch (err) {
let error = err as BusinessError;
console.error(`getAVCastController failed: ${error.message}`);
}
}
async function syncPlaybackStateToRemote(castController: avSession.AVCastController): Promise<void> {
try {
const syncData = {
type: 'playback_state_sync',
position: 125000, // 当前播放位置,毫秒
state: 'playing',
speed: 1.0,
volume: 0.8
};
await castController.sendCustomData(syncData);
console.info('Playback state synced to remote device');
} catch (err) {
let error = err as BusinessError;
console.error(`Sync failed: ${error.message}`);
}
}
3.4 -> 步骤四:控制方集成示例
// 播控中心侧集成示例
async function createControllerAndSendData(sessionId: string): Promise<void> {
try {
// 创建会话控制器
const controller = await avSession.createController(sessionId);
// 监听会话的私有数据
controller.on('customDataReceive', (customData: { [key: string]: Object }) => {
console.info(`Custom data from session ${sessionId}: ${JSON.stringify(customData)}`);
});
// 向会话发送私有数据
const command = {
type: 'set_equalizer',
preset: 'rock',
bands: [0, 2, 4, 2, 0]
};
await controller.sendCustomData(command);
console.info('Custom data sent to session');
} catch (err) {
let error = err as BusinessError;
console.error(`Controller operation failed: ${error.message}`);
}
}
4 -> 总结
4.1 -> 核心优势
-
统一的数据通道:
sendCustomData接口在AVSession、AVSessionController、AVCastController三个核心类中保持一致的签名和使用方式,开发者无需为不同角色编写差异化的数据传输逻辑,降低了学习成本和代码维护复杂度。 -
全场景覆盖:从本地媒体播放到跨设备投播,从应用提供方到系统控制方,私有数据通道覆盖了鸿蒙媒体生态的各个节点,真正实现了全链路的数据互通。
-
灵活的数据结构:键值对形式的自定义数据设计,支持任意类型的数据传输,应用可以根据业务需求自由定义数据结构,不受标准化字段的限制。
-
分布式原生支持:结合鸿蒙软总线技术,私有数据在跨设备传输时具备低延迟、高可靠性的特性,设备发现延迟低于 200ms,状态同步耗时控制在 100ms 以内。
-
与现有能力互补:
sendCustomData并非替代原有的setAVMetadata、setAVPlaybackState等标准化接口,而是在此基础上提供了扩展通道。标准化数据用于系统级展示和控制,私有数据用于业务级定制交互,两者相辅相成。
4.2 -> 开发注意事项
- 三方应用可以作为媒体会话提供方(
AVSession角色),但媒体会话控制方(AVSessionController)和投播组件的完整能力仅对系统应用开放。 sendCustomData发送的数据不会被持久化存储,数据传输的生命周期与会话绑定。- 投播场景中,
AVCastController对象在设备断开连接后失效,再次使用需要重新获取。 - 建议在
sendCustomData调用时添加异常处理,避免因会话状态异常导致应用崩溃。 - 私有数据的大小建议控制在一定范围内,过大的数据包可能影响传输效率。
4.3 -> 适用版本
sendCustomData 接口从 HarmonyOS 6.0(API Version 22)开始支持。使用前请确认开发环境和目标设备满足版本要求。
鸿蒙 6.0 中 sendCustomData 的引入,为音视频开发者提供了更灵活的跨设备通信手段。无论是直播场景的实时互动数据、音乐播放器的歌词同步信息,还是投播场景的用户偏好设置,都可以通过这一统一接口轻松实现。建议音视频类应用尽快适配该接口,以充分利用鸿蒙分布式能力带来的全场景体验优势。
更多推荐



所有评论(0)