使用无头方法实现客户端广告插入
在本教程中,您将使用无头方法在Vega应用中实现客户端广告插入 (CSAI)。这种方法使用客户端-服务器架构,其中用户界面层中的IPlayerClient实例通过基于JavaScript接口 (JSI)的进程间通信 (IPC) 与独立服务层中的VideoPlayer实例进行通信。您将设置一个双播放器架构,其中一个主播放器客户端用于播放内容,一个广告播放器客户端在广告插播期间接管共享视频展示位。
本教程中的示例演示了用于实现无缝广告过渡的预缓冲广告。有关CSAI概念、技巧和同步策略的背景信息,请参阅Vega中的客户端广告插入。
在本教程中,您将学习如何:
- 设置播放器客户端引用和导入
- 检测广告标记并预初始化广告播放器客户端
- 等待广告缓冲,然后暂停主要内容
- 切换视频展示位并播放广告
- 广告结束后返回至主要内容
先决条件
- Vega开发环境已设置
- Vega SDK v0.22或更高版本
@amazon-devices/kepler-player-client和@amazon-devices/kepler-player-client程序包已安装- 主要内容播放器客户端已初始化并已连接到服务
- React Native和TypeScript的基础知识
设置播放器客户端引用
导入所需的程序包并为主播放器客户端、广告播放器客户端和会话ID创建引用。
import {
PlayerClientFactory,
IPlayerClient,
IPlayerSessionPositionListener,
} from '@amazon-devices/kepler-player-client';
import {
IPlayerSessionId,
IPlayerSessionMediaInfo,
IPlayerSessionStatus,
IPlayerSessionState,
} from '@amazon-devices/kepler-player-server';
// 播放器客户端引用
const playerClient = useRef<IPlayerClient | undefined>(undefined); // 主要内容播放器客户端(已初始化)
const adPlayerClient = useRef<IPlayerClient | undefined>(undefined); // 广告播放器客户端
const playerSessionId = useRef<IPlayerSessionId | undefined>(undefined); // 主会话ID
const adPlayerSessionId = useRef<IPlayerSessionId | undefined>(undefined); // 广告会话ID
const sessionIdCounter = useRef(1);
检测广告标记并预初始化广告播放器客户端
当位置侦听器检测到即将到来的广告插播时,使用autoPlay=false预初始化广告播放器客户端,并注册侦听器以了解广告何时缓冲以及何时结束。
- 设置位置侦听器以检测即将到来的广告插播。
const positionListener: IPlayerSessionPositionListener = {
onPositionUpdated: (updatedPosition) => {
const currentTime = updatedPosition[0]?.position || 0;
// 用于确定广告插播是否临近的应用特定逻辑
if (adBreakApproaching(currentTime)) {
initializeAdPlayer(adMediaInfo);
}
},
};
- 创建广告播放器客户端初始化函数。注册状态侦听器以检测READY和ENDED状态。在
IPlayerSessionState.READY不可用的平台上,该服务会发送playerReady消息作为回退。
const initializeAdPlayer = async (adMediaInfo: IPlayerSessionMediaInfo) => {
const factory = new PlayerClientFactory();
adPlayerClient.current = factory.getOrMakeClient(serviceComponentId);
adPlayerSessionId.current = { id: sessionIdCounter.current++ };
// 注册状态侦听器以检测ENDED状态(如果可用,则为READY)
await adPlayerClient.current?.registerStatusListener({
onSessionStatusChanged: (updatedStatus: Array<IPlayerSessionStatus>) => {
const adStatus = updatedStatus.find(
s => s.sessionId?.id === adPlayerSessionId.current?.id
);
if (
IPlayerSessionState.READY !== undefined &&
adStatus?.playbackState === IPlayerSessionState.READY
) {
onAdReady();
} else if (adStatus?.playbackState === IPlayerSessionState.ENDED) {
onAdEnded();
}
}
}, adPlayerSessionId.current);
// 回退: 在IPlayerSessionState.READY不可用的平台上,
// 服务改为发送“playerReady”消息
if (IPlayerSessionState.READY === undefined) {
await adPlayerClient.current?.registerMessageListener(
{
onMessageReceived: (message: any) => {
if (message.type === 'playerReady') {
onAdReady();
}
},
},
adPlayerSessionId.current,
);
}
// 加载autoPlay=false的广告以进行手动控制
await adPlayerClient.current?.load(
adMediaInfo,
{ startPosition: 0, autoPlay: false },
adPlayerSessionId.current,
);
};
等待广告缓冲,然后暂停主要内容
在广告播放器发出READY(已缓冲)信号,且侦听器检测到广告开始时间已到来后,暂停主要内容。
let adReady = false;
const onAdReady = () => {
adReady = true;
// 等待位置侦听器以检测广告开始时间
};
// 当达到广告开始时间且广告准备就绪时,侦听器就位:
if (adReady && currentTime >= adStartTime) {
playerClient.current?.pause(playerSessionId.current);
}
切换展示位并播放广告
当主要内容状态更改为PAUSED时,清空主界面并将其交给广告播放器。
await playerClient.current?.registerStatusListener({
onSessionStatusChanged: (updatedStatus: Array<IPlayerSessionStatus>) => {
const mainStatus = updatedStatus.find(
s => s.sessionId?.id === playerSessionId.current?.id
);
if (mainStatus?.playbackState === IPlayerSessionState.PAUSED && adPlayerClient.current) {
clearMainSurfaceHandle();
setAdSurfaceHandle();
adPlayerClient.current?.play(adPlayerSessionId.current);
}
}
}, playerSessionId.current);
返回至主要内容
广告结束后,清理广告展示位,清理广告播放器客户端,然后恢复主要内容。
const onAdEnded = async () => {
await clearAdSurfaceHandle();
cleanupAdPlayer();
await setMainSurfaceHandle();
await playerClient.current?.play(playerSessionId.current);
};
const cleanupAdPlayer = () => {
if (!adPlayerClient.current) return;
adPlayerClient.current.unloadSync(1000, adPlayerSessionId.current);
adPlayerClient.current = undefined;
adReady = false;
};
清理资源
当您的组件卸载或播放器会话结束时,卸载广告播放器客户端并释放资源。
const cleanup = () => {
if (adPlayerClient.current) {
adPlayerClient.current.unloadSync(1000, adPlayerSessionId.current);
adPlayerClient.current = undefined;
}
// 主播放器客户端清理工作通过您现有的拆解逻辑处理
};
相关内容
Last updated: 2026年3月13日

