### Install Camera Kit SDK and Webpack Source: https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/broadcast-3p-camera-filters-integrating-snap.html Installs the Snap Camera Kit SDK and Webpack using npm. Webpack is used as the bundler in this example. ```bash npm i @snap/camera-kit webpack webpack-cli ``` -------------------------------- ### Install FFmpeg on Ubuntu Source: https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/private-ingest-ll.html Run these commands on your Ubuntu instance to install FFmpeg. Ensure you have added the necessary PPA first. ```bash sudo add-apt-repository ppa:savoury1/ffmpeg4 sudo apt-get update sudo apt-get install ffmpeg ``` -------------------------------- ### Start Composition with PiP Layout Source: https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/ssc-getting-started.html Starts a composition using a picture-in-picture (PiP) layout configuration. ```bash aws ivs-realtime start-composition --stage-arn "arn:aws:ivs:us-east-1:927810967299:stage/8faHz1SQp0ik" --destinations '[{"channel": {"channelArn": "arn:aws:ivs:us-east-1:927810967299:channel/DOlMW4dfMR8r", "encoderConfigurationArn": "arn:aws:ivs:us-east-1:927810967299:encoder-configuration/DEkQHWPVaOwO"}}]' --layout '{"pip":{"participantOrderAttribute":"priority","pipParticipantAttribute":"isPip","pipOffset":10,"pipPosition":"TOP_RIGHT"}}' ``` -------------------------------- ### Start Composition with Grid Layout Source: https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/ssc-getting-started.html Starts a composition using a grid layout configuration for the specified stage. ```bash aws ivs-realtime start-composition --stage-arn "arn:aws:ivs:us-east-1:927810967299:stage/8faHz1SQp0ik" --destinations '[{"channel": {"channelArn": "arn:aws:ivs:us-east-1:927810967299:channel/DOlMW4dfMR8r", "encoderConfigurationArn": "arn:aws:ivs:us-east-1:927810967299:encoder-configuration/9W59OBY2M8s4"}}]' --layout '{"grid":{"participantOrderAttribute":"order","featuredParticipantAttribute":"isFeatured","videoFillMode":"COVER","gridGap":0}}' ``` -------------------------------- ### Install Video.js with NPM Source: https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/ivs-player-release-notes.rss Use this command to install the Video.js npm package. Ensure you are using version 7.6.6 or later for compatibility. ```bash npm install video.js@7.6.6 ``` -------------------------------- ### Start Express Server Source: https://docs.aws.amazon.com/ivs/latest/ChatUserGuide/chat-sdk-js-tutorial-chat-rooms.html Listen for requests and run the server. ```javascript app.listen(port, () => { console.log(`Backend listening on port ${port}`); }); ``` ```bash $ node index.js ``` -------------------------------- ### Start Express Server Source: https://docs.aws.amazon.com/ivs/latest/ChatUserGuide/chat-sdk-react-tutorial-chat-rooms.html Add a listener to your Express app to start the server and make it available on the specified port. This confirms the server is running. ```javascript app.listen(port, () => { console.log(`Backend listening on port ${port}`); }); ``` -------------------------------- ### Start HTTP Server for Local Testing Source: https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/broadcast-3p-camera-filters-background-replacement.html Starts a simple Python HTTP server in the current directory to serve files. This is useful for testing the `index.html` and associated assets locally on `localhost:8000`. ```bash python3 -m http.server -d ./ ``` -------------------------------- ### Run HTTPS Server Source: https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/broadcast-3p-camera-filters-integrating-snap.html Command to start the local HTTPS server. ```bash python3 https_server.py ``` -------------------------------- ### Install IVS Web Broadcast SDK using npm Source: https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/broadcast-web-getting-started.html Use this command to install the npm package for the IVS Web Broadcast SDK. This allows you to import the client and other modules. ```bash npm install amazon-ivs-web-broadcast ``` -------------------------------- ### Configure Environment Variables Source: https://docs.aws.amazon.com/ivs/latest/ChatUserGuide/chat-sdk-js-tutorial-chat-rooms.html Example .env file structure for AWS credentials. ```text # .env # The region to send service requests to. AWS_REGION=us-west-2 # Access keys use an access key ID and secret access key # that you use to sign programmatic requests to AWS. # AWS access key ID. AWS_ACCESS_KEY_ID=... # AWS secret access key. AWS_SECRET_ACCESS_KEY=... ``` -------------------------------- ### Initialize React Project Source: https://docs.aws.amazon.com/ivs/latest/ChatUserGuide/chat-sdk-js-tutorial-chat-rooms.html Commands to create a React app and install the IVS Chat SDK. ```bash npx create-react-app chatterbox ``` ```bash npm install amazon-ivs-chat-messaging ``` ```bash yarn add amazon-ivs-chat-messaging ``` -------------------------------- ### Recording Started Metadata Example Source: https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/rt-individual-participant-recording.html This JSON object represents the metadata when a recording has successfully started. It includes stage ARN, session ID, participant ID, recording start time, and initial media details. ```json { "version": "v1", "stage_arn": "arn:aws:ivs:us-west-2:aws_account_id:stage/AbCdef1G2hij", "session_id": "st-ZyXwvu1T2s", "participant_id": "xYz1c2d3e4f", "recording_started_at": "2024-03-13T13:17:17Z", "recording_status": "RECORDING_STARTED", "media": { "hls": { "path": "media/hls", "playlist": "multivariant.m3u8", "renditions": [ { "path": "high", "playlist": "playlist.m3u8" } ] }, "thumbnails": { "path": "media/thumbnails", "renditions": [ { "path": "high" } ] }, "latest_thumbnail": { "path": "media/latest_thumbnail", "renditions": [ { "path": "high" } ] } } } ``` -------------------------------- ### Initialize Web Project Files Source: https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/getting-started-broadcast-sdk.html Create a new directory and initial files for a web-based IVS broadcast application. ```bash mkdir realtime-web-example cd realtime-web-example touch index.html touch app.js ``` -------------------------------- ### Monitor Recording via EventBridge Source: https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/rt-individual-participant-recording.html Example of the EventBridge event payload received when participant recording starts. ```json { "version": "0", "id": "12345678-1a23-4567-a1bc-1a2b34567890", "detail-type": "IVS Participant Recording State Change", "source": "aws.ivs", "account": "123456789012", "time": "2024-03-13T22:19:04Z", "region": "us-east-1", "resources": ["arn:aws:ivs:us-west-2:123456789012:stage/AbCdef1G2hij"], "detail": { "session_id": "st-ZyXwvu1T2s", "event_name": "Recording Start", "participant_id": "xYz1c2d3e4f", "recording_s3_bucket_name": "ivs-recordings", "recording_s3_key_prefix": "///2024-01-01T12-00-55Z" } } ``` -------------------------------- ### Initialize Backend Project Source: https://docs.aws.amazon.com/ivs/latest/ChatUserGuide/chat-sdk-js-tutorial-chat-rooms.html Commands to create a directory and initialize a Node.js project. ```bash $ mkdir backend & cd backend ``` ```bash $ npm init ``` ```text entry point: (index.js) ``` ```bash $ npm install express aws-sdk cors dotenv ``` -------------------------------- ### Initialize Stage with Strategy Source: https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/web-publish-subscribe.html Demonstrates the complete setup of a stage strategy, including local track acquisition, required strategy functions, and stage initialization. ```javascript const devices = await navigator.mediaDevices.getUserMedia({ audio: true, video: { width: { max: 1280 }, height: { max: 720 }, } }); const myAudioTrack = new LocalStageStream(devices.getAudioTracks()[0]); const myVideoTrack = new LocalStageStream(devices.getVideoTracks()[0]); // Define the stage strategy, implementing required functions const strategy = { audioTrack: myAudioTrack, videoTrack: myVideoTrack, // optional updateTracks(newAudioTrack, newVideoTrack) { this.audioTrack = newAudioTrack; this.videoTrack = newVideoTrack; }, // required stageStreamsToPublish() { return [this.audioTrack, this.videoTrack]; }, // required shouldPublishParticipant(participant) { return true; }, // required shouldSubscribeToParticipant(participant) { return SubscribeType.AUDIO_VIDEO; } }; // Initialize the stage and start publishing const stage = new Stage(token, strategy); await stage.join(); // To update later (e.g. in an onClick event handler) strategy.updateTracks(myNewAudioTrack, myNewVideoTrack); stage.refreshStrategy(); ``` -------------------------------- ### Sample Get Stream Session Response Source: https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/stream-health.html Example JSON response structure returned by the get-stream-session command. ```json { "streamSession": { "startTime": "2021-10-22T00:03:57+00:00", "streamId": "st-1FQzeLONMT9XTKI43leLSo1", "truncatedEvents": [ { "eventTime": "2021-10-22T00:09:30+00:00", "name": "Session Ended", "type": "IVS Stream State Change" }, { "eventTime": "2021-10-22T00:09:30+00:00", "name": "Stream End", "type": "IVS Stream State Change" }, { "eventTime": "2021-10-22T00:03:57+00:00", "name": "Stream Start", "type": "IVS Stream State Change" }, { "eventTime": "2021-10-22T00:03:50+00:00", "name": "Session Created", "type": "IVS Stream State Change" } ], "endTime": "2021-10-22T00:09:31+00:00", "ingestConfiguration": { "audio": { "channels": 2, "codec": "mp4a.40.2", "sampleRate": 48000, "targetBitrate": 160000 }, "video": { "avcLevel": "4.0", "avcProfile": "Baseline", "codec": "avc1.42C028", "encoder": "obs-output module (libobs version 27.0.1)", "targetBitrate": 3500000, "targetFramerate": 30, "videoHeight": 1080, "videoWidth": 1920 } }, "channel": { "name": "", "ingestEndpoint": "3f234d592b38.global-contribute.live-video.net", "authorized": false, "latencyMode": "LOW", "recordingConfigurationArn": "", "type": "STANDARD", "playbackUrl": "https://3f234d592b38.us-west-2.playback.live-video.net/api/video/v1/us-west-2.991729659840.channel.dY7LsluQX1gV.m3u8", "arn": "arn:aws:ivs:us-west-2:991729659840:channel/dY7LsluQX1gV" } } } ``` -------------------------------- ### Recording Start Event JSON Source: https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/eventbridge.html Example of an IVS Recording State Change event when a stream begins recording. ```json { "version": "0", "id": "12345678-1a23-4567-a1bc-1a2b34567890", "detail-type": "IVS Recording State Change", "source": "aws.ivs", "account": "123456789012", "time": "2020-06-23T20:12:36Z", "region": "us-west-2", "resources": [ "arn:aws:ivs:us-west-2:123456789012:channel/AbCdef1G2hij" ], "detail": { "channel_name": "Your Channel", "stream_id": "st-1A2b3c4D5e6F78ghij9Klmn", "recording_status": "Recording Start", "recording_status_reason": "", "recording_s3_bucket_name": "r2s3-dev-channel-1-recordings", "recording_s3_key_prefix": "ivs/v1/123456789012/AbCdef1G2hij/2020/6/23/20/12/j8Z9O91ndcVs", "recording_duration_ms": 0, "recording_session_id": "a6RfV23ES97iyfoQ" } } ``` -------------------------------- ### Setup and Registration Source: https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/player-videojs.html Instructions for including the IVS Video.js tech script and registering it with the Video.js player instance. ```APIDOC ## Setup Amazon IVS Video.js Tech ### Description To integrate Amazon IVS with Video.js, include the script tag and register the tech using the `registerIVSTech` function. ### Setup Steps 1. Include the script tag: ```html ``` 2. Register the tech: ```javascript registerIVSTech(videojs); ``` ### Player Instantiation When creating the player, add `AmazonIVS` as the first tech in the `techOrder` option. Note that the Video.js `sources` option is not supported; use the `src()` function instead. ``` -------------------------------- ### Recording Start Failure Event JSON Source: https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/eventbridge.html Example of an IVS Recording State Change event when recording fails to initialize. ```json { "version": "0", "id": "12345678-1a23-4567-a1bc-1a2b34567890", "detail-type": "IVS Recording State Change", "source": "aws.ivs", "account": "123456789012", "time": "2020-06-23T20:12:36Z", "region": "us-west-2", "resources": [ "arn:aws:ivs:us-west-2:123456789012:channel/AbCdef1G2hij" ], "detail": { "channel_name": "Your Channel", "stream_id": "st-1A2b3c4D5e6F78ghij9Klmn", "recording_status": "Recording Start Failure", "recording_status_reason": "ValidationException", "recording_s3_bucket_name": "r2s3-dev-channel-1-recordings", "recording_s3_key_prefix": "", "recording_duration_ms": 0, "recording_session_id": "a6RfV23ES97iyfoQ" } } ``` -------------------------------- ### Create npm Project Directory Source: https://docs.aws.amazon.com/ivs/latest/ChatUserGuide/chat-sdk-react-tutorial-chat-rooms.html Initialize a new Node.js project for your backend application. Navigate into the created directory to begin setup. ```bash $ mkdir backend & cd backend ``` -------------------------------- ### Example HLS Playlist with Synchronization Tags Source: https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/rt-individual-participant-recording.html This HLS playlist demonstrates the inclusion of EXT-X-PROGRAM-DATE-TIME tags at the start of the recording and at discontinuity points. ```HLS #EXTM3U #EXT-X-VERSION:7 #EXT-X-TARGETDURATION:12 #EXT-X-PLAYLIST-TYPE:VOD #EXT-X-MAP:URI="init-0.mp4" #EXT-X-PROGRAM-DATE-TIME:2024-01-01T12:00:00.000Z #EXTINF:3.30091, 0.mp4 #EXTINF:5.63794, 1.mp4 #EXTINF:2.74290, 2.mp4 #EXT-X-DISCONTINUITY #EXT-X-MAP:URI="init-1.mp4" #EXT-X-PROGRAM-DATE-TIME:2024-01-01T12:00:52.772Z #EXTINF:2.54412, 3.mp4 #EXTINF:5.63649, 4.mp4 ``` -------------------------------- ### Initialize npm Project Source: https://docs.aws.amazon.com/ivs/latest/ChatUserGuide/chat-sdk-react-tutorial-chat-rooms.html Create a package.json file for your Node.js application. Press Enter to accept default values for most prompts. ```bash $ npm init ``` -------------------------------- ### AWS IVS Stream Start Event Example Source: https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/eventbridge.html This event is sent when a stream is being processed and segments are available for the viewer. It indicates that the stream is live and viewable. ```json { "version": "0", "id": "01234567-0123-0123-0123-012345678901", "detail-type": "IVS Stream State Change", "source": "aws.ivs", "account": "aws_account_id", "time": "2017-06-12T10:23:43Z", "region": "us-east-1", "resources": [ "arn:aws:ivs:us-east-1:aws_account_id:channel/12345678-1a23-4567-a1bc-1a2b34567890" ], "detail": { "event_name": "Stream Start", "channel_name": "Your Channel", "stream_id": "st-1A2b3c4D5e6F78ghij9Klmn" } } ``` -------------------------------- ### AWS IVS Session Created Event Example Source: https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/eventbridge.html This event is sent when a channel stream key was used successfully and a stream session was created. It indicates the start of a new streaming session. ```json { "version": "0", "id": "aa5b7a40-36cf-8dc4-5554-32d70e047215", "detail-type": "IVS Stream State Change", "source": "aws.ivs", "account": "535011710559", "time": "2024-09-09T16:17:26Z", "region": "us-east-1", "resources": [ "arn:aws:ivs:us-west-2:535011710559:channel/UCGaMPGLCbcE" ], "detail": { "event_name": "Session Created", "channel_name": "", "stream_id": "st-1AuTyMDASvHUTSb8p5PvbsO" } } ``` -------------------------------- ### Update VIDEO_DEVICE_NAME in Broadcast SDK Source: https://docs.aws.amazon.com/ivs/latest/userguide/doc-history.html In the Broadcast Web SDK Guide, the `VIDEO_DEVICE_NAME` variable was updated to `VIDEO_DEVICE_NAME.source` in "Hide Video" code examples. Ensure this change is reflected in your implementation. ```javascript VIDEO_DEVICE_NAME.source ``` -------------------------------- ### Initialize App Elements and Modules Source: https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/broadcast-3p-camera-filters-background-replacement.html JavaScript setup to retrieve DOM elements and import MediaPipe modules for image segmentation. ```javascript const canvasElement = document.getElementById("canvas"); const background = document.getElementById("background"); const canvasCtx = canvasElement.getContext("2d"); const backgroundCtx = background.getContext("2d"); const video = document.getElementById("webcam"); import { ImageSegmenter, FilesetResolver } from "@mediapipe/tasks-vision"; ``` -------------------------------- ### Recording Started Event JSON Source: https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/record-to-s3.html This JSON payload indicates that a recording session has successfully started. It includes the channel ARN, start time, and initial media details. ```json { "version": "v1", "channel_arn": "arn:aws:ivs:us-west-2:123456789012:channel/AsXego4U6tnj", "recording_started_at": "2020-06-12T12:53:26Z", "recording_status : "RECORDING_STARTED", "media": { "hls": { "path": "media/hls", "playlist": "master.m3u8", "byte_range_playlist": "byte-range-multivariant.m3u8", "renditions": [ { "path": "480p30", "playlist": "playlist.m3u8", "byte_range_playlist": "byte-range-variant.m3u8", "resolution_height": 480, "resolution_width": 852 }, { "path": "360p30", "playlist": "playlist.m3u8", "byte_range_playlist": "byte-range-variant.m3u8", "resolution_height": 360, "resolution_width": 640 }, { "path": "160p30", "playlist": "playlist.m3u8", "byte_range_playlist": "byte-range-variant.m3u8", "resolution_height": 160, "resolution_width": 284 }, { "path": "720p60", "playlist": "playlist.m3u8", "byte_range_playlist": "byte-range-variant.m3u8", "resolution_height": 720, "resolution_width": 1280 } ] }, "thumbnails": { "path": "media/thumbnails", "resolution_height": 480, "resolution_width": 852 }, "latest_thumbnail": { "path": "media/latest_thumbnail/thumb.jpg", "resolution_height": 480, "resolution_width": 852 } } } ``` -------------------------------- ### Create a Recording Configuration Source: https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/create-channel-cli.html Commands to initialize a recording configuration with S3 storage, optional thumbnail settings, or stream reconnection windows. ```bash aws ivs create-recording-configuration --name configuration-1 --destination-configuration s3={bucketName=test-bucket} ``` ```bash aws ivs create-recording-configuration --name configuration-1 --destination-configuration s3={bucketName=s3_bucket_name} --thumbnail-configuration recordingMode="INTERVAL",targetIntervalSeconds=60 ``` ```bash aws ivs create-recording-configuration --name configuration-1 --destination-configuration s3={bucketName=test-bucket} --recording-reconnect-window-seconds 60 ``` -------------------------------- ### Get or Set Playback Rate Source: https://docs.aws.amazon.com/ivs/latest/userguide/player-videojs.html Gets or sets the video playback rate. For live streams, a get returns 1 and a set is ignored. Valid rates are in the range [0.25, 2.0]. ```javascript playbackRate playbackRate(rate) ``` -------------------------------- ### Setup Local User Streams Source: https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/getting-started-pub-sub-ios.html Discovers local camera and microphone devices and assigns them to the local participant. ```swift private var streams = [IVSLocalStageStream]() private let deviceDiscovery = IVSDeviceDiscovery() private func setupLocalUser() { // Gather our camera and microphone once permissions have been granted let devices = deviceDiscovery.listLocalDevices() streams.removeAll() if let camera = devices.compactMap({ $0 as? IVSCamera }).first { streams.append(IVSLocalStageStream(device: camera)) // Use a front camera if available. if let frontSource = camera.listAvailableInputSources().first(where: { $0.position == .front }) { camera.setPreferredInputSource(frontSource) } } if let mic = devices.compactMap({ $0 as? IVSMicrophone }).first { streams.append(IVSLocalStageStream(device: mic)) } participants[0].streams = streams participantsChanged(index: 0, changeType: .updated) } ``` -------------------------------- ### Initialize Camera Kit and Stage Session Source: https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/broadcast-3p-camera-filters-integrating-snap.html Sets up the Camera Kit, creates a session, loads lenses, and configures event listeners for UI controls and stage events. Requires API token and lens group ID. ```javascript /*! Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ const { Stage, LocalStageStream, SubscribeType, StageEvents, ConnectionState, StreamType, } = IVSBroadcastClient; import { bootstrapCameraKit, createMediaStreamSource, Transform2D, } from '@snap/camera-kit'; let cameraButton = document.getElementById('camera-control'); let micButton = document.getElementById('mic-control'); let joinButton = document.getElementById('join-button'); let leaveButton = document.getElementById('leave-button'); let controls = document.getElementById('local-controls'); let videoDevicesList = document.getElementById('video-devices'); let audioDevicesList = document.getElementById('audio-devices'); let lensSelector = document.getElementById('lens-selector'); let session; let availableLenses = []; // Stage management let stage; let joining = false; let connected = false; let localCamera; let localMic; let cameraStageStream; let micStageStream; const liveRenderTarget = document.getElementById('canvas'); const init = async () => { await initializeDeviceSelect(); const cameraKit = await bootstrapCameraKit({ apiToken: 'INSERT_YOUR_API_TOKEN_HERE', }); session = await cameraKit.createSession({ liveRenderTarget }); const { lenses } = await cameraKit.lensRepository.loadLensGroups([ 'INSERT_YOUR_LENS_GROUP_ID_HERE', ]); availableLenses = lenses; populateLensSelector(lenses); const snapStream = liveRenderTarget.captureStream(); lensSelector.addEventListener('change', handleLensChange); lensSelector.disabled = true; cameraButton.addEventListener('click', () => { const isMuted = !cameraStageStream.isMuted; cameraStageStream.setMuted(isMuted); cameraButton.innerText = isMuted ? 'Show Camera' : 'Hide Camera'; }); micButton.addEventListener('click', () => { const isMuted = !micStageStream.isMuted; micStageStream.setMuted(isMuted); micButton.innerText = isMuted ? 'Unmute Mic' : 'Mute Mic'; }); joinButton.addEventListener('click', () => { joinStage(session, snapStream); }); leaveButton.addEventListener('click', () => { leaveStage(); }); }; async function setCameraKitSource(session, mediaStream) { const source = createMediaStreamSource(mediaStream); await session.setSource(source); source.setTransform(Transform2D.MirrorX); session.play(); } const populateLensSelector = (lenses) => { lensSelector.innerHTML = ''; lenses.forEach((lens, index) => { const option = document.createElement('option'); option.value = index; option.text = lens.name || `Lens ${index + 1}`; lensSelector.appendChild(option); }); }; const handleLensChange = (event) => { const selectedIndex = parseInt(event.target.value); if (session && availableLenses[selectedIndex]) { session.applyLens(availableLenses[selectedIndex]); } }; const joinStage = async (session, snapStream) => { if (connected || joining) { return; } joining = true; const token = document.getElementById('token').value; if (!token) { window.alert('Please enter a participant token'); joining = false; return; } // Retrieve the User Media currently set on the page localCamera = await getCamera(videoDevicesList.value); localMic = await getMic(audioDevicesList.value); await setCameraKitSource(session, localCamera); // Create StageStreams for Audio and Video cameraStageStream = new LocalStageStream(snapStream.getVideoTracks()[0]); micStageStream = new LocalStageStream(localMic.getAudioTracks()[0]); const strategy = { stageStreamsToPublish() { return [cameraStageStream, micStageStream]; }, shouldPublishParticipant() { return true; }, shouldSubscribeToParticipant() { return SubscribeType.AUDIO_VIDEO; }, }; stage = new Stage(token, strategy); // Other available events: // https://aws.github.io/amazon-ivs-web-broadcast/docs/sdk-guides/stages#events stage.on(StageEvents.STAGE_CONNECTION_STATE_CHANGED, (state) => { connected = state === ConnectionState.CONNECTED; if (connected) { joining = false; controls.classList.remove('hidden'); lensSelector.disabled = false; } else { controls.classList.add('hidden'); lensSelector.disabled = true; } }); stage.on(StageEvents.STAGE_PARTICIPANT_JOINED, (participant) => { console.log('Participant Joined:', participant); }); stage.on( StageEvents.STAGE_PARTICIPANT_STREAMS_ADDED, (participant, streams) => { ``` -------------------------------- ### S3 Prefix Example Source: https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/record-to-s3.html A concrete example of an S3 prefix path for a recorded stream. ```text ivs/v1/123456789012/AsXego4U6tnj/2020/6/23/20/12/j8Z9O91ndcVs ``` -------------------------------- ### Example CLI Response Source: https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/private-channels-get-info.html The expected JSON output containing the ARN, fingerprint, and tags for the requested playback key. ```json { "keyPair": { "arn": "arn:aws:ivs:us-west-2:991729659840:playback-key/3ff88c71-b18e-415f-948b-18bbde605a97", "fingerprint": "a2:b5:b3:0b:be:8e:73:00:0e:ad:e9:bb:02:c9:81:9a", "tags": {} } } ``` -------------------------------- ### Initialize Expo Project Source: https://docs.aws.amazon.com/ivs/latest/ChatUserGuide/chat-sdk-react-tutorial-chat-rooms.html Commands to scaffold a new React Native project using Expo. ```bash npx create-expo-app ``` ```bash npx create-expo-app -t expo-template-blank-typescript ``` -------------------------------- ### IVS Composition State Change: Destination Start Source: https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/eventbridge.html This event is sent when output to a Destination successfully started. ```APIDOC ## IVS Composition State Change: Destination Start ### Description This event is sent when output to a Destination successfully started. ### Event Details - **event_name**: "Destination Start" - **stage_arn** (string): The ARN of the stage. - **id** (string): The ID of the destination. ### Example Payload ```json { "version": "0", "id": "01234567-0123-0123-0123-012345678901", "detail-type": "IVS Composition State Change", "source": "aws.ivs", "account": "aws_account_id", "time": "2017-06-12T10:23:43Z", "region": "us-east-1", "resources": [ "arn:aws:ivs:us-east-1:aws_account_id:composition/123456789012" ], "detail": { "event_name": "Destination Start", "stage_arn": "", "id": "" } } ``` ``` -------------------------------- ### Initialize Camera Kit and Stage Management Source: https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/broadcast-3p-camera-filters-integrating-snap.html Sets up the Camera Kit session and configures event listeners for UI controls and stage interactions. ```javascript /*! Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ const { Stage, LocalStageStream, SubscribeType, StageEvents, ConnectionState, StreamType, } = IVSBroadcastClient; import { bootstrapCameraKit, createMediaStreamSource, Transform2D, } from '@snap/camera-kit'; let cameraButton = document.getElementById('camera-control'); let micButton = document.getElementById('mic-control'); let joinButton = document.getElementById('join-button'); let leaveButton = document.getElementById('leave-button'); let controls = document.getElementById('local-controls'); let videoDevicesList = document.getElementById('video-devices'); let audioDevicesList = document.getElementById('audio-devices'); let lensSelector = document.getElementById('lens-selector'); let session; let availableLenses = []; // Stage management let stage; let joining = false; let connected = false; let localCamera; let localMic; let cameraStageStream; let micStageStream; const liveRenderTarget = document.getElementById('canvas'); const init = async () => { await initializeDeviceSelect(); const cameraKit = await bootstrapCameraKit({ apiToken: 'INSERT_YOUR_API_TOKEN_HERE', }); session = await cameraKit.createSession({ liveRenderTarget }); const { lenses } = await cameraKit.lensRepository.loadLensGroups([ 'INSERT_YOUR_LENS_GROUP_ID_HERE', ]); availableLenses = lenses; populateLensSelector(lenses); const snapStream = liveRenderTarget.captureStream(); lensSelector.addEventListener('change', handleLensChange); lensSelector.disabled = true; cameraButton.addEventListener('click', () => { const isMuted = !cameraStageStream.isMuted; cameraStageStream.setMuted(isMuted); cameraButton.innerText = isMuted ? 'Show Camera' : 'Hide Camera'; }); micButton.addEventListener('click', () => { const isMuted = !micStageStream.isMuted; micStageStream.setMuted(isMuted); micButton.innerText = isMuted ? 'Unmute Mic' : 'Mute Mic'; }); joinButton.addEventListener('click', () => { joinStage(session, snapStream); }); leaveButton.addEventListener('click', () => { leaveStage(); }); }; async function setCameraKitSource(session, mediaStream) { const source = createMediaStreamSource(mediaStream); await session.setSource(source); source.setTransform(Transform2D.MirrorX); session.play(); } const populateLensSelector = (lenses) => { lensSelector.innerHTML = ''; lenses.forEach((lens, index) => { const option = document.createElement('option'); option.value = index; option.text = lens.name || `Lens ${index + 1}`; lensSelector.appendChild(option); }); }; const handleLensChange = (event) => { const selectedIndex = parseInt(event.target.value); if (session && availableLenses[selectedIndex]) { session.applyLens(availableLenses[selectedIndex]); } }; const joinStage = async (session, snapStream) => { if (connected || joining) { return; } joining = true; const token = document.getElementById('token').value; if (!token) { window.alert('Please enter a participant token'); joining = false; return; } // Retrieve the User Media currently set on the page localCamera = await getCamera(videoDevicesList.value); localMic = await getMic(audioDevicesList.value); await setCameraKitSource(session, localCamera); // Create StageStreams for Audio and Video cameraStageStream = new LocalStageStream(snapStream.getVideoTracks()[0]); micStageStream = new LocalStageStream(localMic.getAudioTracks()[0]); const strategy = { stageStreamsToPublish() { return [cameraStageStream, micStageStream]; }, shouldPublishParticipant() { return true; }, shouldSubscribeToParticipant() { return SubscribeType.AUDIO_VIDEO; }, }; stage = new Stage(token, strategy); // Other available events: // https://aws.github.io/amazon-ivs-web-broadcast/docs/sdk-guides/stages#events stage.on(StageEvents.STAGE_CONNECTION_STATE_CHANGED, (state) => { connected = state === ConnectionState.CONNECTED; if (connected) { joining = false; controls.classList.remove('hidden'); lensSelector.disabled = false; } else { controls.classList.add('hidden'); lensSelector.disabled = true; } }); stage.on(StageEvents.STAGE_PARTICIPANT_JOINED, (participant) => { console.log('Participant Joined:', participant); }); stage.on( StageEvents.STAGE_PARTICIPANT_STREAMS_ADDED, (participant, streams) => { console.log('Participant Media Added: ', participant, streams); let streamsToDisplay = streams; if (participant.isLocal) { // Ensure to exclude local audio streams, otherwise echo will occur streamsToDisplay = streams.filter( (stream) => stream.streamType === StreamType.VIDEO ); } ``` -------------------------------- ### playbackRate Source: https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/player-videojs.html Gets or sets the video playback rate. For live streams, gets return 1 and sets are ignored. ```APIDOC ## playbackRate ### Description Gets or sets the video-playback rate. 1.0 means normal speed; 0.5, half normal speed; 2.0, two times normal speed; and so on. Amazon IVS: On a live stream, a get returns 1, and a set is ignored. ### Method GET/POST ### Endpoint /playbackRate ### Parameters #### Query Parameters - **rate** (number) - Optional - The playback rate. Valid values: in the range [0.25, 2.0]. ### Return Value - **rate** (number) - The playback rate. ``` -------------------------------- ### Create a Stage with Individual Participant Recording via AWS CLI Source: https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/getting-started-create-stage.html Use these commands to initialize a stage with participant recording. The configuration requires a valid storage configuration ARN and specified media types. ```bash aws ivs-realtime create-stage --name "test-stage-participant-recording" --auto-participant-recording-configuration storageConfigurationArn=arn:aws:ivs:us-west-2:123456789012:storage-configuration/LKZ6QR7r55c2,mediaTypes=AUDIO_VIDEO ``` ```bash aws ivs-realtime create-stage --name "test-stage-participant-recording" --auto-participant-recording-configuration storageConfigurationArn=arn:aws:ivs:us-west-2:123456789012:storage-configuration/LKZ6QR7r55c2,mediaTypes=AUDIO_VIDEO,thumbnailConfiguration="{targetIntervalSeconds=10,storage=[SEQUENTIAL,LATEST],recordingMode=INTERVAL}" ``` ```bash aws ivs-realtime create-stage --name "test-stage-participant-recording" --auto-participant-recording-configuration "storageConfigurationArn=arn:aws:ivs:us-west-2:123456789012:storage-configuration/LKZ6QR7r55c2,mediaTypes=AUDIO_VIDEO,thumbnailConfiguration="{targetIntervalSeconds=10,storage=[SEQUENTIAL,LATEST],recordingMode=INTERVAL}",recordingReconnectWindowSeconds=60" ``` -------------------------------- ### Install MediaPipe and Webpack dependencies Source: https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/broadcast-3p-camera-filters-background-replacement.html Install the necessary npm packages for MediaPipe vision tasks and the Webpack bundler. ```bash npm i @mediapipe/tasks-vision webpack webpack-cli ``` ```bash npm i @mediapipe/tasks-vision webpack webpack-cli ``` -------------------------------- ### Initialize Camera and Stream Handling Source: https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/broadcast-3p-camera-filters-background-replacement.html Sets up event listeners for camera and microphone controls, captures the camera stream, and prepares for joining an IVS stage. Ensure device selection and stream initialization are handled prior to this. ```javascript const canvasElement = document.getElementById("canvas"); const background = document.getElementById("background"); const canvasCtx = canvasElement.getContext("2d"); const backgroundCtx = background.getContext("2d"); const video = document.getElementById("webcam"); import { ImageSegmenter, FilesetResolver } from "@mediapipe/tasks-vision"; ``` ```javascript const init = async () => { await initializeDeviceSelect(); cameraButton.addEventListener("click", () => { const isMuted = !cameraStageStream.isMuted; cameraStageStream.setMuted(isMuted); cameraButton.innerText = isMuted ? "Show Camera" : "Hide Camera"; }); micButton.addEventListener("click", () => { const isMuted = !micStageStream.isMuted; micStageStream.setMuted(isMuted); micButton.innerText = isMuted ? "Unmute Mic" : "Mute Mic"; }); localCamera = await getCamera(videoDevicesList.value); const segmentationStream = canvasElement.captureStream(); joinButton.addEventListener("click", () => { joinStage(segmentationStream); }); leaveButton.addEventListener("click", () => { leaveStage(); }); }; ``` -------------------------------- ### Get Microphone Stream Source: https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/broadcast-3p-camera-filters-integrating-snap.html Requests a media stream from a specific microphone. If no deviceId is provided, it attempts to get the default microphone. ```javascript async function getMic(deviceId) { return navigator.mediaDevices.getUserMedia({ video: false, audio: { deviceId: deviceId ? { exact: deviceId } : null, }, }); } ``` -------------------------------- ### Get Camera Stream Source: https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/broadcast-3p-camera-filters-integrating-snap.html Requests a media stream from a specific camera. If no deviceId is provided, it attempts to get the default camera. ```javascript async function getCamera(deviceId) { // Use Max Width and Height return navigator.mediaDevices.getUserMedia({ video: { deviceId: deviceId ? { exact: deviceId } : null, }, audio: false, }); } ``` -------------------------------- ### Example ARN for a Specific Channel Source: https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/security-iam.html An example of how to specify a particular Amazon IVS channel resource in an IAM policy statement. ```json "Resource": "arn:aws:ivs:us-west-2:123456789012:channel/VgNkEJgOVX9N" ``` -------------------------------- ### Implement preferredLayerForStream Strategy Source: https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/ios-publish-subscribe.html These examples demonstrate how to implement the preferredLayerForStream strategy method to control video quality selection for participants. ```swift func stage(_ stage: IVSStage, participant: IVSParticipantInfo, preferredLayerFor stream: IVSRemoteStageStream) -> IVSRemoteStageStreamLayer? { return stream.lowestQualityLayer } ``` ```swift func stage(_ stage: IVSStage, participant: IVSParticipantInfo, preferredLayerFor stream: IVSRemoteStageStream) -> IVSRemoteStageStreamLayer? { If appState.isAutoMode { return nil } else { return appState.layerChoice } } ``` -------------------------------- ### Initialize Local Participant Source: https://docs.aws.amazon.com/ivs/latest/RealTimeUserGuide/getting-started-pub-sub-android.html Sets up device discovery and creates a local participant for previewing camera and microphone stats upon initialization. ```kotlin init { deviceDiscovery = DeviceDiscovery(application) // Create a local participant immediately to render our camera preview and microphone stats val localParticipant = StageParticipant(true, null) participantAdapter.participantJoined(localParticipant) } ``` -------------------------------- ### Complete IVS Player Implementation Source: https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/web-getting-started.html A full example showing script inclusion, video element attachment, and playback initiation. ```html ``` -------------------------------- ### Initialize Express Server Source: https://docs.aws.amazon.com/ivs/latest/ChatUserGuide/chat-sdk-js-tutorial-chat-rooms.html Importing dependencies and configuring the Express application. ```javascript // index.js import express from 'express'; import AWS from 'aws-sdk'; import 'dotenv/config'; import cors from 'cors'; ``` ```javascript const app = express(); const port = 3000; app.use(express.json()); app.use(cors({ origin: ['http://127.0.0.1:5173'] })); ``` -------------------------------- ### RTMPS onCaptionInfo Payload Example Source: https://docs.aws.amazon.com/ivs/latest/userguide/streaming-config.html Example of the binary payload structure for transmitting closed captions via RTMPS using the onCaptionInfo tag. ```text 00000000 12 00 00 69 00 00 00 00 00 00 00 02 00 0d 6f 6e |...i..........on| 00000010 43 61 70 74 69 6f 6e 49 6e 66 6f 08 00 00 00 02 |CaptionInfo.....| 00000020 00 04 74 79 70 65 02 00 03 37 30 38 00 04 64 61 |..type...708..da| 00000030 74 61 02 00 3c 74 51 41 78 52 30 45 35 4e 41 4e |ta..