(تقریبا) د براوزر څخه بې ګټې ویب کیم سټینګ. د رسنیو جریان او ویب ساکټونه

پدې مقاله کې زه غواړم د دریمې ډلې براوزر پلگ انونو لکه اډوب فلش پلیر کارولو پرته د ویب ساکټونو له لارې د ویډیو جریان کولو هڅې شریک کړم. د دې موندلو لپاره ولولئ چې څه یې راغلي.

Adobe Flash، پخوا د Macromedia Flash، د غوښتنلیکونو جوړولو لپاره یو پلیټ فارم دی چې په ویب براوزر کې چلیږي. د میډیا سټریم API معرفي کولو دمخه ، دا په عملی ډول د ویب کیم څخه د ویډیو او غږ خپرولو لپاره یوازینی پلیټ فارم و ، په بیله بیا په براوزر کې د مختلف ډول کنفرانسونو او چیټونو رامینځته کولو لپاره. د میډیا معلوماتو لیږدولو پروتوکول RTMP (ریښتیني وخت پیغام رسولو پروتوکول) واقعیا د اوږدې مودې لپاره تړل شوی و ، پدې معنی: که تاسو غواړئ خپل سټیمینګ خدمت ته وده ورکړئ ، نو د اډوب پخپله سافټویر کارولو لپاره مهربان اوسئ - Adobe میډیا سرور (AMS).

په 2012 کې یو څه وخت وروسته، Adobe خلکو ته "له لاسه ورکړه او هغه یې توی کړه". مشخصات RTMP پروتوکول، چې تېروتنې لري او په اصل کې نیمګړی و. پدې وخت کې ، پراختیا کونکو د دې پروتوکول خپل پلي کول پیل کړل ، او د Wowza سرور څرګند شو. په 2011 کې، Adobe د Wowza په وړاندې د RTMP پورې اړوند پیټینټونو غیرقانوني کارونې لپاره قضیه ثبت کړه؛ له 4 کلونو وروسته، شخړه په دوستانه توګه حل شوه.

د اډوب فلش پلیټ فارم له 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)
}

په پیرودونکي (سټریمینګ اړخ) کې ، تاسو لومړی اړتیا لرئ کیمرې ته لاسرسی ومومئ. دا له لارې ترسره کیږي میډیا سټریم API.

موږ کیمرې / مایکروفون ته لاسرسی (اجازه) ترلاسه کوو د رسنیو وسایل API. دا API یو میتود وړاندې کوي MediaDevices.getUserMedia()، کوم چې پاپ اپ ښیي. یوه کړکۍ د کارونکي څخه د کیمرې او/یا مایکروفون د لاسرسي لپاره د اجازې غوښتنه کوي. زه غواړم یادونه وکړم چې ما په ګوګل کروم کې ټولې تجربې ترسره کړې، مګر زه فکر کوم چې هرڅه به په فایرفوکس کې ورته کار وکړي.

بیا، 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>

په ساکټونو کې د ویډیو جریان خپرولو لپاره، تاسو اړتیا لرئ چې دا په کوم ځای کې کوډ کړئ، بفر یې کړئ، او په برخو کې یې انتقال کړئ. د خام ویډیو جریان د ویب ساکټونو له لارې نشي لیږدول کیدی. دا هغه ځای دی چې زموږ مرستې ته راځي د MediaRecorder 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>

د اوږدې مودې لپاره ما هڅه وکړه چې پوه شم چې ولې دا ناشونې ده چې ترلاسه شوي ټوټې سمدلاسه د ویډیو عنصر ته د پلے بیک لپاره واستوئ، مګر دا معلومه شوه چې دا نشي ترسره کیدی، البته، تاسو باید لومړی ټوټه په ځانګړي بفر کې واچوئ. د ویډیو عنصر، او یوازې بیا به دا د ویډیو جریان پیل کړي. د دې لپاره تاسو اړتیا لرئ د MediaSource API и د فایل ریډر API.

میډیا سرچینه د میډیا پلے بیک څیز او د دې میډیا جریان سرچینې ترمینځ د یو ډول مینځګړی په توګه کار کوي. د میډیا سورس اعتراض د ویډیو/آډیو جریان سرچینې لپاره د پلګ وړ وړ بفر لري. یوه ځانګړتیا دا ده چې بفر یوازې د Uint8 ډاټا ساتلی شي، نو تاسو به د داسې بفر جوړولو لپاره فایل ریډر ته اړتیا ولرئ. کوډ وګورئ او دا به نور روښانه شي:

د ویډیو جریان پلی کول

<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 ms شاته پاتې شي؛ موږ دا پخپله تنظیم کوو کله چې سرور ته د لیږدولو دمخه د ویډیو جریان ویشلو. سربیره پردې ، کله چې ما په خپل لپ ټاپ کې چیک کړ ، د لیږد او ترلاسه کولو اړخونو ترمینځ وقفه په تدریجي ډول راټولیږي ، دا په څرګنده توګه لیدل کیده. ما د دې نیمګړتیا د لرې کولو لپاره د لارو په لټه کې پیل وکړ، او ... راورسید RTCPeerConnection API، کوم چې تاسو ته اجازه درکوي پرته له چالونو څخه د ویډیو جریان لیږد کړئ لکه جریان په ټوټو ویشل. د راټولولو ځنډ، زما په اند، د دې حقیقت له امله دی چې براوزر هره ټوټه د لیږد دمخه د ویبم بڼه کې بیا کوډ کوي. ما نور څه ونه موند، مګر د WebRTC مطالعه پیل کړه. زه فکر کوم چې زه به د خپلې څیړنې د پایلو په اړه جلا مقاله ولیکم که چیرې ما د ټولنې لپاره په زړه پورې وي.

سرچینه: www.habr.com

Add a comment