步骤1:
纳入程序包依赖项
纳入程序包依赖项
将以下文件添加到您的应用程序包中,并定义您的业务逻辑,以向系统中推送最新EPG数据。如需更多指导说明,请参阅EPG引入最佳实践。
您可以通过搜索应用日志来验证这些步骤:
loggingctl log --follow | grep "epg:\|ktf:\|ktf.\|EpgSync"
定义应用的EPG同步任务,方法是在src文件夹中创建EpgSyncTask.ts文件。您可以将以下框架代码用于频道引入逻辑。
import {
ChannelDescriptorBuilder,
ChannelInfoBuilder,
ChannelLineupProvider,
ChannelMetadataBuilder,
EpgLineupInformation,
ExternalIdBuilder,
IChannelInfo,
IExternalId,
IProgram,
InvalidArgumentError,
} from '@amazon-devices/kepler-epg-provider';
const getLatestChannelLineupVersion = () => {
// 待办事项: 从后端查询最新的频道时间表版本。
return '1.0';
};
// “progressCallback”参数用于提供有关
// 引入进度的反馈,用于您稍后将添加的
// 同步源集成。
export const ingestChannelLineup = async (progressCallback?: (percent: number) => void): Promise<void> => {
try {
// 步骤1: 比较最新EPG频道时间表版本与
// EpgLineupInformation.getLastCommittedChannelLineupVersion()
const lastCommitedVersion =
await EpgLineupInformation.getLastCommittedChannelLineupVersion();
const latestVersion = getLatestChannelLineupVersion();
if (lastCommitedVersion === latestVersion) {
// 频道时间表没有变化,因此无需更新
console.info(
`最新的频道时间表版本(${latestVersion})与上次提交的版本(${lastCommitedVersion})相同。将跳过同步。`,
);
return;
}
// 步骤2: 如果版本不匹配,请以小型页面的形式下载
// 客户的授权频道时间表,逐步解析有效负载,
// 并使用ChannelLineupProvider接口设置该时间表。
const channels_page_1 = getChannelData(1, 10);
await ChannelLineupProvider.add(channels_page_1);
if (progressCallback) {
// 待办事项: 计算EPG同步的进度百分比
progressCallback(25);
}
// 待办事项: 使用与上面相同的方法添加其余频道。
if (progressCallback) {
// 待办事项: 计算EPG同步的进度百分比
progressCallback(50);
}
// 步骤3: 使用ChannelLineupProvider.commit提交频道时间表
await ChannelLineupProvider.commit(latestVersion);
} catch (error) {
if (error instanceof InvalidArgumentError) {
// 待办事项: 捕获错误消息并将其推送到后端以快速解决问题。
// 错误消息包括插入失败的总数和前5个失败频道的原因。
console.error(
`EpgSync - 频道时间表引入失败,原因是InvalidArgumentError:${error}`,
);
} else {
// 待办事项: 记录这些错误。还可以考虑将这些错误传播到您的后端,以便与您的亚马逊联系人合作修复这些错误。
console.error(
`EpgSync - 频道时间表引入期间发生了错误:${error}`,
);
}
throw error;
}
};
const getChannelData = (start_num: number, end_num: number): IChannelInfo[] => {
// 待办事项: 添加实际的频道数据。
const channels_list: IChannelInfo[] = [];
for (let i = start_num; i <= end_num; i++) {
const identifier = `频道${i}`;
const name = `频道${i}`;
const descriptor = new ChannelDescriptorBuilder()
.identifier(identifier)
.majorNumber(0)
.minorNumber(0)
.build();
const external_id_list: IExternalId[] = [];
let external_id = new ExternalIdBuilder()
.idType('type')
.value('value')
.build();
external_id_list.push(external_id);
const metadata = new ChannelMetadataBuilder()
.name(name)
.channelType(3)
.externalIdList(external_id_list)
.build();
const channel = new ChannelInfoBuilder()
.channelDescriptor(descriptor)
.channelMetadata(metadata)
.build();
channels_list.push(channel);
}
return channels_list;
};
const doTask = async (): Promise<void> => {
console.info('EpgSync任务启动中...');
await ingestChannelLineup();
// 如果您在EPG同步任务中提供节目数据,请添加节目时间表引入。
// 在更新节目或使用ProgramLineupProvider之前,请提交新的频道时间表(如果需要)。
// 频道和节目更新不能交错。
// await ingestProgramLineup();
// 如果您提供直播活动,请添加直播活动引入。
// await ingestLiveEventLineup();
// 如果在频道和节目时间表引入期间没有引发错误,
// 则EPG同步任务会成功完成。
console.info('EPGSync成功完成!');
};
要在EPG同步任务中提供节目数据,可参考以下节目引入逻辑的框架代码。如果您已将目录与云服务(例如亚马逊目录服务或Gracenote)集成在一起,则无需执行此操作。
import {
IProgram,
IUpsertProgramFailure,
ProgramBuilder,
ProgramLineupProvider2,
} from '@amazon-devices/kepler-epg-provider';
const getLatestProgramLineupVersion = () => {
// 待办事项: 从后端查询最新的节目时间表版本。
return '1.0';
};
//“progressCallback”参数用于提供有关
// 引入进度的反馈,用于您稍后将添加的
// 同步源集成。
export const ingestProgramLineup = async (progressCallback?: (percent: number) => void): Promise<void> => {
try {
// 步骤1: 比较最新EPG节目时间表版本与
// EpgLineupInformation.getLastCommittedProgramLineupVersion()
const lastCommitedVersion =
await EpgLineupInformation.getLastCommittedProgramLineupVersion();
const latestVersion = getLatestProgramLineupVersion();
if (lastCommitedVersion === latestVersion) {
// 上次提交的节目没有任何变化,无需更新
console.info(
`最新的节目时间表版本(${latestVersion})与上次提交的版本(${lastCommitedVersion})相同。将跳过同步。`,
);
return;
}
// 可选步骤: 只有在需要从电子节目指南 (EPG) 中删除错误添加的节目时,
// 使用“clearAllPrograms()”。这样操作不会清除数据存储区中的频道信息。
// 同一事务中,此函数调用“clearAllPrograms()”必须位于对“upsert()”的调用之前。
// 直到调用“commit()”后,ProgramLineupProvider操作才会保留。
// 步骤2: 如果版本不匹配,请以小型页面的形式下载节目时间表,
// 逐步解析,并使用
// 设置该时间表。
// 如果未提交与节目的ChannelDescriptor对应的频道,
// ProgramLineupProvider2.upsert操作将失败。
const programs_page_1 = getProgramData(1, 10);
const upsertProgramFailures_page_1 = await ProgramLineupProvider2.upsert(
programs_page_1,
);
if (upsertProgramFailures_page_1.length > 0) {
// 待办事项: 捕获所有失败节目信息并将其推送到后端,以快速解决节目数据的问题。
console.error(
`EpgSync - 第1页有${upsertProgramFailures_page_1.length}个节目更新和插入失败`,
);
processUpsertProgramFailures(upsertProgramFailures_page_1);
// 待办事项: 可以选择继续更新和插入其余节目或中止节目引入进程。
// throw Error(
// '由于第1页中的节目数据无效而中止节目引入进程',
// );
}
if (progressCallback) {
// 待办事项: 计算EPG同步的进度百分比
progressCallback(75);
}
// 待办事项: 使用与上面相同的方法更新和插入其余节目。
if (progressCallback) {
// 待办事项: 计算EPG同步的进度百分比
progressCallback(100);
}
// 步骤3: 使用ProgramLineupProvider2.commit提交节目时间表
const total_program_failures =
upsertProgramFailures_page_1.length + upsertProgramFailures_page_2.length;
console.info(
`EpgSync - 出错节目总数:${total_program_failures}`,
);
// 待办事项: 如果有任何节目更新和插入失败,并且您在收到这些失败错误时没有中止该进程,
// 则可以更新成功更新和插入的节目的latestVersion,并将失败节目的相关信息
// 发送回后端,以便在下次同步之前修复这些错误。
await ProgramLineupProvider2.commit(latestVersion);
} catch (error) {
// 待办事项: 记录这些错误。还可以考虑将这些错误传播到您的后端,以便与您的亚马逊联系人合作修复这些错误。
console.error(`EpgSync - 节目时间表引入期间发生了错误:${error}`);
throw error;
}
};
const getProgramData = (
channel_start_num: number,
channel_end_num: number,
): IProgram[] => {
// 待办事项: 添加实际的节目数据。下面的示例代码从当前时间开始创建虚构节目。
const programs_list: IProgram[] = [];
const current_time = Date.now();
for (let i = channel_start_num; i <= channel_end_num; i++) {
const identifier = `频道${i}`;
const descriptor = new ChannelDescriptorBuilder()
.identifier(identifier)
.majorNumber(0)
.minorNumber(0)
.build();
// 第一个节目启动时间比当前系统时间早45分钟。
var temp_time = current_time - 45 * 60 * 1000;
// 为每个频道添加50个节目
for (let j = 1; j <= 50; j++) {
const start_time = temp_time;
const end_time = start_time + 60 * 60 * 1000; // 60分钟(以毫秒为单位)
const program_title = `节目${j}`;
const program = new ProgramBuilder()
.identifier(`节目${j}`)
.channelDescriptor(descriptor)
.title(program_title)
.startTimeMs(start_time)
.endTimeMs(end_time)
.build();
programs_list.push(program);
temp_time = end_time;
}
}
return programs_list;
};
// 待办事项: 在日志中添加失败节目的信息并上传到后端,以快速修复无效数据。
const processUpsertProgramFailures = (
upsertProgramFailures: IUpsertProgramFailure[],
): void => {
upsertProgramFailures.forEach((element: IUpsertProgramFailure) => {
const program = element.program;
const program_id = program.identifier;
const channel = element.program.channelDescriptor;
const err =
element.error.message === undefined ? '' : element.error.message;
console.error(
`EpgSync更新和插入ID为${program_id},所属频道ID为${channel.identifier}的节目失败,错误消息为${err}`,
);
});
};
如果您提供直播活动,请先阅读开始使用直播活动,然后查看以下直播活动引入逻辑的框架代码。
import {
EventType,
IAddLiveEventFailure,
ILiveEvent,
LiveEventBuilder,
LiveEventProvider,
PlaybackReferenceBuilder,
PlaybackType,
} from '@amazon-devices/kepler-epg-provider';
import { MediaId } from '@amazon-devices/kepler-media-types';
const getLatestLiveEventLineupVersion = () => {
// 待办事项: 从后端查询最新的直播活动时间表版本。
return '1.0';
};
const ingestLiveEventLineup = async (): Promise<void> => {
try {
// 步骤1: 比较最新EPG直播活动时间表版本与
// EpgLineupInformation.getLastCommittedLiveEventLineupVersion()。
const lastCommitedVersion =
await EpgLineupInformation.getLastCommittedLiveEventLineupVersion();
const latestVersion = getLatestLiveEventLineupVersion();
if (lastCommitedVersion === latestVersion) {
// 上次提交的直播活动没有任何变化,无需更新
console.info(
`最新的直播活动时间表版本${latestVersion}与上次提交的版本${lastCommitedVersion}相同。将跳过同步。`,
);
return;
}
// 步骤2: 如果版本不匹配,请以小型页面的形式
// 逐步解析,并使用
// LiveEventProvider接口设置时间表。
const live_events_page_1 = getLiveEventData(1, 10);
const addLiveEventFailures_page_1 = await LiveEventProvider.add(
live_events_page_1,
);
if (addLiveEventFailures_page_1.length > 0) {
// 待办事项: 捕获所有失败直播活动信息并将其推送到后端,以快速解决直播活动数据的问题。
console.error(
`EpgSync - 页面1有${addLiveEventFailures_page_1.length}个直播活动添加失败`,
);
processAddLiveEventFailures(addLiveEventFailures_page_1);
// 待办事项: 您可以选择继续添加其余直播活动或中止直播活动引入进程。
// throw Error(
// '由于页面1中的直播活动数据无效而中止直播活动引入进程',
// );
}
// 待办事项: 使用与上面相同的方法添加其余直播活动。
// 步骤3: 使用LiveEventProvider.commit提交直播活动时间表
const total_live_event_failures =
addLiveEventFailures_page_1.length + addLiveEventFailures_page_2.length;
console.info(
`EpgSync - 出错直播活动的总数:${total_live_event_failures}`,
);
// 待办事项: 如果有任何直播活动添加失败,并且您在收到这些失败错误时没有中止该进程,
// 则可以更新成功添加的直播活动的latestVersion,并将失败直播活动的相关信息
// 发送回后端,以便在下次同步之前修复这些错误。
await LiveEventProvider.commit(latestVersion);
} catch (error) {
// 待办事项: 记录这些错误。还可以考虑将这些错误传播到您的后端,以便与您的亚马逊联系人合作修复这些错误。
console.error(`EpgSync - 直播活动时间表引入期间发生错误:${error}`);
throw error;
}
};
const getLiveEventData = (start_num: number, end_num: number): ILiveEvent[] => {
// 待办事项: 添加实际的直播活动数据。
const live_events_list: ILiveEvent[] = [];
for (let i = start_num; i <= end_num; i++) {
const playbackReference = new PlaybackReferenceBuilder()
.playbackType(PlaybackType.CONTENT)
.mediaId(new MediaId('contentId', 'catalogName'))
.build();
const start_time = Date.now() - 45 * 60 * 1000;
const end_time = start_time + 60 * 60 * 1000;
const live_event = new LiveEventBuilder()
.identifier(`LiveEvent${i}`)
.eventType(EventType.SCHEDULED_EVENT)
.playbackReference(playbackReference)
.startTimeMs(start_time)
.endTimeMs(end_time)
.title('标题')
.build();
live_events_list.push(live_event);
}
return live_events_list;
};
// 待办事项: 在日志中添加失败直播活动的信息并上传到后端,以快速修复无效数据。
const processAddLiveEventFailures = (
addLiveEventFailures: IAddLiveEventFailure[],
): void => {
addLiveEventFailures.forEach((element: IAddLiveEventFailure) => {
const live_event = element.liveEvent;
const live_event_id = live_event.identifier;
const err =
element.error.message === undefined ? '' : element.error.message;
console.error(
`EpgSync添加ID为${live_event_id}的直播活动失败,错误消息为:${err}`,
);
});
};
接下来,在遵循指定指南的同时,在EPG同步任务中实现您的业务逻辑。
Last updated: 2025年9月30日