San Airteagal seo ba mhaith liom mo chuid iarrachtaí físeáin a shruthú trí shoicéid gréasáin a roinnt gan úsáid a bhaint as forlíontáin brabhsálaí tríú páirtí ar nós Adobe Flash Player. Léigh ar aghaidh chun a fháil amach cad a tháinig de.
Is ardán é Adobe Flash, Macromedia Flash roimhe seo, chun feidhmchláir a chruthú a ritheann i mbrabhsálaí gréasáin. Sular tugadh isteach an Media Stream API, ba é an t-aon ardán a bhí ann chun físeáin agus guth a shruthú ó cheamara gréasáin, chomh maith le cineálacha éagsúla comhdhálacha agus comhráite a chruthú sa bhrabhsálaí. Dúnadh an prótacal maidir le faisnéis meán a tharchur RTMP (Prótacal Teachtaireachtaí Fíor-Ama) ar feadh i bhfad, rud a chiallaigh: más mian leat do sheirbhís sruthú a threisiú, bí cineálta go leor chun bogearraí ó Adobe féin a úsáid - Adobe Media Server (AMS).
Tar éis roinnt ama in 2012, “thug Adobe suas é agus scar sé amach” don phobal.
Tá ardán Adobe Flash níos mó ná 20 bliain d'aois, agus le linn an ama sin aimsíodh go leor leochaileachtaí ríthábhachtacha, tacaíocht
Maidir le mo thionscadal, chinn mé láithreach úsáid Flash sa bhrabhsálaí a thréigean go hiomlán. Thug mé le fios an phríomhchúis thuas; ní thacaítear le Flash freisin ar ardáin soghluaiste, agus níor theastaigh uaim Adobe Flash a imscaradh le haghaidh forbartha ar Windows (aithriseoir fíona). Mar sin leag mé amach cliant a scríobh i JavaScript. Ní bheidh anseo ach fréamhshamhail, mar níos déanaí d'fhoghlaim mé gur féidir sruthú a dhéanamh i bhfad níos éifeachtaí bunaithe ar p2p, ach amháin domsa is piaraí - freastalaí - piaraí a bheidh ann, ach níos mó air sin uair eile, toisc nach bhfuil sé réidh fós.
Chun tús a chur leis, ní mór dúinn an freastalaí gréasáin soicéad iarbhír. Rinne mé an ceann is simplí bunaithe ar an bpacáiste melody go:
Cóid freastalaí
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)
}
Ar an gcliant (taobh sruthú), ní mór duit rochtain a fháil ar an gceamara ar dtús. Déantar é seo trí
Faighimid rochtain (cead) ar an gceamara/micreafón tríd
Ansin, seolann getUserMedia() Gealltanas, a dtéann sé thar réad MediaStream chuige - sruth de shonraí físe-fuaime. Sannaimid an réad seo d'airí src na heiliminte físeáin. Cód:
Taobh craolacháin
<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>
Chun sruth físeáin a chraoladh thar soicéid, ní mór duit é a ionchódú áit éigin, é a mhaolánú, agus é a tharchur i gcodanna. Ní féidir an sruth físe amh a tharchur trí shoicéid gréasáin. Seo an áit a dtagann sé chun ár gcabhair
Ionchódaíonn muid an sruth físeáin, briseann sé ina phíosaí é
<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>
Anois cuirimis tarchur trí shoicéid ghréasáin. Ionadh, tá gach atá uait le haghaidh an réad
Déanaimid an sruth físeáin a tharchur chuig an bhfreastalaí
<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>
Tá an taobh craolta réidh! Anois déanaimis iarracht sruth físeáin a fháil agus é a thaispeáint ar an gcliant. Cad atá de dhíth orainn le haghaidh seo? Gcéad dul síos, ar ndóigh, an nasc soicéad. Ceangaimid “éisteoir” den réad WebSocket agus déanaimid liostáil don imeacht ‘teachtaireacht’. Tar éis píosa sonraí dénártha a fháil, craolann ár bhfreastalaí é do shíntiúsóirí, is é sin, cliaint. Sa chás seo, spreagtar an fheidhm aisghlao a bhaineann le “éisteoir” an imeachta ‘teachtaireachta’ ar an gcliant;
Glacaimid le sruth físeáin
<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>
Ar feadh i bhfad rinne mé iarracht a thuiscint cén fáth go bhfuil sé dodhéanta na píosaí faighte a sheoladh láithreach chuig an eilimint físe le haghaidh athsheinm, ach d'éirigh sé amach nach féidir é seo a dhéanamh, ar ndóigh, ní mór duit an píosa a chur i maolán speisialta ar dtús. an eilimint físe, agus ansin amháin a thosóidh sé ag imirt an tsrutha físeáin. Chun seo beidh ort
Feidhmíonn MediaSource mar chineál idirghabhálaí idir réad athsheinm na meán agus foinse an tsrutha meán seo. Tá maolán inphlugáilte san oibiacht MediaSource le haghaidh foinse an tsrutha físe/fuaime. Gné amháin is ea nach féidir leis an maolán ach sonraí Uint8 a choinneáil, mar sin beidh FileReader uait chun maolán den sórt sin a chruthú. Féach ar an gcód agus beidh sé níos soiléire:
Sruth físeán a imirt
<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>
Tá fréamhshamhail na seirbhíse sruthú réidh. Is é an príomh-mhíbhuntáiste ná go mbeidh athsheinm físe 100 ms taobh thiar den taobh tarchurtha; Thairis sin, nuair a sheiceáil mé ar mo ríomhaire glúine, de réir a chéile carntha an t-aga moille idir na taobhanna tarchuir agus glactha, bhí sé seo le feiceáil go soiléir. Thosaigh mé ag lorg bealaí chun an míbhuntáiste seo a shárú, agus... tháinig mé trasna
Foinse: will.com