(РСчиси) бСскорисна Π²Π΅Π±-ΠΊΠ°ΠΌΠ΅Ρ€Π° која стримува ΠΎΠ΄ прСлистувач. ΠœΠ΅Π΄ΠΈΡƒΠΌΡΠΊΠΈ Ρ‚Π΅ΠΊ ΠΈ Π²Π΅Π±-сокСти

Π’ΠΎ ΠΎΠ²Π°Π° ΡΡ‚Π°Ρ‚ΠΈΡ˜Π° сакам Π΄Π° Π³ΠΈ сподСлам ΠΌΠΎΠΈΡ‚Π΅ ΠΎΠ±ΠΈΠ΄ΠΈ Π·Π° прСнос Π½Π° Π²ΠΈΠ΄Π΅ΠΎ ΠΏΡ€Π΅ΠΊΡƒ Π²Π΅Π±-сокСти Π±Π΅Π· ΠΊΠΎΡ€ΠΈΡΡ‚Π΅ΡšΠ΅ Π½Π° ΠΏΡ€ΠΈΠΊΠ»ΡƒΡ‡ΠΎΡ†ΠΈ Π·Π° прСлистувачи ΠΎΠ΄ Ρ‚Ρ€Π΅Ρ‚ΠΈ страни, ΠΊΠ°ΠΊΠΎ ΡˆΡ‚ΠΎ Π΅ Adobe Flash Player. ΠŸΡ€ΠΎΡ‡ΠΈΡ‚Π°Ρ˜Ρ‚Π΅ Π·Π° Π΄Π° Π΄ΠΎΠ·Π½Π°Π΅Ρ‚Π΅ ΡˆΡ‚ΠΎ ΠΈΠ·Π»Π΅Π·Π΅ ΠΎΠ΄ Ρ‚ΠΎΠ°.

Adobe Flash, ΠΏΠΎΡ€Π°Π½ΠΎ Macromedia Flash, Π΅ ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ° Π·Π° ΠΊΡ€Π΅ΠΈΡ€Π°ΡšΠ΅ Π°ΠΏΠ»ΠΈΠΊΠ°Ρ†ΠΈΠΈ ΠΊΠΎΠΈ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ Π²ΠΎ Π²Π΅Π±-прСлистувач. ΠŸΡ€Π΅Π΄ Π²ΠΎΠ²Π΅Π΄ΡƒΠ²Π°ΡšΠ΅Ρ‚ΠΎ Π½Π° Media Stream API, Ρ‚ΠΎΡ˜ бСшС ΠΏΡ€Π°ΠΊΡ‚ΠΈΡ‡Π½ΠΎ СдинствСната ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ° Π·Π° ΠΏΡ€ΠΎΡΠ»Π΅Π΄ΡƒΠ²Π°ΡšΠ΅ Π²ΠΈΠ΄Π΅ΠΎ ΠΈ глас ΠΎΠ΄ Π²Π΅Π±-ΠΊΠ°ΠΌΠ΅Ρ€Π°, ΠΊΠ°ΠΊΠΎ ΠΈ Π·Π° создавањС Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ Π²ΠΈΠ΄ΠΎΠ²ΠΈ ΠΊΠΎΠ½Ρ„Π΅Ρ€Π΅Π½Ρ†ΠΈΠΈ ΠΈ Ρ€Π°Π·Π³ΠΎΠ²ΠΎΡ€ΠΈ Π²ΠΎ прСлистувачот. ΠŸΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΠΎΡ‚ Π·Π° прСнос Π½Π° мСдиумски ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ RTMP (Real Time Messaging Protocol) Π²ΡΡƒΡˆΠ½ΠΎΡΡ‚ бСшС Π·Π°Ρ‚Π²ΠΎΡ€Π΅Π½ Π΄ΠΎΠ»Π³ΠΎ Π²Ρ€Π΅ΠΌΠ΅, ΡˆΡ‚ΠΎ Π·Π½Π°Ρ‡Π΅ΡˆΠ΅: Π°ΠΊΠΎ сакатС Π΄Π° ја Π·Π°Ρ˜Π°ΠΊΠ½Π΅Ρ‚Π΅ Π²Π°ΡˆΠ°Ρ‚Π° услуга Π·Π° стриминг, Π±ΠΈΠ΄Π΅Ρ‚Π΅ Π΄ΠΎΠ²ΠΎΠ»Π½ΠΎ Ρ™ΡƒΠ±Π΅Π·Π½ΠΈ Π΄Π° користитС софтвСр ΠΎΠ΄ самитС Adobe - Adobe Media Server (AMS).

По Π½Π΅ΠΊΠΎΠ΅ Π²Ρ€Π΅ΠΌΠ΅ Π²ΠΎ 2012 Π³ΠΎΠ΄ΠΈΠ½Π°, Adobe β€žΡΠ΅ ΠΎΡ‚ΠΊΠ°ΠΆΠ° ΠΈ Π³ΠΎ ΠΈΡΠΏΠ»ΡƒΠΊΠ°β€œ Π½Π° Ρ˜Π°Π²Π½ΠΎΡΡ‚Π°. ΡΠΏΠ΅Ρ†ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΡ˜Π° RTMP ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ», кој ΡΠΎΠ΄Ρ€ΠΆΠ΅ΡˆΠ΅ Π³Ρ€Π΅ΡˆΠΊΠΈ ΠΈ Π²ΠΎ ΡΡƒΡˆΡ‚ΠΈΠ½Π° бСшС нСцСлосСн. Π’ΠΎ Ρ‚ΠΎΠ° Π²Ρ€Π΅ΠΌΠ΅, ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ΅Ρ€ΠΈΡ‚Π΅ ΠΏΠΎΡ‡Π½Π°Π° Π΄Π° ΠΏΡ€Π°Π²Π°Ρ‚ свои ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ Π½Π° овој ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» ΠΈ сС појави сСрвСрот Wowza. Π’ΠΎ 2011 Π³ΠΎΠ΄ΠΈΠ½Π°, Adobe поднСсС Ρ‚ΡƒΠΆΠ±Π° ΠΏΡ€ΠΎΡ‚ΠΈΠ² Wowza Π·Π° Π½Π΅Π»Π΅Π³Π°Π»Π½Π° ΡƒΠΏΠΎΡ‚Ρ€Π΅Π±Π° Π½Π° ΠΏΠ°Ρ‚Π΅Π½Ρ‚ΠΈ ΠΏΠΎΠ²Ρ€Π·Π°Π½ΠΈ со RTMP; ΠΏΠΎ 4 Π³ΠΎΠ΄ΠΈΠ½ΠΈ, ΠΊΠΎΠ½Ρ„Π»ΠΈΠΊΡ‚ΠΎΡ‚ бСшС Ρ€Π΅ΡˆΠ΅Π½ спогодбСно.

ΠŸΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π° Adobe Flash Π΅ стара повСќС ΠΎΠ΄ 20 Π³ΠΎΠ΄ΠΈΠ½ΠΈ, Π·Π° Ρ‚ΠΎΠ° Π²Ρ€Π΅ΠΌΠ΅ сС ΠΎΡ‚ΠΊΡ€ΠΈΠ΅Π½ΠΈ ΠΌΠ½ΠΎΠ³Ρƒ ΠΊΡ€ΠΈΡ‚ΠΈΡ‡Π½ΠΈ пропусти, ΠΏΠΎΠ΄Π΄Ρ€ΡˆΠΊΠ° Π²Π΅Ρ‚ΠΈ Π΄Π° Π·Π°Π²Ρ€ΡˆΠΈ Π΄ΠΎ 2020 Π³ΠΎΠ΄ΠΈΠ½Π°, ΠΎΡΡ‚Π°Π²Π°Ρ˜ΡœΠΈ Π½Π΅ΠΊΠΎΠ»ΠΊΡƒ Π°Π»Ρ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²ΠΈ Π·Π° услугата Π·Π° стриминг.

Π—Π° ΠΌΠΎΡ˜ΠΎΡ‚ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚, вСднаш Ρ€Π΅ΡˆΠΈΠ² цСлосно Π΄Π° ја Π½Π°ΠΏΡƒΡˆΡ‚Π°ΠΌ ΡƒΠΏΠΎΡ‚Ρ€Π΅Π±Π°Ρ‚Π° Π½Π° Flash Π²ΠΎ прСлистувачот. Ја Π½Π°Π²Π΅Π΄ΠΎΠ² Π³Π»Π°Π²Π½Π°Ρ‚Π° ΠΏΡ€ΠΈΡ‡ΠΈΠ½Π° ΠΏΠΎΠ³ΠΎΡ€Π΅; Flash исто Ρ‚Π°ΠΊΠ° Π²ΠΎΠΎΠΏΡˆΡ‚ΠΎ Π½Π΅ Π΅ ΠΏΠΎΠ΄Π΄Ρ€ΠΆΠ°Π½ Π½Π° ΠΌΠΎΠ±ΠΈΠ»Π½ΠΈΡ‚Π΅ ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠΈ ΠΈ навистина Π½Π΅ сакав Π΄Π° Π³ΠΎ распорСдам Adobe Flash Π·Π° Ρ€Π°Π·Π²ΠΎΡ˜ Π½Π° Windows (Π΅ΠΌΡƒΠ»Π°Ρ‚ΠΎΡ€ Π·Π° Π²ΠΈΠ½ΠΎ). Π’Π°ΠΊΠ°, Ρ‚Ρ€Π³Π½Π°Π² Π΄Π° напишам ΠΊΠ»ΠΈΠ΅Π½Ρ‚ Π²ΠΎ JavaScript. Ова ќС Π±ΠΈΠ΄Π΅ само ΠΏΡ€ΠΎΡ‚ΠΎΡ‚ΠΈΠΏ, бидСјќи ΠΏΠΎΠ΄ΠΎΡ†Π½Π° Π΄ΠΎΠ·Π½Π°Π² Π΄Π΅ΠΊΠ° стриминг ΠΌΠΎΠΆΠ΅ Π΄Π° сС Π½Π°ΠΏΡ€Π°Π²ΠΈ ΠΌΠ½ΠΎΠ³Ρƒ поСфикасно Π²Ρ€Π· основа Π½Π° p2p, само Π·Π° ΠΌΠ΅Π½Π΅ ќС Π±ΠΈΠ΄Π΅ peer - server - peers, Π½ΠΎ повСќС Π·Π° Ρ‚ΠΎΠ° Π΄Ρ€ΡƒΠ³ ΠΏΠ°Ρ‚, бидСјќи сè ΡƒΡˆΡ‚Π΅ Π½Π΅ Π΅ Π³ΠΎΡ‚ΠΎΠ².

Π—Π° Π΄Π° Π·Π°ΠΏΠΎΡ‡Π½Π΅ΠΌΠ΅, Π½ΠΈ Ρ‚Ρ€Π΅Π±Π° вистинскиот Π²Π΅Π±-сокСт сСрвСр. Јас Π³ΠΎ Π½Π°ΠΏΡ€Π°Π²ΠΈΠ² Π½Π°Ρ˜Π΅Π΄Π½ΠΎΡΡ‚Π°Π²Π½ΠΈΠΎΡ‚ Π²Ρ€Π· основа Π½Π° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΡ‚ melody go:

БСрвСрски ΠΊΠΎΠ΄

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)
}

На ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΡ‚ (страната Π½Π° стриминг), ΠΏΡ€Π²ΠΎ Ρ‚Ρ€Π΅Π±Π° Π΄Π° пристапитС Π΄ΠΎ ΠΊΠ°ΠΌΠ΅Ρ€Π°Ρ‚Π°. Ова сС ΠΏΡ€Π°Π²ΠΈ ΠΏΡ€Π΅ΠΊΡƒ MediaStream API.

Π”ΠΎΠ±ΠΈΠ²Π°ΠΌΠ΅ пристап (Π΄ΠΎΠ·Π²ΠΎΠ»Π°) Π΄ΠΎ ΠΊΠ°ΠΌΠ΅Ρ€Π°Ρ‚Π°/ΠΌΠΈΠΊΡ€ΠΎΡ„ΠΎΠ½ΠΎΡ‚ ΠΏΡ€Π΅ΠΊΡƒ API Π·Π° мСдиумски ΡƒΡ€Π΅Π΄ΠΈ. Овој API ΠΎΠ±Π΅Π·Π±Π΅Π΄ΡƒΠ²Π° ΠΌΠ΅Ρ‚ΠΎΠ΄ MediaDevices.getUserMedia(), кој ΠΏΠΎΠΊΠ°ΠΆΡƒΠ²Π° скокачки ΠΏΡ€ΠΎΠ·ΠΎΡ€Π΅Ρ†. ΠΏΡ€ΠΎΠ·ΠΎΡ€Π΅Ρ† кој Π±Π°Ρ€Π° ΠΎΠ΄ корисникот Π΄ΠΎΠ·Π²ΠΎΠ»Π° Π·Π° пристап Π΄ΠΎ ΠΊΠ°ΠΌΠ΅Ρ€Π°Ρ‚Π° ΠΈ/ΠΈΠ»ΠΈ ΠΌΠΈΠΊΡ€ΠΎΡ„ΠΎΠ½ΠΎΡ‚. Π‘ΠΈ сакал Π΄Π° Π·Π°Π±Π΅Π»Π΅ΠΆΠ°ΠΌ Π΄Π΅ΠΊΠ° Π³ΠΈ ΠΈΠ·Π²Ρ€ΡˆΠΈΠ² ситС СкспСримСнти Π²ΠΎ Google Chrome, Π½ΠΎ мислам Π΄Π΅ΠΊΠ° сè ќС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½ΠΈΡ€Π° исто Π²ΠΎ Firefox.

Π‘Π»Π΅Π΄Π½ΠΎ, getUserMedia() Π²Ρ€Π°ΡœΠ° Promise, Π½Π° ΠΊΠΎΠ΅ ΠΌΡƒ ΠΏΡ€Π΅Π΄Π°Π²Π° ΠΎΠ±Ρ˜Π΅ΠΊΡ‚ 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>

Π—Π° Π΄Π° Π΅ΠΌΠΈΡ‚ΡƒΠ²Π°Ρ‚Π΅ Π²ΠΈΠ΄Π΅ΠΎ стрим ΠΏΡ€Π΅ΠΊΡƒ ΠΏΡ€ΠΈΠΊΠ»ΡƒΡ‡ΠΎΡ†ΠΈΡ‚Π΅, Ρ‚Ρ€Π΅Π±Π° Π΄Π° Π³ΠΎ ΡˆΠΈΡ„Ρ€ΠΈΡ€Π°Ρ‚Π΅ Π½Π΅ΠΊΠ°Π΄Π΅, Π΄Π° Π³ΠΎ Ρ‚Π°ΠΌΠΏΠΎΠ½ΠΈΡ€Π°Ρ‚Π΅ ΠΈ Π΄Π° Π³ΠΎ прСнСсСтС Π½Π° Π΄Π΅Π»ΠΎΠ²ΠΈ. НСобработСниот Π²ΠΈΠ΄Π΅ΠΎ ΠΏΠΎΡ‚ΠΎΠΊ Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° сС прСнСсС ΠΏΡ€Π΅ΠΊΡƒ Π²Π΅Π±-сокСти. Π’ΡƒΠΊΠ° Π½ΠΈ Π΄ΠΎΠ°Ρ“Π° Π½Π° помош 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>

Π‘Ρ‚Ρ€Π°Π½Π°Ρ‚Π° Π½Π° Π΅ΠΌΠΈΡ‚ΡƒΠ²Π°ΡšΠ΅ Π΅ ΠΏΠΎΠ΄Π³ΠΎΡ‚Π²Π΅Π½Π°! Π‘Π΅Π³Π° Π΄Π° сС ΠΎΠ±ΠΈΠ΄Π΅ΠΌΠ΅ Π΄Π° ΠΏΡ€ΠΈΠΌΠΈΠΌΠ΅ Π²ΠΈΠ΄Π΅ΠΎ ΠΏΠΎΡ‚ΠΎΠΊ ΠΈ Π΄Π° Π³ΠΎ ΠΏΡ€ΠΈΠΊΠ°ΠΆΠ΅ΠΌΠ΅ Π½Π° ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΎΡ‚. Π¨Ρ‚ΠΎ Π½ΠΈ Ρ‚Ρ€Π΅Π±Π° Π·Π° ΠΎΠ²Π°? ΠŸΡ€Π²ΠΎ, сС Ρ€Π°Π·Π±ΠΈΡ€Π°, ΠΏΡ€ΠΈΠΊΠ»ΡƒΡ‡ΠΎΠΊΠΎΡ‚ Π·Π° ΡˆΡ‚Π΅ΠΊΠ΅Ρ€. ΠŸΡ€ΠΈΠΊΠ°Ρ‡ΡƒΠ²Π°ΠΌΠ΅ β€žΡΠ»ΡƒΡˆΠ°Ρ‚Π΅Π»β€œ Π½Π° ΠΎΠ±Ρ˜Π΅ΠΊΡ‚ΠΎΡ‚ 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 API ΠΈ FileReader API.

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; Π½ΠΈΠ΅ самитС Π³ΠΎ поставувамС ΠΎΠ²Π° ΠΊΠΎΠ³Π° Π³ΠΎ Π΄Π΅Π»ΠΈΠΌΠ΅ Π²ΠΈΠ΄Π΅ΠΎ-стримот ΠΏΡ€Π΅Π΄ Π΄Π° Π³ΠΎ прСнСсСмС Π½Π° сСрвСрот. ΠŸΠΎΠΊΡ€Π°Ρ˜ Ρ‚ΠΎΠ°, ΠΊΠΎΠ³Π° Π³ΠΎ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΠ² ΠΌΠΎΡ˜ΠΎΡ‚ Π»Π°ΠΏΡ‚ΠΎΠΏ, постСпСно сС Π°ΠΊΡƒΠΌΡƒΠ»ΠΈΡ€Π°ΡˆΠ΅ Π·Π°ΠΎΡΡ‚Π°Π½ΡƒΠ²Π°ΡšΠ΅Ρ‚ΠΎ ΠΏΠΎΠΌΠ΅Ρ“Ρƒ странитС Π·Π° прСнос ΠΈ ΠΏΡ€ΠΈΠΌΠ°ΡšΠ΅, ΠΎΠ²Π° бСшС јасно Π²ΠΈΠ΄Π»ΠΈΠ²ΠΎ. ΠŸΠΎΡ‡Π½Π°Π² Π΄Π° Π±Π°Ρ€Π°ΠΌ Π½Π°Ρ‡ΠΈΠ½ΠΈ Π΄Π° Π³ΠΎ Π½Π°Π΄ΠΌΠΈΠ½Π°ΠΌ овој нСдостаток ΠΈ... Π½Π°ΠΈΠ΄ΠΎΠ² RTCPeerConnection API, кој Π²ΠΈ ΠΎΠ²ΠΎΠ·ΠΌΠΎΠΆΡƒΠ²Π° Π΄Π° прСнСсуватС Π²ΠΈΠ΄Π΅ΠΎ стрим Π±Π΅Π· Ρ‚Ρ€ΠΈΠΊΠΎΠ²ΠΈ ΠΊΠ°ΠΊΠΎ ΡˆΡ‚ΠΎ сС дСлСњС Π½Π° прСносот Π½Π° ΠΏΠ°Ρ€Ρ‡ΠΈΡšΠ°. Акумулирачкото Π·Π°Π΄ΠΎΡ†Π½ΡƒΠ²Π°ΡšΠ΅, мислам, сС Π΄ΠΎΠ»ΠΆΠΈ Π½Π° Ρ„Π°ΠΊΡ‚ΠΎΡ‚ ΡˆΡ‚ΠΎ прСлистувачот ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ Π³ΠΎ ΠΊΠΎΠ΄ΠΈΡ€Π° сСкоС ΠΏΠ°Ρ€Ρ‡Π΅ Π²ΠΎ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Π²Π΅Π±-ΠΌ ΠΏΡ€Π΅Π΄ прСносот. НС ΠΊΠΎΠΏΠ°Π² повСќС, Ρ‚ΡƒΠΊΡƒ ΠΏΠΎΡ‡Π½Π°Π² Π΄Π° Π³ΠΎ ΠΏΡ€ΠΎΡƒΡ‡ΡƒΠ²Π°ΠΌ WebRTC. Мислам Π΄Π΅ΠΊΠ° ќС напишам посСбна ΡΡ‚Π°Ρ‚ΠΈΡ˜Π° Π·Π° Ρ€Π΅Π·ΡƒΠ»Ρ‚Π°Ρ‚ΠΈΡ‚Π΅ ΠΎΠ΄ ΠΌΠΎΠ΅Ρ‚ΠΎ ΠΈΡΡ‚Ρ€Π°ΠΆΡƒΠ²Π°ΡšΠ΅ Π΄ΠΎΠΊΠΎΠ»ΠΊΡƒ смСтам Π΄Π΅ΠΊΠ° Π΅ интСрСсно Π·Π° Π·Π°Π΅Π΄Π½ΠΈΡ†Π°Ρ‚Π°.

Π˜Π·Π²ΠΎΡ€: www.habr.com

Π”ΠΎΠ΄Π°Π΄Π΅Ρ‚Π΅ ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€