Как транслировать прямую трансляцию на Amazon IVS из браузера
16 ноября 2022 г.Добро пожаловать в эту серию статей, в которой мы узнаем, как начать прямую трансляцию в облаке с помощью Amazon Interactive Video Service (Amazon IVS). Если вы впервые присоединяетесь к нам, я призываю вас наверстать упущенное, прочитав остальные сообщения в этой серии!
Ранее в этой серии мы рассмотрели, как транслировать наши прямая трансляция из стороннего программного обеспечения для настольных ПК.
В сегодняшней публикации мы собираемся переключиться и рассмотреть другой вариант — трансляцию нашей прямой трансляции прямо из браузера!
Почему?
Хороший вопрос! Существует множество вариантов рабочего стола для прямой трансляции, и многие из них предлагают такие функции, как настраиваемые сцены, фоны, анимированные переходы и многое другое. Но иногда бизнес-правила наших приложений не требуют всех этих функций. Иногда вам просто нужно транслировать в прямом эфире камеру и микрофон — и, возможно, поделиться своим рабочим столом со своими зрителями.
Для настольных потоковых решений требуется установка и знание стороннего программного обеспечения. Это не всегда желательно (или даже вариант). По этим причинам (среди прочих) SDK веб-вещания Amazon IVS дает нам возможность выполнять потоковую передачу на наш канал непосредственно из веб-браузеров.
:::информация Трансляция из браузера не означает, что вы не можете иметь причудливые фоны, наложения, анимацию и переходы, доступные во многих предложениях для настольных компьютеров. С современными HTML и JavaScript можно сделать массу вещей, и мы рассмотрим некоторые из них в следующем посте. Сегодня мы сосредоточимся на потоковой передаче с основной камеры и микрофона.
:::
Сбор информации о нашей трансляции
Как и во многих предыдущих сообщениях этой серии, мы собираемся создать демонстрацию с помощью CodePen.
Чтобы использовать SDK веб-вещания, нам потребуется немного информации.
Использование консоли управления Amazon IVS
Один из способов получить эти биты — войти в консоль управления Amazon IVS (https://console.aws.amazon. com/ivs) и выбираем канал, с которым работаем. В сведениях о канале прокрутите вниз до раздела Конфигурация потока и скопируйте Конечную точку загрузки и Ключ потока.
Использование интерфейса командной строки AWS
Если вы предпочитаете получать конечную точку загрузки и ключ потоковой передачи через интерфейс командной строки, вы можете сделать это с помощью нескольких отдельных вызовов. Во-первых, нам понадобится канал ARN. Мы можем получить это через вызов list-channels
(docs) и используя канал Name в качестве фильтра. В этом примере demo-channel
— это мой канал Name.
$ CHANNEL_ARN=$(aws ivs list-channels --filter-by-name "demo-channel" --query "channels[0].arn" --output text)
Теперь мы можем получить конечную точку Ingest с помощью вызова get-channel
(документы).
$ aws ivs get-channel --arn=$CHANNEL_ARN --query "channel.ingestEndpoint" --output text
Чтобы получить ключ потока, нам сначала нужно получить его ARN. Мы можем получить это через list-stream-keys
(документы).
$ STREAM_KEY_ARN=$(aws ivs list-stream-keys --channel-arn=$CHANNEL_ARN --query "streamKeys[0].arn" --output text)
Наконец, мы получаем значение ключа потока с помощью get-stream-key
(документы).
$ aws ivs get-stream-key --arn=$STREAM_KEY_ARN --query "streamKey.value" --output text
Использование AWS SDK
Если вы хотите использовать SDK для получения конечной точки загрузки и ключа потоковой передачи, см. Документация SDK для вашего любимого языка. Вот пример того, как это можно сделать с помощью Node.JS SDK:
import {
IvsClient,
GetChannelCommand,
GetStreamKeyCommand,
ListChannelsCommand,
ListStreamKeysCommand
} from "@aws-sdk/client-ivs";
const client = new IvsClient();
const channelName = 'demo-channel';
// list channels, filtering by name, to get the ARN
const listChannelsRequest = new ListChannelsCommand({ filterByName: channelName });
const listChannelsResponse = await client.send(listChannelsRequest);
if (!listChannelsResponse.channels.length) {
console.warn(`No channels matching '${channelName}' were found!`);
const process = await import('node:process')
process.exit(1);
}
const channelArn = listChannelsResponse.channels[0].arn;
console.log(`Channel ARN: ${channelArn}`);
// get the channel (by ARN) to get ingestEndpoint
const getChannelRequest = new GetChannelCommand({ arn: channelArn });
const getChannelResponse = await client.send(getChannelRequest);
const ingestEndpoint = getChannelResponse.channel.ingestEndpoint;
console.log(`Ingest Endpoint: ${ingestEndpoint}`);
// list stream keys to get the stream key ARN
const listStreamKeysRequest = new ListStreamKeysCommand({ channelArn: channelArn });
const listStreamKeysResponse = await client.send(listStreamKeysRequest);
const streamKeyArn = listStreamKeysResponse.streamKeys[0].arn;
// get stream key
const getStreamKeyRequest = new GetStreamKeyCommand({ arn: streamKeyArn });
const getStreamKeyResponse = await client.send(getStreamKeyRequest);
const streamKey = getStreamKeyResponse.streamKey.value;
console.log(`Stream Key: ${streamKey}`);
Запуск приведенного выше кода с допустимым channelName
приведет к выводу, подобному следующему.
Channel ARN: arn:aws:ivs:us-east-1:<redacted>:channel/<redacted>
Ingest Endpoint: <redacted>.global-contribute.live-video.net
Stream Key: sk_us-east-1_<redacted>
Создание демонстрации веб-трансляции
Для начала нам нужно включить SDK веб-вещания на нашу страницу.
<script src="https://web-broadcast.live-video.net/1.1.0/amazon-ivs-web-broadcast.js"></script>
Прежде чем мы рассмотрим использование SDK веб-вещания, давайте добавим на страницу HTML-разметку. Мы начнем с элемента <canvas>
, который мы можем использовать для предварительного просмотра того, что будет транслироваться нашим зрителям.
Мы добавим два элемента <select>
, чтобы позволить вещательной компании выбрать камеру и микрофон, используемые для захвата аудио и видео. Поскольку эта демонстрация выполняется в CodePen, мы также добавим несколько текстовых входных данных для захвата конечной точки загрузки и ключа потоковой передачи, необходимых для настройки широковещательного клиента.
Нам понадобится кнопка для запуска трансляции, поэтому мы добавим ее под текстовые поля. Чтобы управлять макетом и стилем, я включил Bootstrap в CodePen и применил некоторые соответствующие классы к макету и входным данным.
<div class="row">
<div class="col-sm-6 offset-sm-3">
<span class="badge bg-info fs-3 d-none mb-3 w-100" id="online-indicator">Online</span>
<canvas id="broadcast-preview" class="rounded-4 shadow w-100"></canvas>
</div>
</div>
<div class="d-flex flex-column col-sm-6 offset-sm-3 p-1">
<select name="cam-select" id="cam-select" class="form-select w-100 mb-3"></select>
<select name="mic-select" id="mic-select" class="form-select w-100 mb-3"></select>
<input type="text" name="endpoint" id="endpoint" class="form-control w-100 mb-3" placeholder="Ingest Endpoint" />
<input type="password" name="stream-key" id="stream-key" class="form-control w-100 mb-3" placeholder="Stream Key" />
<button class="btn btn-primary w-100 shadow" id="stream-btn">Stream</button>
</div>
Если мы запустим демонстрацию, мы сможем увидеть макет демонстрации. Очевидно, что в предварительном просмотре холста или выбранных элементах ничего не будет, потому что мы еще не заполнили их.
Подключение предпросмотра трансляции, камеры и микрофона
Давайте добавим в демонстрацию немного JavaScript, чтобы мы могли заполнить раскрывающиеся списки камеры и микрофона и предварительно просмотреть камеру вещателя. Добавьте функцию init()
и обработчик для вызова этой функции, когда DOM будет готов.
const init = async () => {
};
document.addEventListener('DOMContentLoaded', init);
В целях безопасности браузеры не позволят нам получить доступ к камере и микрофону пользователя, пока мы не запросим (и не получим) разрешение.
Давайте добавим функцию handlePermissions()
, чтобы позаботиться об этом.
const handlePermissions = async () => {
let permissions = { video: true, audio: true };
try {
await navigator.mediaDevices.getUserMedia(permissions);
}
catch (err) {
console.error(err.message);
permissions = { video: false, audio: false };
}
if (!permissions.video) console.error('Failed to get video permissions.');
if (!permissions.audio) console.error('Failed to get audio permissions.');
};
Функция handlePermissions()
использует navigator.mediaDevices.getUserMedia()
для получения разрешений видео
и аудио
через Объект разрешения
. Мы назовем эту функцию самым первым действием внутри нашей функции init()
.
const init = async () => {
await handlePermissions();
};
Затем мы получим список видео- и аудиоустройств (камера и микрофон) с помощью navigator.mediaDevices.enumerateDevices()
и заполним элементы <select>
. Мы установим первое найденное устройство как «выбранное» по умолчанию.
const getDevices = async () => {
const cameraSelect = document.getElementById('cam-select');
const micSelect = document.getElementById('mic-select');
const devices = await navigator.mediaDevices.enumerateDevices();
const videoDevices = devices.filter((d) => d.kind === 'videoinput');
const audioDevices = devices.filter((d) => d.kind === 'audioinput');
videoDevices.forEach((device, idx) => {
const opt = document.createElement('option');
opt.value = device.deviceId;
opt.innerHTML = device.label;
if (idx === 0) {
window.selectedVideoDeviceId = device.deviceId;
opt.selected = true;
}
cameraSelect.appendChild(opt);
});
audioDevices.forEach((device, idx) => {
const opt = document.createElement('option');
opt.value = device.deviceId;
opt.innerHTML = device.label;
if (idx === 0) {
window.selectedAudioDeviceId = device.deviceId;
opt.selected = true;
}
micSelect.appendChild(opt);
});
};
И обновите нашу функцию init()
, чтобы она вызывала getDevices()
.
const init = async () => {
await handlePermissions();
await getDevices();
};
Создание широковещательного клиента
Теперь, когда у нас есть разрешения и заполнены доступные устройства, мы можем создать экземпляр широковещательного клиента.
const init = async () => {
await handlePermissions();
await getDevices();
window.broadcastClient = IVSBroadcastClient.create({
streamConfig: IVSBroadcastClient.STANDARD_LANDSCAPE,
});
};
В зависимости от типа канала, на который вы транслируете, вам может потребоваться обновить значение streamConfig
до одного из доступных пресетов:
IVSBroadcastClient.BASIC_LANDSCAPE;
IVSBroadcastClient.STANDARD_LANDSCAPE;
IVSBroadcastClient.BASIC_PORTRAIT;
IVSBroadcastClient.STANDARD_PORTRAIT;
Создание видео- и аудиопотоков
Теперь, когда у нас есть широковещательный клиент, мы можем добавить наши устройства ввода видео и аудио к клиенту с помощью addVideoInputDevice()
и addAudioInputDevice()
соответственно. Мы будем повторно использовать эти функции, чтобы позволить вещателям переключать камеру и микрофон во время трансляции, если они этого хотят, поэтому мы добавим некоторую логику, чтобы сначала удалить все существующие устройства, прежде чем добавлять устройство.
const createVideoStream = async () => {
if (window.broadcastClient && window.broadcastClient.getVideoInputDevice('camera1')) window.broadcastClient.removeVideoInputDevice('camera1');
const streamConfig = IVSBroadcastClient.STANDARD_LANDSCAPE;
window.videoStream = await navigator.mediaDevices.getUserMedia({
video: {
deviceId: { exact: window.selectedVideoDeviceId },
width: {
ideal: streamConfig.maxResolution.width,
max: streamConfig.maxResolution.width,
},
height: {
ideal: streamConfig.maxResolution.height,
max: streamConfig.maxResolution.height,
},
},
});
if (window.broadcastClient) window.broadcastClient.addVideoInputDevice(window.videoStream, 'camera1', { index: 0 });
};
Функция captureAudioStream()
аналогична функции captureVideoStream()
:
const createAudioStream = async () => {
if (window.broadcastClient && window.broadcastClient.getAudioInputDevice('mic1')) window.broadcastClient.removeAudioInputDevice('mic1');
window.audioStream = await navigator.mediaDevices.getUserMedia({
audio: {
deviceId: window.selectedAudioDeviceId
},
});
if (window.broadcastClient) window.broadcastClient.addAudioInputDevice(window.audioStream, 'mic1');
};
Давайте изменим функцию init()
, чтобы она вызывала их.
const init = async () => {
await handlePermissions();
await getDevices();
window.broadcastClient = IVSBroadcastClient.create({
streamConfig: IVSBroadcastClient.STANDARD_LANDSCAPE,
});
await createVideoStream();
await createAudioStream();
};
Далее мы добавим две функции для обновления выбранного deviceId
при изменении значения <select>
. Позже мы добавим для них прослушиватели событий, а пока просто добавим функции.
const selectCamera = async (e) => {
window.selectedVideoDeviceId = e.target.value;
await createVideoStream();
};
const selectMic = async (e) => {
window.selectedAudioDeviceId = e.target.value;
await createAudioStream();
};
Предварительный просмотр видеопотока
Теперь, когда мы добавили наше устройство ввода видео в поток, мы можем предварительный просмотр в элементе <canvas>
с помощью функции previewVideo()
.
const previewVideo = () => {
const previewEl = document.getElementById('broadcast-preview');
window.broadcastClient.attachPreview(previewEl);
};
И добавьте вызов previewVideo()
в init()
.
const init = async () => {
await handlePermissions();
await getDevices();
window.broadcastClient = IVSBroadcastClient.create({
streamConfig: IVSBroadcastClient.STANDARD_LANDSCAPE,
});
await createVideoStream();
await createAudioStream();
previewVideo();
};
Подготовка к трансляции
Мы почти готовы к трансляции на наш канал. Давайте добавим функцию toggleBroadcast()
для обработки кликов по кнопке "Поток".
const toggleBroadcast = () => {
if(!window.isBroadcasting) {
startBroadcast();
}
else {
stopBroadcast();
}
};
Здесь мы проверяем, транслируется ли поток в данный момент, и вызываем startBroadcast()
или stopBroadcast()
.
Функция startBroadcast()
проверит конечную точку загрузки и ключ потока, обновит пользовательский интерфейс, а затем вызовет startBroadcast() в
broadcastClient
на начать трансляцию.
const startBroadcast = () => {
const key = document.getElementById('stream-key').value;
const endpoint = document.getElementById('endpoint').value;
const streamBtn = document.getElementById('stream-btn');
const onlineIndicator = document.getElementById('online-indicator');
if(!key && !endpoint) {
alert('Please enter a Stream Key and Ingest Endpoint!');
}
else {
window.broadcastClient
.startBroadcast(key, endpoint)
.then(() => {
streamBtn.innerHTML = 'Stop';
onlineIndicator.classList.remove('d-none');
window.isBroadcasting = true;
})
.catch((error) => {
streamBtn.innerHTML = 'Stream';
onlineIndicator.classList.add('d-none');
window.isBroadcasting = false;
console.error(error);
});
}
};
Функция stopBroadcast()
, как вы могли догадаться, вызовет stopBroadcast()
в broadcastClient
и обновит пользовательский интерфейс.
const stopBroadcast = () => {
window.broadcastClient.stopBroadcast();
window.isBroadcasting = false;
document.getElementById('online-indicator').classList.add('d-none');
}
Наконец, мы закончим функцию init()
, добавив прослушиватели событий для обновления устройств камеры и микрофона и вызовем toggleBroadcast()
, когда пользователь нажимает кнопку «Поток». кнопка.
const init = async () => {
await handlePermissions();
await getDevices();
window.broadcastClient = IVSBroadcastClient.create({
streamConfig: IVSBroadcastClient.STANDARD_LANDSCAPE,
});
await createVideoStream();
await createAudioStream();
previewVideo();
document.getElementById('cam-select').addEventListener('change', selectCamera);
document.getElementById('mic-select').addEventListener('change', selectMic);
document.getElementById('stream-btn').addEventListener('click', toggleBroadcast);
};
Трансляция на канал Amazon IVS из Интернета
Мы готовы к трансляции! Для начала откройте демо в отдельной вкладке браузера.
:::информация
Внимание! Поскольку CodePen выполняет встраивание в <iframe>
, мы не можем встроить эту демонстрацию непосредственно в этот пост блога из-за изолированной природы <iframe>
на HackerNoon. просмотрите CodePen непосредственно в отдельной вкладке браузера.
:::
Подключите конечную точку загрузки и ключ потока и нажмите "Поток", чтобы попробовать. Вы можете убедиться, что ваша трансляция транслируется с помощью функции «Предварительный просмотр в реальном времени» в консоли управления Amazon IVS после обновления пользовательского интерфейса для подтверждения. что ваша трансляция онлайн.
:::подсказка Примечание. Если трансляция вашего потока не начинается, убедитесь, что конечная точка загрузки и ключ потока введены точно так, как показано в консоли управления Amazon IVS. Если у вас по-прежнему возникают проблемы, проверьте, не блокирует ли VPN-подключение требуемый порт. Если это так, повторите демонстрацию, отключившись от VPN.
:::
Обзор
В этом посте мы узнали, как транслировать на наш канал Amazon IVS с помощью SDK Amazon IVS Web Broadcast SDK. Дополнительные сведения см. в документах SDK.
Также опубликовано здесь .
Оригинал