[Работа с видео, JavaScript, Программирование, Видеоконференцсвязь] Streaming multiple RTSP IP cameras on YouTube and/or Facebook
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
As you know, YouTube doesn't have a feature for capturing an RTSP stream. Perhaps this isn't done by a chance, but on the basis of the true pragmatics. This way, people don't stream static video surveillance of their doorways on YouTube and don't ruin its channels, which, as it turned out in the pandemic, are not limitless at all. Just a reminder: there were some cases when the quality of streaming was deteriorated and restricted to 240p. By the way, there is another assumption: streams from IP cameras are the true evil for YouTube because they have a little more than zero viewers, so they can't give the platform a million ad views. Anyway, the feature doesn't exist but we would like to change this and help YouTube to make their viewers happy.
Let's say we want to take an ordinary street IP camera that sends an H.264 stream over RTSP and redirect it to YouTube. To do this, we will need to take the RTSP stream and convert it to the RTMPS stream that YouTube accepts. Why RTMPS, not RTMP? As you know, non-security protocols are dying out. HTTP is brutally persecuted, and its fate has befallen other protocols that don't have the S letter in the end - which means Secure. Facebook refused RTMP stream but fortunately left RTMPS alone. So, to convert RTSP to RTMPS, we do this in a headless way (without using the UI), i.e. on the server.
For one RTSP stream we need one YouTube account that will accept the stream but what should we do if we have not one but a lot of cameras? Of course we can manually create several YouTube accounts, for example, to cover the infield with video surveillance. However, this is very likely to violate the Terms of Service. And what if there are 50 cameras overall, not 10? Should we create 50 accounts? And what's next? How can it be watched? In this case, the mixer can save the occasion and consolidate the cameras into one stream. Let's see how it works with 2 RTPS cameras. The resulting stream is mixer1 = rtsp1 + rtsp2. We send the mixer1 stream to YouTube. Everything works - both cameras are in the same stream. It's worth noting here that mixing is a quite intensive operation using CPU.
At the same time, since we already have an RTSP stream on the server side, we can redirect this stream to other RTMP endpoints without incurring additional CPU and memory costs. We simply withdraw traffic from the RTSP stream and replicate it on Facebook, Twitch, anywhere we want without additional RTSP capture and de-packetizing.
As a DevOps I would feel guilty if I don't script what I could script. Automation is facilitated by the presence of a REST API for controlling video capture from the camera and retransmission.For example, by using a query:
/rtsp/startup
you can capture a video stream from an IP camera.A query:
/rtsp/find_all
allows you to get a list of streams captured by the RTSP server. A query to end the RTSP session is as follows:
/rtsp/terminate
You can control capture and relay of video streams either by using a simple browser and any convenient REST client, or by using the minimum number of code lines to embed the server management functionality in your web project. Let's take a closer look at how this can be done.A small manual on how to organize a live broadcast on YouTube and Facebook using a minimum codeFor the server side, we use demo.flashphoner.com. To quickly deploy your WCS server, use this instruction or run one of the virtual instances on Amazon, DigitalOcean or in Docker.It is assumed that you have a verified YouTube account and you have already created a broadcast in YouTube Studio, as well as a live video broadcast in your Facebook account.For live broadcasts to work on YouTube and Facebook, you need to specify the following lines in the WCS settings file flashphoner.properties: rtmp_transponder_stream_name_prefix= – Removes all prefixes for the relayed stream. rtmp_transponder_full_url=true – With "true", ignores "streamName" and uses the RTMP address to relay the stream in the form in which the user specified it. rtmp_flash_ver_subscriber=LNX 76.219.189.0 - to negotiate RTMP client versions between WCS and YouTube.
Now that all the preparatory steps have been completed, let's move on to programming. Place the minimum necessary elements in the HTML file:Connect the scripts of the main API and JS for the live broadcast, which we will create a little later:
<script type="text/javascript" src="../../../../flashphoner.js"></script>
<script type="text/javascript" src="rtsp-to-rtmp-min.js"></script>
Initialize API to load the web page:
<body onload="init_page()">
Add the necessary elements and buttons - fields for entering unique stream codes for YouTube and Facebook, a button for publishing the RTSP stream, a div element for displaying the current status of the program, and a button for stopping the publication:
<input id="streamKeyYT" type="text" placeholder="YouTube Stream key"/>
<input id="streamKeyFB" type="text" placeholder="FaceBook Stream key"/>
<button id="repubBtn">Start republish</button>
<div id="republishStatus"></div>
<br>
<button id="stopBtn">Stop republish</button>
Then move on to creating JS for RTSP republication. The script is a mini REST client.Create constants: Constant "url" to write an address for queries REST API . Replace "demo.flashphoner.com" with your WCS address.Constant "rtspStream" — specify the RTSP address of the stream from the IP camera. As an example, we use an RTSP stream from a virtual camera.
var url = "https://demo.flashphoner.com:8444/rest-api";
var rtspStream = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov"
The function "init_page()" initializes the main API when a web page is loaded. Also in this function, we assign the buttons to the called functions and call the "getStream" function, which captures the RTSP video stream from the IP camera:
function init_page() {
Flashphoner.init({});
repubBtn.onclick = streamToYouTube;
stopBtn.onclick = stopStream;
getStream();
}
The function "getStream()" sends to WCS REST a query "/rtsp/startup" to capture the RTSP video stream whose address was written to the constant "rtspStream"
function getStream() {
fetchUrl = url + "/rtsp/startup";
const options = {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"uri": rtspStream
}),
}
fetch(fetchUrl, options);
console.log("Stream Captured");
}
The function "streamToYouTube()" republishes the captured video stream to the live broadcast on YouTube:
function streamToYouTube() {
fetchUrl = url + "/push/startup";
const options = {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"streamName": rtspStream,
"rtmpUrl": "rtmp://a.rtmp.youtube.com/live2/"+document.getElementById("streamKeyYT").value
}),
}
fetch(fetchUrl, options);
streamToFB()
}
This function sends to WCS REST a call "/push/startup" with the following values in the parameters: "streamName" - name of the stream captured from the IP camera. The stream name corresponds to its RTSP address written to the constant "rtspStream""rtmpUrl" - server URL + unique stream code. This data is given when creating a live broadcast in YouTube Studio. In our example, we rigidly fixed the URL in the code, you can add another field for it to your web page. The unique stream code is indicated in the field "streamKeyYT" on our web page. The function "streamToFB" republishes the captured video stream to the live broadcast on Facebook:
function streamToFB() {
fetchUrl = url + "/push/startup";
const options = {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"streamName": rtspStream,
"rtmpUrl": "rtmps://live-api-s.facebook.com:443/rtmp/"+document.getElementById("streamKeyFB").value
}),
}
fetch(fetchUrl, options);
document.getElementById("republishStatus").textContent = "Stream republished";
}
This function also sends to WCS REST a call "/push/startup" with the following values in the parameters: "streamName" - name of the stream captured from the IP camera. The stream name corresponds to its RTSP address written to the constant "rtspStream""rtmpUrl" - server URL + unique stream code. This data can be found on the Facebook Live Stream page in the Live API section. The server URL in this function is specified in the code, as well as for the publishing function on YouTube. For this time, take a unique stream code from the field "streamKeyFB" on the web page. The function "stopStream()" sends to RTSP a query "/rtsp/terminate" which stops capturing the stream from the IP camera to WCS and accordingly stops publishing on YouTube and Facebook:
function stopStream() {
fetchUrl = url + "/rtsp/terminate";
const options = {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"uri": document.getElementById("rtspLink").value
}),
}
fetch(fetchUrl, options);
document.getElementById("captureStatus").textContent = null;
document.getElementById("republishStatus").textContent = null;
document.getElementById("stopStatus").textContent = "Stream stopped";
}
Full HTML and JS file codes will be discussed below.So. Save the files and try to run. Procedure for testingCreate a live stream in YouTube Studio. Copy the unique video stream code:
Open the previously created HTML page. In the first field, enter the unique video stream code copied to YouTube:
Create a live stream in your account on Facebook. Copy the unique video stream code.
Go back to our web page, paste the copied code into the second field and click "Start republish
Now check our republication. Again, go to YouTube Studio and Facebook, wait a few seconds and get a stream preview.
To stop republication, click "Stop"
Now, as we promised, full source codes of the example: Listing of the HTML file "rtsp-to-rtmp-min.html"
<!DOCTYPE html>
<html lang="en">
<head>
<script type="text/javascript" src="../../../../flashphoner.js"></script>
<script type="text/javascript" src="rtsp-to-rtmp-min.js"></script>
</head>
<body onload="init_page()">
<input id="streamKeyYT" type="text" placeholder="YouTube Stream key" /> <input id="streamKeyFB" type="text" placeholder="Facebook Stream key" /> <button id="repubBtn">Start republish</button>
<div id="republishStatus"></div>
<br />
<button id="stopBtn">Stop republish</button>
</body>
</html>
Listing of the JS file "rtsp-to-rtmp-min.js":
var url = "https://demo.flashphoner.com:8444/rest-api";
var rtspStream = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov"
function init_page() {
Flashphoner.init({});
repubBtn.onclick = streamToYouTube;
stopBtn.onclick = stopStream;
getStream();
}
function getStream() {
fetchUrl = url + "/rtsp/startup";
const options = {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"uri": rtspStream
}),
}
fetch(fetchUrl, options);
console.log("Stream Captured");
}
function streamToYouTube() {
fetchUrl = url + "/push/startup";
const options = {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"streamName": rtspStream,
"rtmpUrl": "rtmp://a.rtmp.youtube.com/live2/" + document.getElementById("streamKeyYT").value
}),
}
fetch(fetchUrl, options);
streamToFB()
}
function streamToFB() {
fetchUrl = url + "/push/startup";
const options = {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"streamName": rtspStream,
"rtmpUrl": "rtmps://live-api-s.facebook.com:443/rtmp/" + document.getElementById("streamKeyFB").value
}),
}
fetch(fetchUrl, options);
document.getElementById("republishStatus").textContent = "Stream republished";
}
function stopStream() {
fetchUrl = url + "/rtsp/terminate";
const options = {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
"uri": rtspStream
}),
}
fetch(fetchUrl, options);
document.getElementById("republishStatus").textContent = "Stream stopped";
}
Just a little code is required for the minimum implementation. Of course, for the final implementation of features, some adjustments are still needed – adding styles to a web page and various checks for data validity to the JS code. But it really works. Have a great streaming!LinksDemoWCS on Amazon EC2WCS on DigitalOceanWCS in DockerWebRTC video stream broadcast with conversion to RTMP --- Server functions for converting WebRTC audio video stream to RTMPStreaming from an RTMP Live Encoder --- Server functions for converting video streams from Live Encoder to RTMPHTML5-RTSP player for IP cams --- Server functions for playing RTSP video streams
===========
Источник:
habr.com
===========
Похожие новости:
- [JavaScript, Программирование, Карьера в IT-индустрии] Публичное техническое собеседование на мидл фронтенд-разработчика: 15 июня в 19.00
- [Разработка веб-сайтов, Работа с видео, Программирование, Видеоконференцсвязь] Стриминг множества RTSP IP камер на YouTube и/или Facebook
- [Программирование, DevOps] Утилиты для обработки JSON (перевод)
- [Программирование, Java] Java 15 и IntelliJ IDEA (перевод)
- [Программирование, Геоинформационные сервисы, Математика, Визуализация данных, Научно-популярное] Построение достоверных геологических моделей
- [Open source, Программирование, API, Apache, Natural Language Processing] Как добавить Natural Language Processing в Minecraft
- [Беспроводные технологии, Программирование микроконтроллеров, Умный дом, Интернет вещей, DIY или Сделай сам] Hello NXP JN5169 Zigbee World: правильное подключение и переподключение устройств
- [Настройка Linux, Программирование микроконтроллеров] Собираем и устанавливаем свою Linux-систему на микроконтроллер STM32MP1
- [Программирование, Анализ и проектирование систем, Проектирование и рефакторинг, IT-стандарты] Хватит организовывать код по типу файлов (перевод)
- [Программирование, Совершенный код, Проектирование и рефакторинг] Актуальность принципов SOLID (перевод)
Теги для поиска: #_rabota_s_video (Работа с видео), #_javascript, #_programmirovanie (Программирование), #_videokonferentssvjaz (Видеоконференцсвязь), #_webrtc, #_wcs, #_facebook, #_javascript, #_rest_api, #_rtsp, #_rtmp, #_rtmps, #_ip_camera, #_youtube, #_blog_kompanii_flashphoner (
Блог компании Flashphoner
), #_rabota_s_video (
Работа с видео
), #_javascript, #_programmirovanie (
Программирование
), #_videokonferentssvjaz (
Видеоконференцсвязь
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 14:21
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
As you know, YouTube doesn't have a feature for capturing an RTSP stream. Perhaps this isn't done by a chance, but on the basis of the true pragmatics. This way, people don't stream static video surveillance of their doorways on YouTube and don't ruin its channels, which, as it turned out in the pandemic, are not limitless at all. Just a reminder: there were some cases when the quality of streaming was deteriorated and restricted to 240p. By the way, there is another assumption: streams from IP cameras are the true evil for YouTube because they have a little more than zero viewers, so they can't give the platform a million ad views. Anyway, the feature doesn't exist but we would like to change this and help YouTube to make their viewers happy. Let's say we want to take an ordinary street IP camera that sends an H.264 stream over RTSP and redirect it to YouTube. To do this, we will need to take the RTSP stream and convert it to the RTMPS stream that YouTube accepts. Why RTMPS, not RTMP? As you know, non-security protocols are dying out. HTTP is brutally persecuted, and its fate has befallen other protocols that don't have the S letter in the end - which means Secure. Facebook refused RTMP stream but fortunately left RTMPS alone. So, to convert RTSP to RTMPS, we do this in a headless way (without using the UI), i.e. on the server. For one RTSP stream we need one YouTube account that will accept the stream but what should we do if we have not one but a lot of cameras? Of course we can manually create several YouTube accounts, for example, to cover the infield with video surveillance. However, this is very likely to violate the Terms of Service. And what if there are 50 cameras overall, not 10? Should we create 50 accounts? And what's next? How can it be watched? In this case, the mixer can save the occasion and consolidate the cameras into one stream. Let's see how it works with 2 RTPS cameras. The resulting stream is mixer1 = rtsp1 + rtsp2. We send the mixer1 stream to YouTube. Everything works - both cameras are in the same stream. It's worth noting here that mixing is a quite intensive operation using CPU. At the same time, since we already have an RTSP stream on the server side, we can redirect this stream to other RTMP endpoints without incurring additional CPU and memory costs. We simply withdraw traffic from the RTSP stream and replicate it on Facebook, Twitch, anywhere we want without additional RTSP capture and de-packetizing. As a DevOps I would feel guilty if I don't script what I could script. Automation is facilitated by the presence of a REST API for controlling video capture from the camera and retransmission.For example, by using a query: /rtsp/startup
/rtsp/find_all
/rtsp/terminate
Now that all the preparatory steps have been completed, let's move on to programming. Place the minimum necessary elements in the HTML file:Connect the scripts of the main API and JS for the live broadcast, which we will create a little later: <script type="text/javascript" src="../../../../flashphoner.js"></script>
<script type="text/javascript" src="rtsp-to-rtmp-min.js"></script> <body onload="init_page()">
<input id="streamKeyYT" type="text" placeholder="YouTube Stream key"/>
<input id="streamKeyFB" type="text" placeholder="FaceBook Stream key"/> <button id="repubBtn">Start republish</button> <div id="republishStatus"></div> <br> <button id="stopBtn">Stop republish</button> var url = "https://demo.flashphoner.com:8444/rest-api";
var rtspStream = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov" function init_page() {
Flashphoner.init({}); repubBtn.onclick = streamToYouTube; stopBtn.onclick = stopStream; getStream(); } function getStream() {
fetchUrl = url + "/rtsp/startup"; const options = { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ "uri": rtspStream }), } fetch(fetchUrl, options); console.log("Stream Captured"); } function streamToYouTube() {
fetchUrl = url + "/push/startup"; const options = { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ "streamName": rtspStream, "rtmpUrl": "rtmp://a.rtmp.youtube.com/live2/"+document.getElementById("streamKeyYT").value }), } fetch(fetchUrl, options); streamToFB() } function streamToFB() {
fetchUrl = url + "/push/startup"; const options = { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ "streamName": rtspStream, "rtmpUrl": "rtmps://live-api-s.facebook.com:443/rtmp/"+document.getElementById("streamKeyFB").value }), } fetch(fetchUrl, options); document.getElementById("republishStatus").textContent = "Stream republished"; } function stopStream() {
fetchUrl = url + "/rtsp/terminate"; const options = { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ "uri": document.getElementById("rtspLink").value }), } fetch(fetchUrl, options); document.getElementById("captureStatus").textContent = null; document.getElementById("republishStatus").textContent = null; document.getElementById("stopStatus").textContent = "Stream stopped"; } Open the previously created HTML page. In the first field, enter the unique video stream code copied to YouTube: Create a live stream in your account on Facebook. Copy the unique video stream code. Go back to our web page, paste the copied code into the second field and click "Start republish Now check our republication. Again, go to YouTube Studio and Facebook, wait a few seconds and get a stream preview. To stop republication, click "Stop" Now, as we promised, full source codes of the example: Listing of the HTML file "rtsp-to-rtmp-min.html" <!DOCTYPE html>
<html lang="en"> <head> <script type="text/javascript" src="../../../../flashphoner.js"></script> <script type="text/javascript" src="rtsp-to-rtmp-min.js"></script> </head> <body onload="init_page()"> <input id="streamKeyYT" type="text" placeholder="YouTube Stream key" /> <input id="streamKeyFB" type="text" placeholder="Facebook Stream key" /> <button id="repubBtn">Start republish</button> <div id="republishStatus"></div> <br /> <button id="stopBtn">Stop republish</button> </body> </html> var url = "https://demo.flashphoner.com:8444/rest-api";
var rtspStream = "rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mov" function init_page() { Flashphoner.init({}); repubBtn.onclick = streamToYouTube; stopBtn.onclick = stopStream; getStream(); } function getStream() { fetchUrl = url + "/rtsp/startup"; const options = { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ "uri": rtspStream }), } fetch(fetchUrl, options); console.log("Stream Captured"); } function streamToYouTube() { fetchUrl = url + "/push/startup"; const options = { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ "streamName": rtspStream, "rtmpUrl": "rtmp://a.rtmp.youtube.com/live2/" + document.getElementById("streamKeyYT").value }), } fetch(fetchUrl, options); streamToFB() } function streamToFB() { fetchUrl = url + "/push/startup"; const options = { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ "streamName": rtspStream, "rtmpUrl": "rtmps://live-api-s.facebook.com:443/rtmp/" + document.getElementById("streamKeyFB").value }), } fetch(fetchUrl, options); document.getElementById("republishStatus").textContent = "Stream republished"; } function stopStream() { fetchUrl = url + "/rtsp/terminate"; const options = { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ "uri": rtspStream }), } fetch(fetchUrl, options); document.getElementById("republishStatus").textContent = "Stream stopped"; } =========== Источник: habr.com =========== Похожие новости:
Блог компании Flashphoner ), #_rabota_s_video ( Работа с видео ), #_javascript, #_programmirovanie ( Программирование ), #_videokonferentssvjaz ( Видеоконференцсвязь ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 14:21
Часовой пояс: UTC + 5