Just to make sure everything works as expected, here are my current Node/AWS CLI versions (in case we need to look up an ARN or something with the CLI)
$ node --version
v18.12.1
$ aws --version
aws-cli/2.9.12 Python/3.9.11 Darwin/21.6.0 exe/x86_64 prompt/off
To run the demos that we'll build, install http-server
.
npm install -g http-server
First, create an node project:
$ npm init
Next, install the IVS SDK:
$ npm install @aws-sdk/client-ivs
Reference doc.
create-channel.js
import { IvsClient, CreateChannelCommand } from "@aws-sdk/client-ivs";
const client = new IvsClient();
const input = {
'name': 'demo-1',
'latencyMode': 'LOW',
'type': 'BASIC',
};
const command = new CreateChannelCommand(input);
const response = await client.send(command);
console.log(response);
Run:
node create-channel.js
Expected output:
{
"$metadata": {
"httpStatusCode": 200,
"requestId": "[redacted]",
"cfId": "[redacted]",
"attempts": 1,
"totalRetryDelay": 0
},
"channel": {
"arn": "arn:aws:ivs:us-east-1:[redacted]:channel/9WeUUczacjIX",
"authorized": false,
"ingestEndpoint": "[redacted].global-contribute.live-video.net",
"latencyMode": "LOW",
"name": "demo-1",
"playbackUrl": "https://f99084460c35.us-east-1.playback.live-video.net/api/video/v1/us-east-1.[redacted].channel.[redacted].m3u8",
"recordingConfigurationArn": "",
"tags": {},
"type": "STANDARD"
},
"streamKey": {
"arn": "arn:aws:ivs:us-east-1:[redacted]:stream-key/[redacted]",
"channelArn": "arn:aws:ivs:us-east-1:[redacted]:channel/[redacted]",
"tags": {},
"value": "sk_us-east-[redacted]"
}
}
Reference docs.
Create web-broadcast.html
.
<!DOCTYPE html>
<html lang="en">
<head>
<title>IVS Web Broadcast SDK</title>
<script src="https://web-broadcast.live-video.net/1.2.0/amazon-ivs-web-broadcast.js"></script>
<script>
</script>
</head>
<body>
<div>
<p>
<input type="password" id="streamKey" placeholder="Stream Key" />
</p>
</div>
<div>
<canvas id="preview" style="width: 800px; height: 450px;"></canvas>
</div>
<div>
<p>
<button type="button" id="toggle-btn">Toggle Broadcast</button>
</p>
</div>
</body>
</html>
Add a DOMContentLoaded
listener:
document.addEventListener('DOMContentLoaded', async () => {
window.broadcasting = false;
// get permission to access mic/cam
await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
});
The rest of the commands below will be added to the DOMContentLoaded
handler.
Create an instance of the web broadcast client:
// create a broadcast client
const client = IVSBroadcastClient.create({
streamConfig: IVSBroadcastClient.BASIC_FULL_HD_LANDSCAPE,
ingestEndpoint: 'f99084460c35.global-contribute.live-video.net',
});
Add a preview:
// add a preview
const previewEl = document.getElementById('preview');
client.attachPreview(previewEl);
Get mics/cams and create streams:
// get mics/cams
// can also use this to populate a <select>
// to allow user to choose mic/cam
const devices = await navigator.mediaDevices.enumerateDevices();
window.videoDevices = devices.filter(d => d.kind === 'videoinput');
window.audioDevices = devices.filter(d => d.kind === 'audioinput');
// get a stream from the webcam
window.cameraStream = await navigator.mediaDevices.getUserMedia({
video: {
deviceId: { exact: window.videoDevices[0].deviceId },
width: { ideal: 1920, max: 1920 },
height: { ideal: 1080, max: 1080 },
},
});
// get a stream from the mic
window.microphoneStream = await navigator.mediaDevices.getUserMedia({
audio: { deviceId: window.audioDevices[0].deviceId },
});
Add streams to client:
// add the streams to the client
client.addVideoInputDevice(window.cameraStream, 'camera1', { index: 0 });
client.addAudioInputDevice(window.microphoneStream, 'mic1');
Add button listener to toggle broadcast:
document.getElementById('toggle-btn').addEventListener('click', (evt) => {
if (!window.broadcasting) {
const streamKey = document.getElementById('streamKey').value;
client
.startBroadcast(streamKey)
.then((result) => {
console.log('Broadcast started!');
window.broadcasting = true;
})
.catch((error) => {
console.error('Broadcast failed!', error);
window.broadcasting = false;
});
}
else {
client.stopBroadcast();
console.log('Broadcast ended!');
window.broadcasting = false;
}
});
Reference User Guide & API Docs.
<!DOCTYPE html>
<html lang="en">
<head>
<title>IVS Playback</title>
<script src="https://player.live-video.net/1.14.0/amazon-ivs-player.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
// set stream url
const streamUrl = '[Playback URL]';
// init and play
const ivsPlayer = IVSPlayer.create();
ivsPlayer.attachHTMLVideoElement(document.getElementById('video-player'));
ivsPlayer.load(streamUrl);
ivsPlayer.play();
});
</script>
</head>
<body>
<video id="video-player" style="height: 450px; width: 800px;" controls autoplay muted></video>
</body>
</html>
Add listeners for player events:
// listen for playing
ivsPlayer.addEventListener(IVSPlayer.PlayerState.PLAYING, () => {
console.log('playing');
});
// listen for stopped
ivsPlayer.addEventListener(IVSPlayer.PlayerState.ENDED, () => {
console.log('stopped');
});
// listen for metadata
ivsPlayer.addEventListener(IVSPlayer.PlayerEventType.TEXT_METADATA_CUE, (evt) => {
console.log(evt);
});
// get quality, latency, buffer
setInterval(() => {
console.log('Quality', ivsPlayer.getQuality());
console.log(`Bitrate: ${ivsPlayer.getQuality().bitrate / 1000} kbps`);
console.log(`Live Latency: ${ivsPlayer.getLiveLatency()} seconds`);
console.log(`Buffer: ${ivsPlayer.getBufferDuration()} seconds`);
}, 1500);