āĻāĻ āĻ¨āĻŋāĻŦāĻ¨ā§āĻ§ā§ āĻāĻŽāĻŋ āĻ
ā§āĻ¯āĻžāĻĄā§āĻŦ āĻĢā§āĻ˛ā§āĻ¯āĻžāĻļ āĻĒā§āĻ˛ā§āĻ¯āĻŧāĻžāĻ°ā§āĻ° āĻŽāĻ¤ā§ āĻ¤ā§āĻ¤ā§āĻ¯āĻŧ āĻĒāĻā§āĻˇā§āĻ° āĻŦā§āĻ°āĻžāĻāĻāĻžāĻ° āĻĒā§āĻ˛āĻžāĻāĻāĻ¨āĻā§āĻ˛āĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ¨āĻž āĻāĻ°ā§ āĻāĻ¯āĻŧā§āĻŦāĻ¸āĻā§āĻā§āĻ° āĻŽāĻžāĻ§ā§āĻ¯āĻŽā§ āĻāĻŋāĻĄāĻŋāĻ āĻ¸ā§āĻā§āĻ°āĻŋāĻŽ āĻāĻ°āĻžāĻ° āĻāĻŽāĻžāĻ° āĻĒā§āĻ°āĻā§āĻˇā§āĻāĻžāĻā§āĻ˛āĻŋ āĻāĻžāĻ āĻāĻ°āĻ¤ā§ āĻāĻžāĻā§ˇ āĻāĻ° āĻĨā§āĻā§ āĻā§ āĻāĻ¸ā§āĻā§ āĻ¤āĻž āĻāĻžāĻ¨āĻ¤ā§ āĻĒāĻĄāĻŧā§āĻ¨āĨ¤
āĻ
ā§āĻ¯āĻžāĻĄā§āĻŦ āĻĢā§āĻ˛ā§āĻ¯āĻžāĻļ, āĻĒā§āĻ°ā§āĻŦā§ āĻŽā§āĻ¯āĻžāĻā§āĻ°ā§āĻŽāĻŋāĻĄāĻŋāĻ¯āĻŧāĻž āĻĢā§āĻ˛ā§āĻ¯āĻžāĻļ, āĻāĻāĻāĻŋ āĻāĻ¯āĻŧā§āĻŦ āĻŦā§āĻ°āĻžāĻāĻāĻžāĻ°ā§ āĻāĻžāĻ˛āĻŋāĻ¤ āĻ
ā§āĻ¯āĻžāĻĒā§āĻ˛āĻŋāĻā§āĻļāĻ¨ āĻ¤ā§āĻ°āĻŋāĻ° āĻāĻāĻāĻŋ āĻĒā§āĻ˛ā§āĻ¯āĻžāĻāĻĢāĻ°ā§āĻŽāĨ¤ āĻŽāĻŋāĻĄāĻŋāĻ¯āĻŧāĻž āĻ¸ā§āĻā§āĻ°āĻŋāĻŽ āĻāĻĒāĻŋāĻāĻ āĻĒā§āĻ°āĻŦāĻ°ā§āĻ¤āĻ¨ā§āĻ° āĻāĻā§, āĻāĻāĻŋ āĻāĻāĻāĻŋ āĻāĻ¯āĻŧā§āĻŦāĻā§āĻ¯āĻžāĻŽ āĻĨā§āĻā§ āĻāĻŋāĻĄāĻŋāĻ āĻāĻŦāĻ āĻāĻ¯āĻŧā§āĻ¸ āĻ¸ā§āĻā§āĻ°āĻŋāĻŽ āĻāĻ°āĻžāĻ° āĻĒāĻžāĻļāĻžāĻĒāĻžāĻļāĻŋ āĻŦā§āĻ°āĻžāĻāĻāĻžāĻ°ā§ āĻŦāĻŋāĻāĻŋāĻ¨ā§āĻ¨ āĻ§āĻ°āĻŖā§āĻ° āĻ¸āĻŽā§āĻŽā§āĻ˛āĻ¨ āĻāĻŦāĻ āĻā§āĻ¯āĻžāĻ āĻ¤ā§āĻ°āĻŋ āĻāĻ°āĻžāĻ° āĻāĻ¨ā§āĻ¯ āĻāĻžāĻ°ā§āĻ¯āĻ¤ āĻāĻāĻŽāĻžāĻ¤ā§āĻ° āĻĒā§āĻ˛ā§āĻ¯āĻžāĻāĻĢāĻ°ā§āĻŽ āĻāĻŋāĻ˛āĨ¤ āĻŽāĻŋāĻĄāĻŋāĻ¯āĻŧāĻž āĻ¤āĻĨā§āĻ¯ RTMP (āĻ°āĻŋāĻ¯āĻŧā§āĻ˛ āĻāĻžāĻāĻŽ āĻŽā§āĻ¸ā§āĻāĻŋāĻ āĻĒā§āĻ°ā§āĻā§āĻāĻ˛) āĻĒā§āĻ°ā§āĻ°āĻŖā§āĻ° āĻāĻ¨ā§āĻ¯ āĻĒā§āĻ°ā§āĻā§āĻāĻ˛āĻāĻŋ āĻāĻ¸āĻ˛ā§ āĻĻā§āĻ°ā§āĻ āĻ¸āĻŽāĻ¯āĻŧā§āĻ° āĻāĻ¨ā§āĻ¯ āĻŦāĻ¨ā§āĻ§ āĻāĻŋāĻ˛, āĻ¯āĻžāĻ° āĻ
āĻ°ā§āĻĨ āĻāĻŋāĻ˛: āĻāĻĒāĻ¨āĻŋ āĻ¯āĻĻāĻŋ āĻāĻĒāĻ¨āĻžāĻ° āĻ¸ā§āĻā§āĻ°āĻŋāĻŽāĻŋāĻ āĻĒāĻ°āĻŋāĻˇā§āĻŦāĻžāĻā§ āĻŦā§āĻ¸ā§āĻ āĻāĻ°āĻ¤ā§ āĻāĻžāĻ¨, āĻ¤āĻžāĻšāĻ˛ā§ 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() āĻāĻāĻāĻŋ āĻĒā§āĻ°āĻ¤āĻŋāĻļā§āĻ°ā§āĻ¤āĻŋ āĻĒā§āĻ°āĻĻāĻžāĻ¨ āĻāĻ°ā§, āĻ¯ā§āĻāĻžāĻ¨ā§ āĻāĻāĻŋ āĻāĻāĻāĻŋ āĻŽāĻŋāĻĄāĻŋāĻ¯āĻŧāĻžāĻ¸ā§āĻā§āĻ°āĻŋāĻŽ āĻ āĻŦāĻā§āĻā§āĻ āĻĒāĻžāĻ¸ āĻāĻ°ā§ - āĻāĻŋāĻĄāĻŋāĻ-āĻ āĻĄāĻŋāĻ āĻĄā§āĻāĻžāĻ° āĻāĻāĻāĻŋ āĻ¸ā§āĻā§āĻ°ā§āĻŽāĨ¤ āĻāĻŽāĻ°āĻž āĻāĻ āĻ āĻŦāĻā§āĻā§āĻāĻāĻŋāĻā§ āĻāĻŋāĻĄāĻŋāĻ āĻāĻĒāĻžāĻĻāĻžāĻ¨ā§āĻ° 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>
āĻāĻāĻāĻŋ āĻĻā§āĻ°ā§āĻ āĻ¸āĻŽāĻ¯āĻŧā§āĻ° āĻāĻ¨ā§āĻ¯ āĻāĻŽāĻŋ āĻŦā§āĻāĻžāĻ° āĻā§āĻˇā§āĻāĻž āĻāĻ°ā§āĻāĻŋ āĻā§āĻ¨ āĻ
āĻŦāĻŋāĻ˛āĻŽā§āĻŦā§ āĻĒā§āĻ°āĻžāĻĒā§āĻ¤ āĻā§āĻāĻ°ā§āĻā§āĻ˛āĻŋ āĻĒā§āĻ˛ā§āĻŦā§āĻ¯āĻžāĻā§āĻ° āĻāĻ¨ā§āĻ¯ āĻāĻŋāĻĄāĻŋāĻ āĻāĻĒāĻžāĻĻāĻžāĻ¨āĻāĻŋāĻ¤ā§ āĻĒā§āĻ°ā§āĻ°āĻŖ āĻāĻ°āĻž āĻ
āĻ¸āĻŽā§āĻāĻŦ, āĻ¤āĻŦā§ āĻĻā§āĻāĻž āĻā§āĻ˛ āĻ¯ā§ āĻāĻāĻŋ āĻāĻ°āĻž āĻ¯āĻžāĻŦā§ āĻ¨āĻž, āĻ
āĻŦāĻļā§āĻ¯āĻ, āĻāĻĒāĻ¨āĻžāĻā§ āĻĒā§āĻ°āĻĨāĻŽā§ āĻā§āĻāĻ°ā§āĻāĻŋāĻā§ āĻāĻāĻāĻŋ āĻŦāĻŋāĻļā§āĻˇ āĻŦāĻžāĻĢāĻžāĻ°ā§ āĻāĻŦāĻĻā§āĻ§ āĻ°āĻžāĻāĻ¤ā§ āĻšāĻŦā§āĨ¤ āĻāĻŋāĻĄāĻŋāĻ āĻāĻĒāĻžāĻĻāĻžāĻ¨, āĻāĻŦāĻ āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° āĻ¤āĻžāĻ°āĻĒāĻ° āĻāĻāĻŋ āĻāĻŋāĻĄāĻŋāĻ āĻ¸ā§āĻā§āĻ°āĻŋāĻŽ āĻŦāĻžāĻāĻžāĻ¨ā§ āĻļā§āĻ°ā§ āĻšāĻŦā§. āĻāĻ āĻāĻ¨ā§āĻ¯ āĻāĻĒāĻ¨āĻžāĻ° āĻĒā§āĻ°āĻ¯āĻŧā§āĻāĻ¨ āĻšāĻŦā§
āĻŽāĻŋāĻĄāĻŋāĻ¯āĻŧāĻžāĻ¸ā§āĻ°ā§āĻ¸ āĻŽāĻŋāĻĄāĻŋāĻ¯āĻŧāĻž āĻĒā§āĻ˛ā§āĻŦā§āĻ¯āĻžāĻ āĻ āĻŦāĻā§āĻā§āĻ āĻāĻŦāĻ āĻāĻ āĻŽāĻŋāĻĄāĻŋāĻ¯āĻŧāĻž āĻ¸ā§āĻā§āĻ°āĻŋāĻŽā§āĻ° āĻāĻ¤ā§āĻ¸ā§āĻ° āĻŽāĻ§ā§āĻ¯ā§ āĻāĻ āĻ§āĻ°āĻŖā§āĻ° āĻŽāĻ§ā§āĻ¯āĻ¸ā§āĻĨāĻ¤āĻžāĻāĻžāĻ°ā§ āĻšāĻŋāĻ¸āĻžāĻŦā§ āĻāĻžāĻ āĻāĻ°ā§āĨ¤ āĻŽāĻŋāĻĄāĻŋāĻ¯āĻŧāĻžāĻ¸ā§āĻ°ā§āĻ¸ āĻ āĻŦāĻā§āĻā§āĻāĻāĻŋāĻ¤ā§ āĻāĻŋāĻĄāĻŋāĻ/āĻ āĻĄāĻŋāĻ āĻ¸ā§āĻā§āĻ°āĻŋāĻŽā§āĻ° āĻā§āĻ¸ā§āĻ° āĻāĻ¨ā§āĻ¯ āĻāĻāĻāĻŋ āĻĒā§āĻ˛āĻžāĻāĻ¯ā§āĻā§āĻ¯ āĻŦāĻžāĻĢāĻžāĻ° āĻ°āĻ¯āĻŧā§āĻā§āĨ¤ āĻāĻāĻāĻŋ āĻŦā§āĻļāĻŋāĻˇā§āĻā§āĻ¯ āĻšāĻ˛ āĻŦāĻžāĻĢāĻžāĻ°āĻāĻŋ āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° 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