自动播放Amazon IVS实时流
#aws #javascript #amazonivs #livestreaming

有时是将一个应用程序与另一个应用程序区分开的小功能。如果您已将实时流添加到您的应用程序中,并且用户的导航到他们对查看感兴趣的频道中,那么如果频道在访问页面时当前不广播会发生什么?也许您添加了Amazon Interactive Video Service (Amazon IVS) chat来创建互动体验,以便观众可以花时间等待广播互相聊天,但是当广播上线时会发生什么?您的观众是否必须单击一个“播放”按钮,还是更糟地重新加载整个网页才能查看流?我们如何改善这种体验?上线时自动播放流程会更好吗?当然会的!可悲的是,Amazon IVS player没有用于自动播放实时流的内置方法。但是,我们可以解决这个限制!

自动播放视频的一个选项是使用轮询(通过客户端的setInterval())检查流是否广播:

setInterval(() => {
  ivsPlayer.load(streamUrl);
  ivsPlayer.play();
});

这在技术上有效,但这不是最好的主意。通过投票方法,您最终会在控制台中出现大量的404错误。另外,您必须存储该间隔,并最终在何时开始播放时将其清除。您应该多久运行一次支票?每秒似乎很频繁,每10秒似乎很少一次。这是一个混乱的方法,需要额外的代码来管理。

一种更好的方法是在线上网时向客户发送推送通知。通过这种方法,您可以避免投票的混乱,并且可以确保广播公司上网后尽快开始流。那么,我们如何知道何时在线流,我们如何轻松地将通知发送给客户?

我们以前曾考虑使用Amazon EventBridge rules to send push notifications或在流到在线流时提醒,并且我们可以使用类似的方法来自动播放实时流。通过这种方法,我们将创建一个EventBridge规则,该规则会在流中进行在线时触发AWS lambda功能。但是,我们可以使用Amazon IVS CHAT自定义事件(或者)发送推送通知(或除了)发送通知,以向所有连接的CHAT客户端发送消息,并且在客户端的处理程序中,在接收到消息时开始播放流。

不使用Amazon IVS聊天?没关系!您可以利用任何酒吧/子或Websocket实现将消息发送到您的前端。另外,即使您不使用Amazon IVS聊天进行交互式聊天,您仍然可以将其用作应用程序消息的事件总线。

创建Lambda功能和EventBridge规则

让我们使用AWS无服务器应用程序模型(AWS SAM)设置无服务器应用程序。在此应用程序中,我们将拥有一个函数,该功能将用于发送自定义聊天事件。让我们首先看一下AWS lambda函数(index.mjs)。此功能将需要使用使我们能够从AWS SDK使用JavaScript(V3)的@aws-sdk/ivs-chat模块的图层。我们将使用SendEventdocs)方法向我们的聊天客户发送自定义事件。

import { IvschatClient, CreateChatTokenCommand, SendEventCommand } from '@aws-sdk/client-ivschat';

const chatArn = process.env.DEMO_CHAT_ARN;

export const streamStarted = async (event) => {
  const client = new IvschatClient();

  const sendEventInput = {
    roomIdentifier: chatArn,
    eventName: 'STREAM_STARTED',
    attributes: {
      event: JSON.stringify(event),
    },
  }
  const sendEventRequest = new SendEventCommand(sendEventInput);
  const sendEventResponse = await client.send(sendEventRequest)

  const response = {
    statusCode: 200,
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'OPTIONS,GET,PUT,POST,DELETE',
      'Content-Type': 'application/json'
    },
    isBase64Encoded: false
  };
  response.statusCode = 200;
  response.body = JSON.stringify(sendEventResponse, '', 2);
  return response;
};

我们需要一个template.yaml文件来创建和部署该功能。在此模板中,我们还将为EventBridge规则添加一个定义,并为规则创建必要的权限,以调用AWS lambda函数。另请注意,我将DEMO_CHAT_ARN设置为环境变量,以便可以在AWS lambda函数中访问。

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: Amazon IVS Functions
Globals:
  Function:
    Runtime: nodejs18.x
    Timeout: 30
    MemorySize: 128
  Api:
    Cors:
      AllowMethods: "'GET,POST,OPTIONS'"
      AllowHeaders: "'Content-Type'"
      AllowOrigin: "'*'"
      MaxAge: "'600'"
Resources:
  LambdaRefLayer:
    Type: AWS::Serverless::LayerVersion
    Properties:
      LayerName: sam-app-dependencies
      Description: Dependencies for sam app
      ContentUri: dependencies/
      CompatibleRuntimes:
        - nodejs18.x
      LicenseInfo: "MIT"
      RetentionPolicy: Retain

  IVSAccessPolicy:
    Type: AWS::IAM::Policy
    Properties:
      PolicyName: IVSAccess
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Action:
              - 'ivschat:*'
            Resource: '*'
      Roles:
        - Ref: StreamStartedRole

  StreamStarted:
    Type: 'AWS::Serverless::Function'
    Properties:
      Environment:
        Variables:
          DEMO_CHAT_ARN: 'arn:aws:ivschat:us-east-1:[redacted]:room/[redacted]'
      Handler: index.streamStarted
      Layers:
        - !Ref LambdaRefLayer
      CodeUri: lambda/

  EventRule0:
    Type: AWS::Events::Rule
    Properties:
      Description: >-
        Rule to send a custom chat event when an Amazon IVS live stream session
        begins
      EventBusName: default
      EventPattern:
        source:
          - aws.ivs
        detail-type:
          - IVS Stream State Change
        detail:
          event_name:
            - Stream Start
      Name: demo-stream-started-0
      State: ENABLED
      Targets:
        -
          Arn: 
            Fn::GetAtt: 
              - "StreamStarted"
              - "Arn"
          Id: "StreamStartedTarget"

  PermissionForEventsToInvokeLambda: 
    Type: AWS::Lambda::Permission
    Properties: 
      FunctionName: 
        Ref: "StreamStarted"
      Action: "lambda:InvokeFunction"
      Principal: "events.amazonaws.com"
      SourceArn: 
        Fn::GetAtt: 
          - "EventRule0"
          - "Arn"

现在,我们可以通过AWS SAM CLI package此无服务器应用程序。

注意:如果您不熟悉AWS SAM,请查看“入门” guide

sam package --template-file template.yaml --output-template-file packaged.yaml --s3-bucket ivs-demo

deploy it。

sam deploy --template-file packaged.yaml --stack-name ivs-demo-stack --capabilities CAPABILITY_IAM

部署后,您可以验证是否创建了EventBridge规则。一种方法是在EventBridge控制台中查看您的规则。

EventBridge rules

您还可以验证AWS lambda是通过控制台创建的。

AWS Lambda function

现在,我们可以在Amazon IVS频道上启动广播,并观察到Eventbridge规则已通过控制台调用。

EventBridge rule invocations

聆听客户端的自定义活动

现在,我们已将自定义事件发布到Amazon IVS聊天室,我们可以设置前端以连接到聊天室,并在我们的onmessage处理程序中添加一些逻辑,以在自定义事件为时播放流已收到。上面的AWS lambda函数在自定义事件的Attributes属性中发送触发事件,因此我们可以使用该触发事件中的数据来检查频道名称并确定是否需要播放流。在下面的示例中未定义playStream()方法,但它将包含根据您选择的视频播放器播放流的任何必要逻辑。

const connection = new WebSocket('[chat room endpoint]', '[chat token]');

connection.onmessage = (event) => {
  const data = JSON.parse(event.data);

  if (data.Type === 'MESSAGE') {
    // render chat message 
  }
  if (data.Type === 'EVENT') {
    switch (data.EventName) {
      case 'STREAM_STARTED':
        const triggerEvent = JSON.parse(data.Attributes.event);
        if (triggerEvent.detail.channel_name === 'demo-channel' && !isPlaying) {
          playStream();
        } 
        break;
    }
  }
}

就是这样!现在,当广播公司上网时,我们的流将自动播放。

概括

在这篇文章中,我们学会了如何使用EventBridge规则来发送自定义的Amazon IVS聊天事件,当时Amazon IVS实时流会话开始,以便可以自动播放实时流视频。问题,评论和反馈总是在下面欢迎。