(تقريبا) بيڪار ويب ڪيم برائوزر کان اسٽريمنگ. ميڊيا اسٽريم ۽ ويب ساکٽ

هن آرٽيڪل ۾، مان ايڊوب فليش پليئر جهڙن ٽئين پارٽي برائوزر پلگ ان استعمال ڪرڻ کان سواءِ ويب ساکٽ ذريعي وڊيو اسٽريمنگ ڪرڻ جي پنهنجي ڪوششن کي شيئر ڪرڻ چاهيان ٿو. نتيجا ڏسڻ لاءِ پڙهو.

ايڊوب فليش - اڳوڻي ميڪروميڊيا فليش - ويب برائوزر ۾ هلندڙ ايپليڪيشنون ٺاهڻ لاءِ هڪ پليٽ فارم آهي. ميڊيا اسٽريم API جي تعارف کان اڳ، اهو عملي طور تي ويب ڪيم مان وڊيو ۽ آواز کي اسٽريم ڪرڻ لاءِ واحد پليٽ فارم هو، انهي سان گڏ برائوزر ۾ مختلف قسمن جون ڪانفرنسون ۽ چيٽ ٺاهڻ لاءِ. ميڊيا جي معلومات منتقل ڪرڻ لاءِ پروٽوڪول، RTMP (ريئل ٽائيم ميسيجنگ پروٽوڪول)، ڊگهي عرصي تائين مؤثر طريقي سان بند ڪيو ويو هو، مطلب ته جيڪڏهن توهان پنهنجي اسٽريمنگ سروس لانچ ڪرڻ چاهيو ٿا، ته توهان کي ايڊوب جو پنهنجو سافٽ ويئر، ايڊوب ميڊيا سرور (AMS) استعمال ڪرڻ گهرجي.

ڪجهه وقت کان پوءِ 2012 ۾، ايڊوب "همت هارائي ڇڏي ۽ عوام آڏو اڇلائي ڇڏيو" وضاحت آر ٽي ايم پي پروٽوڪول، جنهن ۾ ڪيڙا هئا ۽ بنيادي طور تي نامڪمل هو، مڪمل طور تي لاڳو نه ڪيو ويو هو. ان وقت تائين، ڊولپرز پروٽوڪول جا پنهنجا لاڳو ڪرڻ شروع ڪري ڇڏيا هئا، ۽ اهڙي طرح ووزا سرور پيدا ٿيو. 2011 ۾، ايڊوب ووزا خلاف آر ٽي ايم پي سان لاڳاپيل پيٽنٽ جي غير قانوني استعمال لاءِ ڪيس داخل ڪيو؛ تڪرار چار سالن بعد خوش اسلوبي سان حل ڪيو ويو.

ايڊوب فليش پليٽ فارم 20 سالن کان وڌيڪ پراڻو آهي، جنهن دوران ڪيتريون ئي نازڪ ڪمزوريون دريافت ڪيون ويون آهن، سپورٽ وعدو ڪيو 2020 تائين موجود نه هوندو، جنهن سان اسٽريمنگ سروس لاءِ ڪجھ متبادل رهجي ويندا.

منهنجي منصوبي لاءِ، مون فوري طور تي برائوزر ۾ فليش کي مڪمل طور تي ڇڏڻ جو فيصلو ڪيو. مون مٿي مکيه سبب جو ذڪر ڪيو، پر فليش موبائل پليٽ فارمن تي بلڪل به سپورٽ نه آهي، ۽ ونڊوز تي ترقي لاءِ ايڊوب فليش کي ترتيب ڏيڻ (وائن ايموليٽر استعمال ڪندي) يقيني طور تي ناپسنديده هو. تنهن ڪري، مون جاوا اسڪرپٽ ۾ هڪ ڪلائنٽ لکڻ جو فيصلو ڪيو. اهو صرف هڪ پروٽوٽائپ هوندو، جيئن مون بعد ۾ سکيو ته اسٽريمنگ پير-ٽو-پيئر (P2P) استعمال ڪندي تمام گهڻو ڪارآمد طريقي سان ڪري سگهجي ٿو، جيتوڻيڪ منهنجي صورت ۾، اهو پير-سرور-پيئر هوندو. پر اهو ڪنهن ٻئي وقت لاءِ هڪ ڪهاڻي آهي، ڇاڪاڻ ته اهو اڃا تائين تيار ناهي.

شروع ڪرڻ لاءِ، اسان کي هڪ ويب ساڪيٽ سرور جي ضرورت آهي. مون ميلوڊي گو پيڪيج استعمال ڪندي هڪ سادو سرور ٺاهيو آهي:

سرور-سائڊ ڪوڊ

package main

import (
	"errors"
	"github.com/go-chi/chi"
	"gopkg.in/olahol/melody.v1"
	"log"
	"net/http"
	"time"
)

func main() {
	r := chi.NewRouter()
	m := melody.New()

	m.Config.MaxMessageSize = 204800

	r.Get("/", func(w http.ResponseWriter, r *http.Request) {
		http.ServeFile(w, r, "public/index.html")
	})
	r.Get("/ws", func(w http.ResponseWriter, r *http.Request) {
		m.HandleRequest(w, r)
	})

         // Бродкастим видео поток 
	m.HandleMessageBinary(func(s *melody.Session, msg []byte) {
		m.BroadcastBinary(msg)
	})

	log.Println("Starting server...")

	http.ListenAndServe(":3000", r)
}

ڪلائنٽ (براڊڪاسٽنگ واري پاسي) تي، توهان کي پهريان ڪئميرا تائين رسائي حاصل ڪرڻ جي ضرورت آهي. اهو ذريعي ڪيو ويندو آهي MediaStream API.

اسان کي ڪئميرا/مائڪروفون تائين رسائي (اجازت) ملي ٿي ميڊيا ڊوائيسز APIهي API هڪ طريقو مهيا ڪري ٿو ميڊيا ڊيوائسز.گيٽ يوزر ميڊيا ()، جيڪو هڪ پاپ اپ ونڊو ڏيکاري ٿو جيڪو صارف کان ڪئميرا ۽/يا مائڪروفون تائين رسائي جي اجازت گهري ٿو. مان اهو ٻڌائڻ چاهيان ٿو ته مون پنهنجا سڀئي تجربا گوگل ڪروم ۾ ڪيا، پر مون کي لڳي ٿو ته اهو فائر فاڪس ۾ به ساڳيو ڪم ڪندو.

اڳيون، getUserMedia() هڪ پروميس واپس ڪري ٿو، ان کي ميڊيا اسٽريم آبجيڪٽ پاس ڪري ٿو - وڊيو ۽ آڊيو ڊيٽا جو هڪ وهڪرو. اسان هن آبجيڪٽ کي وڊيو عنصر جي src ملڪيت کي تفويض ڪريون ٿا. ڪوڊ:

نشريات واري پاسي

<style>
  #videoObjectHtml5ApiServer { width: 320px; height: 240px; background: #666; }
</style>
</head>
<body>
<!-- Здесь в этом "окошечке" клиент будет видеть себя -->
<video autoplay id="videoObjectHtml5ApiServer"></video>

<script type="application/javascript">
  var
        video = document.getElementById('videoObjectHtml5ApiServer');

// если доступен MediaDevices API, пытаемся получить доступ к камере (можно еще и к микрофону)
// getUserMedia вернет обещание, на которое подписываемся и полученный видеопоток в колбеке направляем в video объект на странице

if (navigator.mediaDevices.getUserMedia) {
        navigator.mediaDevices.getUserMedia({video: true}).then(function (stream) {
          // видео поток привязываем к video тегу, чтобы клиент мог видеть себя и контролировать 
          video.srcObject = stream;
        });
}
</script>

ساکٽ تي وڊيو اسٽريم نشر ڪرڻ لاءِ، ان کي انڪوڊ ڪرڻ، بفر ڪرڻ، ۽ ٽڪرن ۾ منتقل ڪرڻ جي ضرورت آهي. هڪ خام وڊيو اسٽريم ويب ساکٽ تي منتقل نه ٿي ڪري سگهجي. هي اهو هنڌ آهي جتي ويب ساکٽ بچاءُ لاءِ ايندا آهن. ميڊيا ريڪارڊر APIهي API توهان کي انڪوڊ ڪرڻ ۽ هڪ اسٽريم کي ٽڪرن ۾ ورهائڻ جي اجازت ڏئي ٿو. مان وڊيو اسٽريم کي دٻائڻ لاءِ انڪوڊ ڪريان ٿو، نيٽ ورڪ تي موڪليل بائيٽس جو تعداد گهٽائي ٿو. هڪ ڀيرو ٽڪرن ۾ ورهائجي، هر ٽڪرو ويب ساکٽ ڏانهن موڪلي سگهجي ٿو. ڪوڊ:

اسان وڊيو اسٽريم کي انڪوڊ ڪيو ۽ ان کي حصن ۾ ورهايو.

<style>
  #videoObjectHtml5ApiServer { width: 320px; height: 240px; background: #666; }
</style>
</head>
<body>
<!-- Здесь в этом "окошечке" клиент будет видеть себя -->
<video autoplay id="videoObjectHtml5ApiServer"></video>

<script type="application/javascript">
  var
        video = document.getElementById('videoObjectHtml5ApiServer');

// если доступен MediaDevices API, пытаемся получить доступ к камере (можно еще и к микрофону)
// getUserMedia вернет обещание, на которое подписываемся и полученный видеопоток в колбеке направляем в video объект на странице

if (navigator.mediaDevices.getUserMedia) {
        navigator.mediaDevices.getUserMedia({video: true}).then(function (stream) {
          // видео поток привязываем к video тегу, чтобы клиент мог видеть себя и контролировать 
          video.srcObject = s;
          var
            recorderOptions = {
                mimeType: 'video/webm; codecs=vp8' // будем кодировать видеопоток в формат webm кодеком vp8
              },
              mediaRecorder = new MediaRecorder(s, recorderOptions ); // объект MediaRecorder

               mediaRecorder.ondataavailable = function(e) {
                if (e.data && e.data.size > 0) {
                  // получаем кусочек видеопотока в e.data
                }
            }

            mediaRecorder.start(100); // делит поток на кусочки по 100 мс каждый

        });
}
</script>

هاڻي اچو ته ويب ساکٽ ٽرانسميشن شامل ڪريون. حيرت انگيز طور تي، توهان کي صرف هڪ شئي جي ضرورت آهي. ويب ساکٽان ۾ صرف ٻه طريقا آهن: موڪليو ۽ بند ڪريو. نالا پاڻ لاءِ ڳالهائين ٿا. اضافي ڪوڊ:

اسان وڊيو اسٽريم کي سرور ڏانهن منتقل ڪريون ٿا

<style>
  #videoObjectHtml5ApiServer { width: 320px; height: 240px; background: #666; }
</style>
</head>
<body>
<!-- Здесь в этом "окошечке" клиент будет видеть себя -->
<video autoplay id="videoObjectHtml5ApiServer"></video>

<script type="application/javascript">
  var
        video = document.getElementById('videoObjectHtml5ApiServer');

// если доступен MediaDevices API, пытаемся получить доступ к камере (можно еще и к микрофону)
// getUserMedia вернет обещание, на которое подписываемся и полученный видеопоток в колбеке направляем в video объект на странице

if (navigator.mediaDevices.getUserMedia) {
        navigator.mediaDevices.getUserMedia({video: true}).then(function (stream) {
          // видео поток привязываем к video тегу, чтобы клиент мог видеть себя и контролировать 
          video.srcObject = s;
          var
            recorderOptions = {
                mimeType: 'video/webm; codecs=vp8' // будем кодировать видеопоток в формат webm кодеком vp8
              },
              mediaRecorder = new MediaRecorder(s, recorderOptions ), // объект MediaRecorder
              socket = new WebSocket('ws://127.0.0.1:3000/ws');

               mediaRecorder.ondataavailable = function(e) {
                if (e.data && e.data.size > 0) {
                  // получаем кусочек видеопотока в e.data
                 socket.send(e.data);
                }
            }

            mediaRecorder.start(100); // делит поток на кусочки по 100 мс каждый

        }).catch(function (err) { console.log(err); });
}
</script>

براڊڪاسٽ سائڊ تيار آهي! هاڻي اچو ته هڪ وڊيو اسٽريم حاصل ڪرڻ ۽ ان کي ڪلائنٽ تي ڏيکارڻ جي ڪوشش ڪريون. ان لاءِ اسان کي ڇا گهرجي؟ پهرين، يقيناً، هڪ ساکٽ ڪنيڪشن. اسان هڪ ٻڌندڙ کي ويب ساکٽ آبجيڪٽ سان ڳنڍيندا آهيون ۽ 'پيغام' ايونٽ کي سبسڪرائب ڪندا آهيون. بائنري ڊيٽا جو هڪ ٽڪرو حاصل ڪرڻ کان پوءِ، اسان جو سرور ان کي سبسڪرائبرز، يعني ڪلائنٽس ڏانهن نشر ڪندو آهي. ڪلائنٽ تي، 'پيغام' ٻڌندڙ سان لاڳاپيل هڪ ڪال بيڪ فنڪشن شروع ٿئي ٿو، ۽ فنڪشن جو دليل اصل اعتراض آهي - وڊيو اسٽريم جو VP8-انڪوڊ ٿيل ٽڪرو.

اسان کي هڪ وڊيو اسٽريم ملي رهيو آهي.

<style>
  #videoObjectHtml5ApiServer { width: 320px; height: 240px; background: #666; }
</style>
</head>
<body>
<!-- Здесь в этом "окошечке" клиент будет видеть тебя -->
<video autoplay id="videoObjectHtml5ApiServer"></video>

<script type="application/javascript">
  var
        video = document.getElementById('videoObjectHtml5ApiServer'),
         socket = new WebSocket('ws://127.0.0.1:3000/ws'), 
         arrayOfBlobs = [];

         socket.addEventListener('message', function (event) {
                // "кладем" полученный кусочек в массив 
                arrayOfBlobs.push(event.data);
                // здесь будем читать кусочки
                readChunk();
            });
</script>

مون گهڻو وقت اهو سمجهڻ جي ڪوشش ڪئي ته مان فوري طور تي حاصل ڪيل ٽڪرن کي وڊيو عنصر ڏانهن پلے بیک لاءِ ڇو نه موڪلي سگهيس، پر اهو ظاهر ٿيو ته اهو يقيني طور تي ممڪن ناهي. توهان کي پهريان ٽڪري کي وڊيو عنصر سان ڳنڍيل هڪ خاص بفر ۾ رکڻ جي ضرورت آهي، ۽ صرف ان کان پوءِ وڊيو اسٽريم هلڻ شروع ٿيندو. اهو ڪرڻ لاءِ، توهان کي ضرورت پوندي ميڊيا سورس API и فائل ريڊر API.

ميڊيا سورس ميڊيا پلے بیک آبجيڪٽ ۽ ميڊيا اسٽريم جي سورس جي وچ ۾ هڪ وچولي طور ڪم ڪري ٿو. ميڊيا سورس آبجيڪٽ ۾ سورس وڊيو/آڊيو اسٽريم لاءِ هڪ پلگيبل بفر شامل آهي. هڪ خاص ڳالهه اها آهي ته بفر ۾ صرف Uint8 ڊيٽا شامل ٿي سگهي ٿو، تنهن ڪري اهڙي بفر ٺاهڻ لاءِ هڪ FileReader جي ضرورت آهي. ڪوڊ کي ڏسڻ سان شيون واضح ٿي وينديون:

وڊيو اسٽريم کيڏي رهيو آهي

<style>
  #videoObjectHtml5ApiServer { width: 320px; height: 240px; background: #666; }
</style>
</head>
<body>
<!-- Здесь в этом "окошечке" клиент будет видеть тебя -->
<video autoplay id="videoObjectHtml5ApiServer"></video>

<script type="application/javascript">
  var
        video = document.getElementById('videoObjectHtml5ApiServer'),
         socket = new WebSocket('ws://127.0.0.1:3000/ws'),
        mediaSource = new MediaSource(), // объект MediaSource
        vid2url = URL.createObjectURL(mediaSource), // создаем объект URL для связывания видеопотока с проигрывателем
        arrayOfBlobs = [],
        sourceBuffer = null; // буфер, пока нуль-объект

         socket.addEventListener('message', function (event) {
                // "кладем" полученный кусочек в массив 
                arrayOfBlobs.push(event.data);
                // здесь будем читать кусочки
                readChunk();
            });

         // как только MediaSource будет оповещен , что источник готов отдавать кусочки 
        // видео/аудио потока
        // создаем буфер , следует обратить внимание, что буфер должен знать в каком формате 
        // каким кодеком был закодирован поток, чтобы тем же способом прочитать видеопоток
         mediaSource.addEventListener('sourceopen', function() {
            var mediaSource = this;
            sourceBuffer = mediaSource.addSourceBuffer("video/webm; codecs="vp8"");
        });

      function readChunk() {
        var reader = new FileReader();
        reader.onload = function(e) { 
          // как только FileReader будет готов, и загрузит себе кусочек видеопотока
          // мы "прицепляем" перекодированный в Uint8Array (был Blob) кусочек в буфер, связанный
          // с проигрывателем, и проигрыватель начинает воспроизводить полученный кусочек видео/аудио
          sourceBuffer.appendBuffer(new Uint8Array(e.target.result));

          reader.onload = null;
        }
        reader.readAsArrayBuffer(arrayOfBlobs.shift());
      }
</script>

اسٽريمنگ سروس پروٽوٽائپ تيار آهي. مکيه خرابي اها آهي ته وڊيو پلے بیک ٽرانسميٽنگ سائڊ کان 100 ايم ايس پوئتي هوندو، جيڪو اسان پاڻ کي مقرر ڪيو جڏهن وڊيو اسٽريم کي ورهائڻ وقت ان کي سرور تي منتقل ڪرڻ کان اڳ. ان کان علاوه، جڏهن مون ان کي پنهنجي ليپ ٽاپ تي آزمايو، مون کي بتدريج ٽرانسميٽنگ ۽ وصول ڪندڙ سائڊ جي وچ ۾ هڪ وقفو محسوس ٿيو، جيڪو واضح طور تي نظر اچي رهيو هو. مون هن خرابي کي دور ڪرڻ جا طريقا ڳولڻ شروع ڪيا، ۽... مون کي مليو آر ٽي سي پيئر ڪنيڪشن API، جيڪو وڊيو کي اسٽريم ڪرڻ جي اجازت ڏئي ٿو بغير ڪنهن چال جي جيئن اسٽريم کي ٽڪرن ۾ ورهايو وڃي. مون کي يقين آهي ته جمع ٿيڻ ۾ دير، برائوزر جي ٽرانسميشن کان اڳ هر ٽڪر کي WebM فارميٽ ۾ ٽرانسڪوڊ ڪرڻ جي ڪري آهي. مون وڌيڪ کوٽائي ڪرڻ بند ڪيو ۽ WebRTC جو مطالعو شروع ڪيو. جيڪڏهن مون کي ڪميونٽي لاءِ دلچسپ لڳي ته مان پنهنجي تحقيق جي نتيجن بابت هڪ الڳ مضمون لکڻ جو ارادو رکان ٿو.

جو ذريعو: www.habr.com

DDoS تحفظ سان سائيٽن لاءِ قابل اعتماد هوسٽنگ خريد ڪريو، VPS VDS سرور 🔥 DDoS تحفظ سان قابل اعتماد ويب سائيٽ هوسٽنگ خريد ڪريو، VPS VDS سرورز | ProHoster