هن آرٽيڪل ۾ مان حصيداري ڪرڻ چاهيان ٿو وڊيو اسٽريم ڪرڻ جي منهنجي ڪوششن کي ويب ساکٽ ذريعي بغير ٽئين پارٽي برائوزر پلگ ان استعمال ڪرڻ جهڙوڪ Adobe Flash Player. انهي کي ڳولڻ لاء پڙهو ته ان مان ڇا آيو.
Adobe Flash، اڳ ۾ Macromedia Flash، ايپليڪيشن ٺاهڻ لاءِ هڪ پليٽ فارم آهي جيڪي ويب برائوزر ۾ هلن ٿيون. ميڊيا اسٽريم API جي تعارف کان اڳ، اهو عملي طور تي ويب ڪيم کان وڊيو ۽ آواز اسٽريمنگ لاءِ واحد پليٽ فارم هو، انهي سان گڏ برائوزر ۾ مختلف قسم جون ڪانفرنسون ۽ چيٽ ٺاهڻ لاءِ. ميڊيا جي معلومات جي منتقلي لاءِ پروٽوڪول RTMP (Real Time Messaging Protocol) اصل ۾ هڪ ڊگهي وقت لاءِ بند هو، جنهن جو مطلب هو: جيڪڏهن توهان چاهيو ٿا ته پنهنجي اسٽريمنگ سروس کي بهتر بڻائي، ته مهرباني ڪري پاڻ کي Adobe مان سافٽ ويئر استعمال ڪرڻ لاءِ مهرباني ڪريو - Adobe Media Server (AMS).
2012 ۾ ڪجهه وقت کان پوء، Adobe عوام کي "ڇڏي ڇڏيو ۽ ان کي ختم ڪيو".
ايڊوب فليش پليٽ فارم 20 سالن کان وڌيڪ پراڻو آهي، جنهن دوران ڪيتريون ئي نازڪ خاميون دريافت ڪيون ويون آهن، سپورٽ
منهنجي منصوبي لاء، مون فوري طور تي برائوزر ۾ فليش جي استعمال کي مڪمل طور تي ختم ڪرڻ جو فيصلو ڪيو. مون مٿي بيان ڪيو بنيادي سبب؛ فليش موبائل پليٽ فارمن تي به سپورٽ نه آهي، ۽ مان واقعي نه ٿي چاهيان ته ايڊوب فليش کي ونڊوز تي ڊولپمينٽ لاءِ (وائن ايموليٽر). تنهن ڪري مان جاوا اسڪرپٽ ۾ ڪلائنٽ لکڻ لاءِ نڪتو. اهو صرف هڪ پروٽوٽائپ هوندو، ڇاڪاڻ ته بعد ۾ مون کي معلوم ٿيو ته اسٽريمنگ تمام گهڻي موثر طريقي سان ٿي سگهي ٿي 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)
}
ڪلائنٽ تي (اسٽريمنگ پاسي)، توهان کي پهريون ڀيرو ڪئميرا تائين رسائي جي ضرورت آهي. هن ذريعي ڪيو ويندو آهي
اسان حاصل ڪريون ٿا رسائي (اجازت) ذريعي ڪئميرا / مائڪروفون تائين
اڳيون، getUserMedia() هڪ واعدو موٽائي ٿو، جنهن تي اهو هڪ MediaStream اعتراض پاس ڪري ٿو - وڊيو-آڊيو ڊيٽا جو هڪ وهڪرو. اسان هن اعتراض کي وڊيو عنصر جي 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>
ساکٽ تي وڊيو اسٽريم کي نشر ڪرڻ لاءِ، توهان کي ان کي ڪٿي انڪوڊ ڪرڻ، ان کي بفر ڪرڻ ۽ ان کي حصن ۾ منتقل ڪرڻ جي ضرورت آهي. خام وڊيو وهڪرو ويب ساکٽ ذريعي منتقل نه ٿي ڪري سگھجي. اهو آهي جتي اهو اسان جي مدد لاء اچي ٿو
اسان وڊيو اسٽريم کي انڪوڊ ڪيو، ان کي ٽڪر ۾ ٽوڙيو
<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>
نشريات واري پاسي تيار آهي! هاڻي اچو ته هڪ وڊيو وهڪرو حاصل ڪرڻ جي ڪوشش ڪريو ۽ ان کي ڪلائنٽ تي ڏيکاري. ان لاءِ اسان کي ڪهڙي ضرورت آهي؟ پهرين، يقينا، ساکٽ ڪنيڪشن. اسان ڳنڍيون ٿا ”ٻڌندڙ“ WebSocket اعتراض سان ۽ سبسڪرائب ڪريو 'پيغام' واقعي جي. حاصل ڪرڻ کان پوء بائنري ڊيٽا جو هڪ ٽڪرو، اسان جو سرور ان کي سبسڪرائبرز تائين نشر ڪري ٿو، يعني ڪلائنٽ. انهي حالت ۾، ڪال بڪ فنڪشن سان لاڳاپيل "ٻڌندڙ" سان لاڳاپيل 'پيغام' واقعي جي ڪلائنٽ تي چالو ڪيو ويو آهي؛ اعتراض پاڻ کي فنڪشنل دليل ۾ منتقل ڪيو ويو آهي - وڊيو اسٽريم جو هڪ ٽڪرو 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 ميڊيا پلے بیک اعتراض ۽ هن ميڊيا اسٽريم جي ماخذ جي وچ ۾ هڪ قسم جي وچولي طور ڪم ڪري ٿو. MediaSource اعتراض وڊيو/آڊيو اسٽريم جي ماخذ لاءِ پلگبلبل بفر تي مشتمل آهي. ھڪڙي خصوصيت اھو آھي ته بفر صرف 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 ms ذريعي منتقلي واري پاسي کان پوئتي رهجي ويندي؛ اسان اهو پاڻ کي سيٽ ڪيو جڏهن وڊيو اسٽريم کي ورهائڻ کان پهريان ان کي سرور ڏانهن منتقل ڪيو وڃي. ان کان علاوه، جڏهن مون پنهنجي ليپ ٽاپ تي چيڪ ڪيو، منتقلي ۽ وصول ڪندڙ پاسن جي وچ ۾ دير سان گڏ ٿي وئي، اهو واضح طور تي نظر اچي رهيو هو. مون ان نقصان کي دور ڪرڻ جا طريقا ڳولڻ شروع ڪيا، ۽...
جو ذريعو: www.habr.com