Ma kēia ʻatikala makemake wau e kaʻana like i kaʻu mau hoʻāʻo e kahe wikiō ma o nā websockets me ka ʻole o ka hoʻohana ʻana i nā plugins polokalamu ʻaoʻao ʻekolu e like me Adobe Flash Player. E heluhelu e ʻike i ka mea i loaʻa mai.
ʻO Adobe Flash, ʻo Macromedia Flash ma mua, he kahua no ka hana ʻana i nā noi e holo ana ma kahi polokalamu kele pūnaewele. Ma mua o ka hoʻokomo ʻia ʻana o ka Media Stream API, ʻo ia wale nō ke kahua no ka hoʻoheheʻe ʻana i ka wikiō a me ka leo mai kahi webcam, a me ka hana ʻana i nā ʻano kūkā like ʻole a me nā kamaʻilio ʻana ma ka polokalamu kele pūnaewele. ʻO ka protocol no ka hoʻouna ʻana i ka ʻike media RTMP (Real Time Messaging Protocol) ua pani maoli ʻia no ka manawa lōʻihi, ʻo ia hoʻi: inā makemake ʻoe e hoʻoikaika i kāu lawelawe streaming, e ʻoluʻolu e hoʻohana i nā polokalamu mai Adobe iā lākou iho - Adobe Media Server (AMS).
Ma hope o kekahi manawa ma 2012, "haʻalele a kuha" ʻo Adobe i ka lehulehu.
ʻOi aku ka Adobe Flash platform ma mua o 20 mau makahiki, i ia manawa ua ʻike ʻia nā mea koʻikoʻi koʻikoʻi, kākoʻo.
No kaʻu papahana, ua hoʻoholo koke wau e haʻalele loa i ka hoʻohana ʻana o Flash i ka polokalamu kele pūnaewele. Ua hōʻike wau i ke kumu nui ma luna; ʻAʻole i kākoʻo ʻia ʻo Flash ma nā kahua paʻa, a ʻaʻole wau makemake e kau i ka Adobe Flash no ka hoʻomohala ʻana ma Windows (wine emulator). No laila ua hoʻomaka wau e kākau i kahi mea kūʻai aku ma JavaScript. He prototype wale nō kēia, no ka mea ma hope mai ua aʻo au e hiki ke hana ʻoi aku ka maikaʻi o ke kahe ʻana ma muli o ka p2p, noʻu wale nō e lilo ia i hoa - server - peers, akā ʻoi aku ka nui o kēlā me kēia manawa, no ka mea ʻaʻole i mākaukau.
No ka hoʻomaka ʻana, pono mākou i ka server websockets maoli. Ua hana au i ka mea maʻalahi loa ma muli o ka pūʻolo melody go:
Code kikowaena
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)
}
Ma ka mea kūʻai aku (ka ʻaoʻao kahawai), pono ʻoe e komo i ke kāmela. Hana ʻia kēia ma o
Loaʻa iā mākou ke komo (ʻae) i ka pahupaʻikiʻi / microphone ma o
A laila, e hoʻihoʻi ka getUserMedia () i kahi ʻōlelo hoʻohiki, kahi e hāʻawi ai i kahi mea MediaStream - kahi kahawai o ka ʻikepili wikiō-leo. Hāʻawi mākou i kēia mea i ka waiwai src o ka mea wikiō. Code:
ʻaoʻao hoʻolaha
<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>
No ka hoʻolaha ʻana i ke kahawai wikiō ma luna o nā kumu, pono ʻoe e hoʻopili iā ia ma kahi, hoʻopaʻa iā ia, a hoʻouna i nā ʻāpana. ʻAʻole hiki ke hoʻouna ʻia ke kahawai wikiō maka ma o nā websockets. ʻO kēia kahi e hiki mai ai ke kōkua iā mākou
Hoʻopili mākou i ke kahawai wikiō, e wāwahi i nā ʻāpana
<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>
I kēia manawa e hoʻohui kākou i ka hoʻouna ʻana ma o nā websockets. ʻO ka mea kupanaha, ʻo ka mea āu e pono ai no kēia mea
Hoʻouna mākou i ke kahawai wikiō i ke kikowaena
<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>
Ua mākaukau ka ʻaoʻao hoʻolaha! I kēia manawa e hoʻāʻo mākou e loaʻa i kahi kahawai wikiō a hōʻike iā ia ma ka mea kūʻai aku. He aha kā mākou e pono ai no kēia? ʻO ka mea mua, ʻoiaʻiʻo, ka pilina socket. Hoʻopili mākou i kahi "hoʻolohe" i ka mea WebSocket a kau inoa i ka hanana 'memo'. I ka loaʻa ʻana o kahi ʻāpana ʻikepili binary, hoʻolaha kā mākou kikowaena i nā mea kākau inoa, ʻo ia hoʻi, nā mea kūʻai aku. I kēia hihia, hoʻomaka ka hana callback e pili ana me ka "hoʻolohe" o ka hanana 'message' i ka mea kūʻai aku; ua hoʻoili ʻia ka mea ponoʻī i loko o ka manaʻo hana - kahi ʻāpana o ke kahawai wikiō i hoʻopaʻa ʻia e vp8.
ʻAe mākou i ke kahawai wikiō
<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>
No ka manawa lōʻihi ua ho'āʻo wau e hoʻomaopopo i ke kumu hiki ʻole ke hoʻouna koke i nā ʻāpana i loaʻa i ka mea wikiō no ka pāʻani ʻana, akā ua ʻike ʻia ʻaʻole hiki ke hana ʻia kēia, ʻoiaʻiʻo, pono ʻoe e kau mua i ka ʻāpana i kahi paʻa kūikawā i hoʻopaʻa ʻia i ka mea wikiō, a laila wale nō e hoʻomaka ai e pāʻani i ke kahawai wikiō. No kēia e pono ai ʻoe
Hana ʻia ʻo MediaSource ma ke ʻano he mea waena ma waena o ka mea pāʻani pāʻani a me ke kumu o kēia kahawai media. Aia i loko o ka mea MediaSource kahi pale hoʻopili no ke kumu o ke kahawai wikiō/leo. ʻO kahi hiʻohiʻona hiki i ka buffer ke hoʻopaʻa i ka ʻikepili Uint8, no laila pono ʻoe i kahi FileReader e hana i kahi pale. E nānā i ke code a e ʻike ʻia:
Ke pāʻani nei i ke kahawai wikiō
<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>
Ua mākaukau ka prototype o ka lawelawe streaming. ʻO ka hemahema nui, ʻo ka pāʻani wikiō e waiho ma hope o ka ʻaoʻao hoʻouna e 100 ms; hoʻonoho mākou iā mākou iho i ka wā e hoʻokaʻawale ai i ke kahawai wikiō ma mua o ka hoʻouna ʻana i ke kikowaena. Eia kekahi, i koʻu nānā ʻana i kaʻu pona, ua hōʻuluʻulu ʻia ka lag ma waena o ka lawe ʻana a me ka loaʻa ʻana o nā ʻaoʻao, ʻike maopopo ʻia kēia. Ua hoʻomaka wau e ʻimi i nā ala e lanakila ai i kēia hemahema, a ... hele mai
Source: www.habr.com