هن آرٽيڪل ۾، مان ايڊوب فليش پليئر جهڙن ٽئين پارٽي برائوزر پلگ ان استعمال ڪرڻ کان سواءِ ويب ساکٽ ذريعي وڊيو اسٽريمنگ ڪرڻ جي پنهنجي ڪوششن کي شيئر ڪرڻ چاهيان ٿو. نتيجا ڏسڻ لاءِ پڙهو.
ايڊوب فليش - اڳوڻي ميڪروميڊيا فليش - ويب برائوزر ۾ هلندڙ ايپليڪيشنون ٺاهڻ لاءِ هڪ پليٽ فارم آهي. ميڊيا اسٽريم 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)
}
ڪلائنٽ (براڊڪاسٽنگ واري پاسي) تي، توهان کي پهريان ڪئميرا تائين رسائي حاصل ڪرڻ جي ضرورت آهي. اهو ذريعي ڪيو ويندو آهي .
اسان کي ڪئميرا/مائڪروفون تائين رسائي (اجازت) ملي ٿي هي 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 توهان کي انڪوڊ ڪرڻ ۽ هڪ اسٽريم کي ٽڪرن ۾ ورهائڻ جي اجازت ڏئي ٿو. مان وڊيو اسٽريم کي دٻائڻ لاءِ انڪوڊ ڪريان ٿو، نيٽ ورڪ تي موڪليل بائيٽس جو تعداد گهٽائي ٿو. هڪ ڀيرو ٽڪرن ۾ ورهائجي، هر ٽڪرو ويب ساکٽ ڏانهن موڪلي سگهجي ٿو. ڪوڊ:
اسان وڊيو اسٽريم کي انڪوڊ ڪيو ۽ ان کي حصن ۾ ورهايو.
<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>
مون گهڻو وقت اهو سمجهڻ جي ڪوشش ڪئي ته مان فوري طور تي حاصل ڪيل ٽڪرن کي وڊيو عنصر ڏانهن پلے بیک لاءِ ڇو نه موڪلي سگهيس، پر اهو ظاهر ٿيو ته اهو يقيني طور تي ممڪن ناهي. توهان کي پهريان ٽڪري کي وڊيو عنصر سان ڳنڍيل هڪ خاص بفر ۾ رکڻ جي ضرورت آهي، ۽ صرف ان کان پوءِ وڊيو اسٽريم هلڻ شروع ٿيندو. اهو ڪرڻ لاءِ، توهان کي ضرورت پوندي и .
ميڊيا سورس ميڊيا پلے بیک آبجيڪٽ ۽ ميڊيا اسٽريم جي سورس جي وچ ۾ هڪ وچولي طور ڪم ڪري ٿو. ميڊيا سورس آبجيڪٽ ۾ سورس وڊيو/آڊيو اسٽريم لاءِ هڪ پلگيبل بفر شامل آهي. هڪ خاص ڳالهه اها آهي ته بفر ۾ صرف 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 ايم ايس پوئتي هوندو، جيڪو اسان پاڻ کي مقرر ڪيو جڏهن وڊيو اسٽريم کي ورهائڻ وقت ان کي سرور تي منتقل ڪرڻ کان اڳ. ان کان علاوه، جڏهن مون ان کي پنهنجي ليپ ٽاپ تي آزمايو، مون کي بتدريج ٽرانسميٽنگ ۽ وصول ڪندڙ سائڊ جي وچ ۾ هڪ وقفو محسوس ٿيو، جيڪو واضح طور تي نظر اچي رهيو هو. مون هن خرابي کي دور ڪرڻ جا طريقا ڳولڻ شروع ڪيا، ۽... مون کي مليو ، جيڪو وڊيو کي اسٽريم ڪرڻ جي اجازت ڏئي ٿو بغير ڪنهن چال جي جيئن اسٽريم کي ٽڪرن ۾ ورهايو وڃي. مون کي يقين آهي ته جمع ٿيڻ ۾ دير، برائوزر جي ٽرانسميشن کان اڳ هر ٽڪر کي WebM فارميٽ ۾ ٽرانسڪوڊ ڪرڻ جي ڪري آهي. مون وڌيڪ کوٽائي ڪرڻ بند ڪيو ۽ WebRTC جو مطالعو شروع ڪيو. جيڪڏهن مون کي ڪميونٽي لاءِ دلچسپ لڳي ته مان پنهنجي تحقيق جي نتيجن بابت هڪ الڳ مضمون لکڻ جو ارادو رکان ٿو.
جو ذريعو: www.habr.com
