Skip to content

recursivecodes/ivs-cloud-cards

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AWS Cloud Cards - Amazon Interactive Video Service

Online Reference

This document is an online companion to the AWS Cloud Cards deck for Amazon Interactive Video Service (Amazon IVS).

Table of Contents

👋 Welcome To Cloud Cards!

🤘 IVS Rocks!

⭐️ Live Streaming Made Easy

Code Samples

$ aws ivs create-channel --name low-latency-demo
import { IvsClient, CreateChannelCommand } 
  from '@aws-sdk/client-ivs';
const client = new IvsClient();
const createChannelInput = {
  'name': 'low-latency-demo',
  'type': 'STANDARD',
}
const command = new CreateChannelCommand(createChannelInput);
const response = await client.send(command);

💪 Save It For Later (Low-Latency)

Code

# create S3 bucket
$ aws s3 mb s3://ivs-demo-recording-bucket
# create recording config
$ aws ivs create-recording-configuration \
  --name demo-config \
  --destination-configuration '{
    "s3": {
      "bucketName": "ivs-demo-recording-bucket"
    }
  }' \
  --thumbnail-configuration '{
    "recordingMode": "INTERVAL",
    "targetIntervalSeconds": 30,
    "storage": ["LATEST"],
  }'
#create channel, associate new recording config
$ aws ivs create-channel \
  --name recorded-channel-demo \
  --recording-configuration-arn [RECORDING_CONFIG_ARN]

💪 Change The Channel

Code

$ aws ivs create-channel \
  --name low-latency-demo \
  --type STANDARD

💪 Members Only

Code

$ openssl ecparam -name secp384r1 -genkey -noout -out priv.pem
$ openssl ec -in priv.pem -pubout -out public.pem
$ aws ivs import-playback-key-pair \
  --public-key-material "`cat public.pem`"
$ aws ivs create-channel --authorized

💪 Flexible Ingest

Code

$ ffmpeg -re -stream_loop -1 \
  -i $VIDEO_FILEPATH -r 30 \
  -c:v libx264 -pix_fmt yuv420p \
  -profile:v main -preset veryfast \
  -x264opts "nal-hrd=cbr:no-scenecut" \
  -minrate 3000 -maxrate 3000 -g 60 \
  -c:a aac -b:a 160k -ac 2 -ar 44100 \
  -f flv rtmps://$INGEST_ENDPOINT:443/app/$STREAM_KEY
$ export URI="srt://$INGEST_ENDPOINT:9000"
$ URI="$URI?streamid=$STREAM_KEY"
$ URI="$URI&passphrase=$PASSPHRASE"
$ ffmpeg -re -i $VIDEO_FILEPATH -c copy -f mpegts $URI

💪 Equal Access

Code

$ git clone https://github.com/aws-samples/\
amazon-ivs-webgpu-captions-demo.git

# initialize the infrastructure
$ npm run deploy:init

# deploy the backend stack
$ npm run deploy:backend

# run the client app
$ npm ci
$ npm run dev

# deploy the client app (optional)
$ npm run deploy:website

💪 What Time Is It?

Code

$ aws ivs put-metadata \
  --channel-arn "[CHANNEL_ARN]" \
  --metadata "test metadata"
const videoEl = document.getElementById('video-player');
const streamUrl = '[PLAYBACK_URL]';
const ivsPlayer = IVSPlayer.create();
ivsPlayer.attachHTMLVideoElement(videoEl);
ivsPlayer.load(streamUrl);
ivsPlayer.play();

const evt = IVSPlayer.PlayerEventType.TEXT_METADATA_CUE;
ivsPlayer.addEventListener(evt, (metadata) => {
  console.log(metadata);
})

💪 No Pirates!

Code

$ aws ivs create-playback-restriction-policy \
  --name demo-policy \
  --enable-strict-origin-enforcement \
  --allowed-countries "US", "JP" \
  --allowed-origins "https://example.com"
# add policy to channel
$ aws ivs update-channel \
  --arn [CHANNEL_ARN] \
  --playback-restriction-policy-arn [POLICY_ARN]

💪 No Interruptions

⭐️ Welcome To The Stage!

Code

$ aws ivs-realtime create-stage --name real-time-demo
$ aws ivs-realtime create-stage --name real-time-demo \
  --participant-token-configurations '[{"userId": "1"}]'
import { IvsRealTimeClient, CreateStageCommand } 
  from "@aws-sdk-client-ivs-realtime";

const client = new IvsRealTimeClient();
const input = {
  name: 'real-time-demo',
  participantTokenConfigurations: [
    {
      userId: "1",
    }
  ]
};
const command = new CreateStageCommand(input);
const response = await client.send(command);

💪 Extended Reach (Part 1)

💪 Extended Reach (Part 2)

Code

$ aws ivs-realtime create-encoder-configuration \
  --name demo-encoder-configuration \
  --video "bitrate=25000000,height=720,width=1280,framerate=30"
$ aws ivs-realtime start-composition \
  --stage-arn [REAL_TIME_STAGE_ARN] \
  --destination '[
    {
      "channel": {
        "channelArn": "[LOW_LATENCY_CHANNEL_ARN]",
        "encoderConfigurationArn": "[ENCODER_CONFIG_ARN]"
      }
    }
  ]'

💪 Save It For Later (Real-Time)

Code

$ aws ivs-realtime create-storage-configuration \
  --name demo-storage-config \
  --s3 "bucket=demo-recording-bucket"
$ aws ivs-realtime create-encoder-configuration \
  --name demo-encoder-configuration \
  --video "bitrate=6000000,height=1080,width=1920,framerate=60"
$ aws ivs-realtime start-composition \
  --stage-arn "[STAGE_ARN]" \
  --destination '[{
    "s3": {
      "encoderConfigurationArn": ["[ENCODER_CONFIG_ARN]"],
      "storageConfigurationArn": "[STORAGE_CONFIG_ARN]"
    }
  }]
  '

💪 WHIP It Up!

💪 Perfect Timing

Code

const config = {
  inBandMessaging: { enabled: true }
};
const stream = new LocalStageStream(videoTrack, config);
const payload = new TextEncoder().encode('test').buffer;
stream.insertSeiMessage(payload);
const strategy = {
    subscribeConfiguration: (participant) => {
        return { inBandMessaging: { enabled: true } };
    }
    // ... other strategy functions
}
stage.on(StageEvents.STAGE_STREAM_SEI_MESSAGE_RECEIVED, 
  (participant, seiMessage) => {
    console.log(seiMessage.payload, seiMessage.uuid);
});
{"timestamp":"...","event":"card_dealt","seat":2,"card":"7H","face_up":true}
{"timestamp":"...","event":"card_dealt","seat":4,"card":"6S","face_up":true}
{"timestamp":"...","event":"card_dealt","card":"3S","face_up":true}
{"timestamp":"...","event":"card_dealt","seat":2,"card":"5H","face_up":true}
{"timestamp":"...","event":"card_dealt","seat":4,"card":"10H","face_up":true}
{"timestamp":"...","event":"card_dealt","card":"4S","face_up":false}
{"timestamp":"...","event":"prompt_player","seat":4}
{"timestamp":"...","event":"player_action","seat":4,"action":"hit"}
{"timestamp":"...","event":"card_dealt","seat":4,"card":"4S","face_up":false}
{"timestamp":"...","event":"prompt_player","seat":4}
{"timestamp":"...","event":"player_action","seat":4,"action":"stand"}
{"timestamp":"...","event":"prompt_player","seat":2}
{"timestamp":"...","event":"player_action","seat":2,"action":"hit"}
{"timestamp":"...","event":"card_dealt","seat":2,"card":"JS","face_up":false}
{"timestamp":"...","event":"prompt_player","seat":2}
{"timestamp":"...","event":"player_action","seat":2,"action":"stay"}
{"timestamp":"...","event":"dealer_reveal","card":"4S"}

💪 Alternative Ingest

Code

$ aws ivs-realtime create-ingest-configuration \
  --name demo-ingest-config \
  --stage-arn "[STAGE_ARN]" \
  --ingest-protocol RTMPS

💪 Real Time, Real Quality

Code

let cameraStream = new LocalStageStream(
  cameraDevice,
  {
    simulcast: { enabled: true }
  }
);
const initialLayerPreference: InitialLayerPreference.LOWEST_QUALITY;
const strategy = {
    subscribeConfiguration: (participant) => {
        return {
            simulcast: {
                initialLayerPreference
            }
        }
    },
    preferredLayerForStream: (participant, stream) => {
      return stream.getLowestQualityLayer();
    }
    // ... other strategy functions
}

⭐️ Hey Chat!

Code

$ aws ivschat create-room --name chat
$ aws ivschat create-chat-token \
  --room-identifier "[CHAT_ARN]" \
  --user-id "1" \
  --capabilities "SEND_MESSAGE"
const token = "[CHAT_TOKEN]";
const endpoint = "[CHAT_ENDPOINT]";
const connection = new WebSocket(endpoint, token);
const payload = {
  "Action": "SEND_MESSAGE",
  "Content": "text message",
}
connection.send(JSON.stringify(payload));
connection.onmessage = (event) => {
  const message = JSON.parse(event.data);
  console.log(message);
}

💪 Watch What You Say!

Code

{
   "Content": "string",
   "MessageId": "string",
   "RoomArn": "string",
   "Attributes": {"string": "string"},
   "Sender": {
      "Attributes": { "string": "string" },
      "UserId": "string",
      "Ip": "string"
   }
}
{
   "Content": "string",
   "ReviewResult": "string",
   "Attributes": {"string": "string"},
}
"Attributes": { "Reason": "denied for moderation" }
$ aws ivschat create-room \
  --name demo-chat \
  --message-review-handler '
    {
      "fallbackResult": "DENY",
      "uri": "[LAMBDA_ARN]",
    }
  '

💪 Remember What They Said

Code

$ aws logs create-log-group --log-group-name demo-chat-cw-logs
$ aws ivschat create-logging-configuration \
  --name demo-chat-log  \
  --destination-configuration '
    {
      "cloudWatchLogs": {
        "logGroupName" : "demo-chat-cw-logs"
      }
    }
  '
$ aws ivschat create-room \
  --name demo-chat  \
  --logging-configuration-identifiers "[LOGGING_CONFIG_ARN]"
$ aws s3 mb s3://demo-chat-s3-logs
$ aws ivschat create-logging-configuration \
  --name demo-chat-log  \
  --destination-configuration '
    {
      "s3": {
        "bucketName" : "demo-chat-s3-logs"
      }
    }
  '
# create firehose delivery stream first...
$ aws ivschat create-logging-configuration \
  --name demo-chat-log  \
  --destination-configuration '
    {
      "firehose": {
        "deliveryStreamName" : "demo-chat-firehose-stream"
      }
    }
  '

☁️ Amazon CloudWatch

☁️ Amazon EventBridge

Code

export const handler = async (event) => {
  console.log(`
    Received: '${event["detail-type"]}'
    named '${event.detail.event_name}'
    at ${event.time}
    on channel ${event.detail.channel_name}
    with stream id ${event.detail.stream_id}.
  `);
}
# create rule
$ aws events put-rule  \
  --name demo-ivs-event \
  --event-pattern "{\"source\": [\"aws.ivs\"]}" \
  --state ENABLED
# add permission to invoke lambda
$ aws lambda add-permission \
  --function-name ivs-demo-function \
  --statement-id EventBridgeInvoke \
  --action lambda:InvokeFunction \
  --principal events.amazonaws.com \
  --source-arn [RULE_ARN]
# add lambda function as target for rule
$ aws events put-targets --rule demo-ivs-rule \
  --targets '{"Id": "1", "Arn": "[LAMBDA_ARN]"}'

☁️ AWS CloudTrail

☁️ Amazon S3

☁️ AWS AppSync

Code

$ aws appsync create-api \
  --name demo-event-api \
  --event-config '
    {
      "authProviders": [{"authType": "API_KEY"}],
      "connectionAuthModes": [{"authType": "API_KEY"}],
      "defaultPublishAuthModes": [{"authType": "API_KEY"}],
      "defaultSubscribeAuthModes": [{"authType": "API_KEY"}]
    }'
$ aws appsync create-api-key --api-id [API_ID]
$ aws appsync create-channel-namespace \
  --name default-api-ns \
  --api-id [API_ID]

🧑🏽‍💻 Watch Anywhere

Code

const videoEl = document.getElementById('video-player');
const streamUrl = '[PLAYBACK_URL]';
const ivsPlayer = IVSPlayer.create();
ivsPlayer.attachHTMLVideoElement(videoEl);
ivsPlayer.load(streamUrl);
ivsPlayer.play();

🧑🏽‍💻 Streaming On The Go

Code

<canvas id="preview"></canvas>

<script type="module">
  const streamKey = '[STREAM_KEY]';
  const ingestEndpoint = '[INGEST_ENDPOINT]';
  const streamConfig = IVSBroadcastClient.STANDARD_LANDSCAPE;
  const config = { streamConfig, ingestEndpoint };
  const client = IVSBroadcastClient.create(config);
  await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
  client.attachPreview(document.getElementById('preview'));
  const devices = await navigator.mediaDevices.enumerateDevices();
  const videoDevices = devices.filter(d => d.kind == 'videoinput');
  const audioDevices = devices.filter(d => d.kind == 'audioinput');
  const cameraStream = 
    await navigator.mediaDevices.getUserMedia({
      video: { 
        deviceId: videoDevices[0].deviceId,
        aspectRatio: 16 / 9,
      },
    });
  const microphoneStream = 
    await navigator.mediaDevices.getUserMedia({
      audio: { 
        deviceId: audioDevices[0].deviceId 
      },
    });
  client.addVideoInputDevice(cameraStream, 'camera1', { index: 0 });
  client.addAudioInputDevice(microphoneStream, 'mic1');
  client.startBroadcast(streamKey)
</script>

💡 Let Them Cook

💡 Place Your Bets

💡 Learning Time

💡 Can You Hear Me?

Code

$ git clone \
  https://github.com/aws-samples/amazon-ivs-real-time-audio-rooms-web-demo.git
$ cd amazon-ivs-real-time-audio-rooms-web-demo
$ npm run deploy:init
$ npm run deploy:backend:dev # for development
$ npm run deploy:backend:prod # for production
$ npm run deploy:website:dev # for development
$ npm run deploy:website:prod # for production
$ npm run dev

💡 Shop Until You Drop

Code

# check out the project
$ git clone \
  https://github.com/aws-samples/\
amazon-ivs-real-time-basic-web-demo.git
$ cd amazon-ivs-real-time-basic-web-demo

# install required packages
$ npm ci

# run the deploy
# when the deployment successfully completes
# copy the url provided in the output
# you may need the url when running client app
$ npm run deploy

# retrieve the CloudFormation stack outputs
$ aws cloudformation describe-stacks \
  --stack-name AmazonIVSRtWebDemoStack \
  --query 'Stacks[].Outputs'

# cleanup (delete all resources associated 
# with this demo including DynamoDB table)
$ npm run destroy

💡 Social Streaming

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published