在我们的上一篇文章[todo:link]中,我们学会了如何创建虚拟的“舞台”,以创建一个实时的视频聊天体验,以使用Amazon Interactive Video服务(Amazon IVS)为多达12位参与者创建实时的视频聊天体验。作为独立功能,它非常强大,使我们能够为应用程序添加实时协作。但是,创建此功能的目的是使开发人员能够轻松地创建类似于Twitch上“来宾明星”功能的协作实时流媒体体验。在这篇文章中,我们将基于以前的演示,将所有参与者的音频和视频供稿相结合到一个供稿中,并广播将其提供给Amazon IVS频道。
如果您尚未阅读上一篇文章,则应该在继续此帖子之前执行此操作。回顾一下,在那篇文章中,我们学会了如何:
- 使用JavaScript(V3)的AWS SDK创建阶段资源
- 使用JavaScript(v3)的AWS SDK创建一个舞台参与者令牌
- 使用网络广播SDK连接到虚拟阶段,以进行参与者之间的实时视频聊天
创建协作实时流媒体体验的下一步是将本地参与者和远程参与者都结合到可以发布到Amazon IVS频道的单个流中。为此,我们还可以使用Web广播SDK,所以让我们看看它是如何完成的。
创建广播客户端
如果您回想起,在上一篇文章中,我们在DOMContentLoaded
处理程序的内部调用了几个功能,该功能启用了权限,获得的设备,配置了Stage
实例并处理了加入舞台的处理。我们将在称为initBroadcastClient()
的流中添加另一种方法,我们可以使用它来创建IVSBroadcastClient
的实例。我们在标记中需要一个<canvas>
元素的组合流,以便我们的参与者可以预览最终将广播到亚马逊IVS频道。
const initBroadcastClient = async () => {
broadcastClient = IVSBroadcastClient.create({
streamConfig: IVSBroadcastClient.STANDARD_LANDSCAPE,
ingestEndpoint: '[YOUR INGEST ENDPOINT]',
});
const previewEl = document.getElementById('broadcast-preview');
broadcastClient.attachPreview(previewEl);
const bgImage = new Image();
bgImage.src = '/images/stage_bg.png';
broadcastClient.addImageSource(bgImage, 'bg-image', { index: 0 });
};
为了使事情在视觉上更具吸引力,我使用addImageSource()
在流中添加了背景图像。 addImageSource()
方法接收三个参数:图像,源的唯一名称以及用于定义源定义index
(或'layer')的VideoComposition
对象。如果您检查docs是否为VideoComposition
进行检查,您还会注意,它可以包含height
,width
,x
和y
的值。当我们为每个参与者添加视频层时,我们将在一些属性中利用这些属性。
将参与者的音频和视频添加到广播客户端
接下来,我们将为广播客户端添加每个参与者的音频和视频。我们将在上一篇文章中定义的StageEvents.STAGE_PARTICIPANT_STREAMS_ADDED
处理程序内部执行此操作。修改该函数以将调用添加到两个新功能。
stage.on(StageEvents.STAGE_PARTICIPANT_STREAMS_ADDED, (participant, streams) => {
renderParticipant(participant, streams);
renderVideosToClient(participant, streams.find(s => s.streamType === StreamType.VIDEO));
renderAudioToClient(participant, streams.find(s => s.streamType === StreamType.AUDIO));
});
现在,让我们创建renderVideosToClient()
函数。在这里,我将VideoComposition
进行了硬编码,以适合单个参与者的值。在您的应用程序中,您需要动态计算height
,width
,x
和y
值,具体取决于当前参与对话的用户数量。
const renderVideosToClient = async (participant, stream) => {
const participantId = participant.id;
const videoId = `video-${participantId}`;
const composition = {
index: 1,
height: 984,
width: 1750,
x: 85,
y: 48
};
const mediaStream = new MediaStream();
mediaStream.addTrack(stream.mediaStreamTrack);
broadcastClient.addVideoInputDevice(mediaStream, videoId, composition);
};
renderAudioToClient()
函数看起来相似,但是使用SDK的addAudioInputDevice()
方法添加音轨。
const renderAudioToClient = async (participant, stream) => {
const participantId = participant.id;
const audioTrackId = `audio-${participantId}`;
const mediaStream = new MediaStream();
mediaStream.addTrack(stream.mediaStreamTrack);
broadcastClient.addAudioInputDevice(mediaStream, audioTrackId)
};
在这一点上,舞台可以通过致电broadcastClient.startBroadcast('[YOUR STREAM KEY]')
来广播到频道。当他们离开舞台时,我们还需要处理从broadcastClient
中删除参与者。为此,更新StageEvents.STAGE_PARTICIPANT_STREAMS_REMOVED
的处理程序。
stage.on(StageEvents.STAGE_PARTICIPANT_STREAMS_REMOVED, (participant, streams) => {
const videoTrackId = `video-${participant.id}`;
const audioTrackId = `audio-${participant.id}`;
if (broadcastClient.getVideoInputDevice(videoTrackId)) broadcastClient.removeVideoInputDevice(videoTrackId);
if (broadcastClient.getAudioInputDevice(audioTrackId)) broadcastClient.removeAudioInputDevice(audioTrackId);
const videoId = `${participant.id}-video`
document.getElementById(videoId).closest('.participant-col').remove();
updateVideoCompositions(); // function not defined in demo, implementation will vary
});
这是一个参与者的实现方式。请注意,每个阶段参与者将显示在底部屏幕上,并在上面显示要广播的复合视图。
并且当多个参与者加入虚拟阶段时,应用程序会调整布局以适应每个参与者。
当“主机”参与者单击“广播”按钮时,组合的对话将被广播到Amazon IVS频道,作为复合视图,所有参与者音频和视频都合并为单个流。
概括
在这篇文章中,我们学会了如何通过来自多个远程参与者的音频和视频创建实时广播。在以后的帖子中,我们将研究创建复合流并将其广播到Amazon IVS频道的替代选项。