(āĻĒā§āĻ°āĻžāĻ¯āĻŧ) āĻāĻ•āĻŸāĻŋ āĻŦā§āĻ°āĻžāĻ‰āĻœāĻžāĻ° āĻĨā§‡āĻ•ā§‡ āĻ…āĻ•ā§‡āĻœā§‹ āĻ“āĻ¯āĻŧā§‡āĻŦāĻ•ā§āĻ¯āĻžāĻŽ āĻ¸ā§āĻŸā§āĻ°āĻŋāĻŽāĻŋāĻ‚āĨ¤ āĻŽāĻŋāĻĄāĻŋāĻ¯āĻŧāĻž āĻ¸ā§āĻŸā§āĻ°āĻŋāĻŽ āĻāĻŦāĻ‚ āĻ“āĻ¯āĻŧā§‡āĻŦāĻ¸āĻ•ā§‡āĻŸ

āĻāĻ‡ āĻ¨āĻŋāĻŦāĻ¨ā§āĻ§ā§‡ āĻ†āĻŽāĻŋ āĻ…ā§āĻ¯āĻžāĻĄā§‹āĻŦ āĻĢā§āĻ˛ā§āĻ¯āĻžāĻļ āĻĒā§āĻ˛ā§‡āĻ¯āĻŧāĻžāĻ°ā§‡āĻ° āĻŽāĻ¤ā§‹ āĻ¤ā§ƒāĻ¤ā§€āĻ¯āĻŧ āĻĒāĻ•ā§āĻˇā§‡āĻ° āĻŦā§āĻ°āĻžāĻ‰āĻœāĻžāĻ° āĻĒā§āĻ˛āĻžāĻ—āĻ‡āĻ¨āĻ—ā§āĻ˛āĻŋ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ¨āĻž āĻ•āĻ°ā§‡ āĻ“āĻ¯āĻŧā§‡āĻŦāĻ¸āĻ•ā§‡āĻŸā§‡āĻ° āĻŽāĻžāĻ§ā§āĻ¯āĻŽā§‡ āĻ­āĻŋāĻĄāĻŋāĻ“ āĻ¸ā§āĻŸā§āĻ°āĻŋāĻŽ āĻ•āĻ°āĻžāĻ° āĻ†āĻŽāĻžāĻ° āĻĒā§āĻ°āĻšā§‡āĻˇā§āĻŸāĻžāĻ—ā§āĻ˛āĻŋ āĻ­āĻžāĻ— āĻ•āĻ°āĻ¤ā§‡ āĻšāĻžāĻ‡ā§ˇ āĻāĻ° āĻĨā§‡āĻ•ā§‡ āĻ•ā§€ āĻāĻ¸ā§‡āĻ›ā§‡ āĻ¤āĻž āĻœāĻžāĻ¨āĻ¤ā§‡ āĻĒāĻĄāĻŧā§āĻ¨āĨ¤

āĻ…ā§āĻ¯āĻžāĻĄā§‹āĻŦ āĻĢā§āĻ˛ā§āĻ¯āĻžāĻļ, āĻĒā§‚āĻ°ā§āĻŦā§‡ āĻŽā§āĻ¯āĻžāĻ•ā§āĻ°ā§‹āĻŽāĻŋāĻĄāĻŋāĻ¯āĻŧāĻž āĻĢā§āĻ˛ā§āĻ¯āĻžāĻļ, āĻāĻ•āĻŸāĻŋ āĻ“āĻ¯āĻŧā§‡āĻŦ āĻŦā§āĻ°āĻžāĻ‰āĻœāĻžāĻ°ā§‡ āĻšāĻžāĻ˛āĻŋāĻ¤ āĻ…ā§āĻ¯āĻžāĻĒā§āĻ˛āĻŋāĻ•ā§‡āĻļāĻ¨ āĻ¤ā§ˆāĻ°āĻŋāĻ° āĻāĻ•āĻŸāĻŋ āĻĒā§āĻ˛ā§āĻ¯āĻžāĻŸāĻĢāĻ°ā§āĻŽāĨ¤ āĻŽāĻŋāĻĄāĻŋāĻ¯āĻŧāĻž āĻ¸ā§āĻŸā§āĻ°āĻŋāĻŽ āĻāĻĒāĻŋāĻ†āĻ‡ āĻĒā§āĻ°āĻŦāĻ°ā§āĻ¤āĻ¨ā§‡āĻ° āĻ†āĻ—ā§‡, āĻāĻŸāĻŋ āĻāĻ•āĻŸāĻŋ āĻ“āĻ¯āĻŧā§‡āĻŦāĻ•ā§āĻ¯āĻžāĻŽ āĻĨā§‡āĻ•ā§‡ āĻ­āĻŋāĻĄāĻŋāĻ“ āĻāĻŦāĻ‚ āĻ­āĻ¯āĻŧā§‡āĻ¸ āĻ¸ā§āĻŸā§āĻ°āĻŋāĻŽ āĻ•āĻ°āĻžāĻ° āĻĒāĻžāĻļāĻžāĻĒāĻžāĻļāĻŋ āĻŦā§āĻ°āĻžāĻ‰āĻœāĻžāĻ°ā§‡ āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āĻ¨ āĻ§āĻ°āĻŖā§‡āĻ° āĻ¸āĻŽā§āĻŽā§‡āĻ˛āĻ¨ āĻāĻŦāĻ‚ āĻšā§āĻ¯āĻžāĻŸ āĻ¤ā§ˆāĻ°āĻŋ āĻ•āĻ°āĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻ•āĻžāĻ°ā§āĻ¯āĻ¤ āĻāĻ•āĻŽāĻžāĻ¤ā§āĻ° āĻĒā§āĻ˛ā§āĻ¯āĻžāĻŸāĻĢāĻ°ā§āĻŽ āĻ›āĻŋāĻ˛āĨ¤ āĻŽāĻŋāĻĄāĻŋāĻ¯āĻŧāĻž āĻ¤āĻĨā§āĻ¯ RTMP (āĻ°āĻŋāĻ¯āĻŧā§‡āĻ˛ āĻŸāĻžāĻ‡āĻŽ āĻŽā§‡āĻ¸ā§‡āĻœāĻŋāĻ‚ āĻĒā§āĻ°ā§‹āĻŸā§‹āĻ•āĻ˛) āĻĒā§āĻ°ā§‡āĻ°āĻŖā§‡āĻ° āĻœāĻ¨ā§āĻ¯ āĻĒā§āĻ°ā§‹āĻŸā§‹āĻ•āĻ˛āĻŸāĻŋ āĻ†āĻ¸āĻ˛ā§‡ āĻĻā§€āĻ°ā§āĻ˜ āĻ¸āĻŽāĻ¯āĻŧā§‡āĻ° āĻœāĻ¨ā§āĻ¯ āĻŦāĻ¨ā§āĻ§ āĻ›āĻŋāĻ˛, āĻ¯āĻžāĻ° āĻ…āĻ°ā§āĻĨ āĻ›āĻŋāĻ˛: āĻ†āĻĒāĻ¨āĻŋ āĻ¯āĻĻāĻŋ āĻ†āĻĒāĻ¨āĻžāĻ° āĻ¸ā§āĻŸā§āĻ°āĻŋāĻŽāĻŋāĻ‚ āĻĒāĻ°āĻŋāĻˇā§‡āĻŦāĻžāĻ•ā§‡ āĻŦā§āĻ¸ā§āĻŸ āĻ•āĻ°āĻ¤ā§‡ āĻšāĻžāĻ¨, āĻ¤āĻžāĻšāĻ˛ā§‡ Adobe āĻĨā§‡āĻ•ā§‡ āĻ¸āĻĢā§āĻŸāĻ“āĻ¯āĻŧā§āĻ¯āĻžāĻ° āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ•āĻ°āĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻ¯āĻĨā§‡āĻˇā§āĻŸ āĻ¸āĻĻāĻ¯āĻŧ āĻšā§‹āĻ¨ - Adobe Media Server (AMS)ā§ˇ

2012 āĻ¸āĻžāĻ˛ā§‡ āĻ•āĻŋāĻ›ā§ āĻ¸āĻŽāĻ¯āĻŧ āĻĒāĻ°ā§‡, Adobe āĻœāĻ¨āĻ¸āĻžāĻ§āĻžāĻ°āĻŖā§‡āĻ° āĻ•āĻžāĻ›ā§‡ "āĻ¤ā§āĻ¯āĻžāĻ— āĻ•āĻ°ā§‡ āĻāĻŦāĻ‚ āĻĨā§āĻĨā§ āĻĻā§‡āĻ¯āĻŧ"āĨ¤ āĻ¸ā§āĻĒā§‡āĻ¸āĻŋāĻĢāĻŋāĻ•ā§‡āĻļāĻ¨ RTMP āĻĒā§āĻ°ā§‹āĻŸā§‹āĻ•āĻ˛, āĻ¯āĻžāĻ¤ā§‡ āĻ¤ā§āĻ°ā§āĻŸāĻŋ āĻ›āĻŋāĻ˛ āĻāĻŦāĻ‚ āĻāĻŸāĻŋ āĻŽā§‚āĻ˛āĻ¤ āĻ…āĻ¸āĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āĻ›āĻŋāĻ˛āĨ¤ āĻ¤āĻ¤āĻ•ā§āĻˇāĻŖā§‡, āĻŦāĻŋāĻ•āĻžāĻļāĻ•āĻžāĻ°ā§€āĻ°āĻž āĻāĻ‡ āĻĒā§āĻ°ā§‹āĻŸā§‹āĻ•āĻ˛ā§‡āĻ° āĻ¨āĻŋāĻœāĻ¸ā§āĻŦ āĻŦāĻžāĻ¸ā§āĻ¤āĻŦāĻžāĻ¯āĻŧāĻ¨ āĻ•āĻ°āĻ¤ā§‡ āĻļā§āĻ°ā§ āĻ•āĻ°ā§‡ āĻāĻŦāĻ‚ Wowza āĻ¸āĻžāĻ°ā§āĻ­āĻžāĻ° āĻ‰āĻĒāĻ¸ā§āĻĨāĻŋāĻ¤ āĻšāĻ¯āĻŧā§‡āĻ›āĻŋāĻ˛āĨ¤ 2011 āĻ¸āĻžāĻ˛ā§‡, Adobe RTMP-āĻ¸āĻŽā§āĻĒāĻ°ā§āĻ•āĻŋāĻ¤ āĻĒā§‡āĻŸā§‡āĻ¨ā§āĻŸā§‡āĻ° āĻ…āĻŦā§ˆāĻ§ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ°ā§‡āĻ° āĻœāĻ¨ā§āĻ¯ Wowza āĻāĻ° āĻŦāĻŋāĻ°ā§āĻĻā§āĻ§ā§‡ āĻāĻ•āĻŸāĻŋ āĻŽāĻžāĻŽāĻ˛āĻž āĻĻāĻžāĻ¯āĻŧā§‡āĻ° āĻ•āĻ°ā§‡; 4 āĻŦāĻ›āĻ° āĻĒāĻ°, āĻŦāĻŋāĻ°ā§‹āĻ§āĻŸāĻŋ āĻŦāĻ¨ā§āĻ§ā§āĻ¤ā§āĻŦāĻĒā§‚āĻ°ā§āĻŖāĻ­āĻžāĻŦā§‡ āĻ¸āĻŽāĻžāĻ§āĻžāĻ¨ āĻ•āĻ°āĻž āĻšāĻ¯āĻŧā§‡āĻ›āĻŋāĻ˛āĨ¤

āĻ…ā§āĻ¯āĻžāĻĄā§‹āĻŦ āĻĢā§āĻ˛ā§āĻ¯āĻžāĻļ āĻĒā§āĻ˛ā§āĻ¯āĻžāĻŸāĻĢāĻ°ā§āĻŽāĻŸāĻŋ 20 āĻŦāĻ›āĻ°ā§‡āĻ°āĻ“ āĻŦā§‡āĻļāĻŋ āĻĒā§āĻ°āĻžāĻ¨ā§‹, āĻāĻ‡ āĻ¸āĻŽāĻ¯āĻŧā§‡ āĻ…āĻ¨ā§‡āĻ•āĻ—ā§āĻ˛āĻŋ āĻœāĻŸāĻŋāĻ˛ āĻĻā§āĻ°ā§āĻŦāĻ˛āĻ¤āĻž āĻ†āĻŦāĻŋāĻˇā§āĻ•ā§ƒāĻ¤ āĻšāĻ¯āĻŧā§‡āĻ›ā§‡, āĻ¸āĻŽāĻ°ā§āĻĨāĻ¨ āĻĒā§āĻ°āĻ¤āĻŋāĻļā§āĻ°ā§āĻ¤āĻŋāĻŦāĻĻā§āĻ§ 2020 āĻ¸āĻžāĻ˛ā§‡āĻ° āĻŽāĻ§ā§āĻ¯ā§‡ āĻļā§‡āĻˇ āĻšāĻŦā§‡, āĻ¸ā§āĻŸā§āĻ°āĻŋāĻŽāĻŋāĻ‚ āĻĒāĻ°āĻŋāĻˇā§‡āĻŦāĻžāĻ° āĻœāĻ¨ā§āĻ¯ āĻ•āĻ¯āĻŧā§‡āĻ•āĻŸāĻŋ āĻŦāĻŋāĻ•āĻ˛ā§āĻĒ āĻ°ā§‡āĻ–ā§‡āĨ¤

āĻ†āĻŽāĻžāĻ° āĻĒā§āĻ°āĻ•āĻ˛ā§āĻĒā§‡āĻ° āĻœāĻ¨ā§āĻ¯, āĻ†āĻŽāĻŋ āĻ…āĻŦāĻŋāĻ˛āĻŽā§āĻŦā§‡ āĻŦā§āĻ°āĻžāĻ‰āĻœāĻžāĻ°ā§‡ āĻĢā§āĻ˛ā§āĻ¯āĻžāĻļ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ° āĻ¸āĻŽā§āĻĒā§‚āĻ°ā§āĻŖāĻ°ā§‚āĻĒā§‡ āĻĒāĻ°āĻŋāĻ¤ā§āĻ¯āĻžāĻ— āĻ•āĻ°āĻžāĻ° āĻ¸āĻŋāĻĻā§āĻ§āĻžāĻ¨ā§āĻ¤ āĻ¨āĻŋāĻ¯āĻŧā§‡āĻ›āĻŋāĨ¤ āĻ†āĻŽāĻŋ āĻ‰āĻĒāĻ°ā§‡ āĻĒā§āĻ°āĻ§āĻžāĻ¨ āĻ•āĻžāĻ°āĻŖ āĻ¨āĻŋāĻ°ā§āĻĻā§‡āĻļ āĻ•āĻ°ā§‡āĻ›āĻŋ; āĻŽā§‹āĻŦāĻžāĻ‡āĻ˛ āĻĒā§āĻ˛ā§āĻ¯āĻžāĻŸāĻĢāĻ°ā§āĻŽā§‡ āĻĢā§āĻ˛ā§āĻ¯āĻžāĻļāĻ“ āĻ¸āĻŽāĻ°ā§āĻĨāĻŋāĻ¤ āĻ¨āĻ¯āĻŧ, āĻāĻŦāĻ‚ āĻ†āĻŽāĻŋ āĻ¸āĻ¤ā§āĻ¯āĻŋāĻ‡ āĻ‰āĻ‡āĻ¨ā§āĻĄā§‹āĻœ (āĻ“āĻ¯āĻŧāĻžāĻ‡āĻ¨ āĻāĻŽā§āĻ˛ā§‡āĻŸāĻ°) āĻŦāĻŋāĻ•āĻžāĻļā§‡āĻ° āĻœāĻ¨ā§āĻ¯ āĻ…ā§āĻ¯āĻžāĻĄā§‹āĻŦ āĻĢā§āĻ˛ā§āĻ¯āĻžāĻļ āĻ¸ā§āĻĨāĻžāĻĒāĻ¨ āĻ•āĻ°āĻ¤ā§‡ āĻšāĻžāĻ‡āĻ¨āĻŋāĨ¤ āĻ¤āĻžāĻ‡ āĻ†āĻŽāĻŋ āĻœāĻžāĻ­āĻžāĻ¸ā§āĻ•ā§āĻ°āĻŋāĻĒā§āĻŸā§‡ āĻāĻ•āĻŸāĻŋ āĻ•ā§āĻ˛āĻžāĻ¯āĻŧā§‡āĻ¨ā§āĻŸ āĻ˛āĻŋāĻ–āĻ¤ā§‡ āĻ¸ā§‡āĻŸ āĻ†āĻ‰āĻŸ. āĻāĻŸāĻŋ āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° āĻāĻ•āĻŸāĻŋ āĻĒā§āĻ°ā§‹āĻŸā§‹āĻŸāĻžāĻ‡āĻĒ āĻšāĻŦā§‡, āĻ¯ā§‡āĻšā§‡āĻ¤ā§ āĻĒāĻ°ā§‡ āĻ†āĻŽāĻŋ āĻļāĻŋāĻ–ā§‡āĻ›āĻŋ āĻ¯ā§‡ 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)
}

āĻ•ā§āĻ˛āĻžāĻ¯āĻŧā§‡āĻ¨ā§āĻŸā§‡ (āĻ¸ā§āĻŸā§āĻ°āĻŋāĻŽāĻŋāĻ‚ āĻ¸āĻžāĻ‡āĻĄ), āĻ†āĻĒāĻ¨āĻžāĻ•ā§‡ āĻĒā§āĻ°āĻĨāĻŽā§‡ āĻ•ā§āĻ¯āĻžāĻŽā§‡āĻ°āĻž āĻ…ā§āĻ¯āĻžāĻ•ā§āĻ¸ā§‡āĻ¸ āĻ•āĻ°āĻ¤ā§‡ āĻšāĻŦā§‡āĨ¤ āĻāĻ‡ āĻŽāĻžāĻ§ā§āĻ¯āĻŽā§‡ āĻ•āĻ°āĻž āĻšāĻ¯āĻŧ āĻŽāĻŋāĻĄāĻŋāĻ¯āĻŧāĻžāĻ¸ā§āĻŸā§āĻ°āĻŋāĻŽ API.

āĻ†āĻŽāĻ°āĻž āĻāĻ° āĻŽāĻžāĻ§ā§āĻ¯āĻŽā§‡ āĻ•ā§āĻ¯āĻžāĻŽā§‡āĻ°āĻž/āĻŽāĻžāĻ‡āĻ•ā§āĻ°ā§‹āĻĢā§‹āĻ¨ā§‡ āĻ…ā§āĻ¯āĻžāĻ•ā§āĻ¸ā§‡āĻ¸ (āĻ…āĻ¨ā§āĻŽāĻ¤āĻŋ) āĻ˛āĻžāĻ­ āĻ•āĻ°āĻŋ āĻŽāĻŋāĻĄāĻŋāĻ¯āĻŧāĻž āĻĄāĻŋāĻ­āĻžāĻ‡āĻ¸ API. āĻāĻ‡ API āĻāĻ•āĻŸāĻŋ āĻĒāĻĻā§āĻ§āĻ¤āĻŋ āĻĒā§āĻ°āĻĻāĻžāĻ¨ āĻ•āĻ°ā§‡ MediaDevices.getUserMedia(), āĻ¯āĻž āĻĒāĻĒāĻ†āĻĒ āĻĻā§‡āĻ–āĻžāĻ¯āĻŧāĨ¤ āĻāĻ•āĻŸāĻŋ āĻ‰āĻ‡āĻ¨ā§āĻĄā§‹ āĻŦā§āĻ¯āĻŦāĻšāĻžāĻ°āĻ•āĻžāĻ°ā§€āĻ•ā§‡ āĻ•ā§āĻ¯āĻžāĻŽā§‡āĻ°āĻž āĻāĻŦāĻ‚/āĻ…āĻĨāĻŦāĻž āĻŽāĻžāĻ‡āĻ•ā§āĻ°ā§‹āĻĢā§‹āĻ¨ āĻ…ā§āĻ¯āĻžāĻ•ā§āĻ¸ā§‡āĻ¸ āĻ•āĻ°āĻžāĻ° āĻ…āĻ¨ā§āĻŽāĻ¤āĻŋ āĻšāĻžāĻšā§āĻ›ā§‡āĨ¤ āĻ†āĻŽāĻŋ āĻ¨ā§‹āĻŸ āĻ•āĻ°āĻ¤ā§‡ āĻšāĻžāĻ‡ āĻ¯ā§‡ āĻ†āĻŽāĻŋ āĻ—ā§āĻ—āĻ˛ āĻ•ā§āĻ°ā§‹āĻŽā§‡ āĻ¸āĻŽāĻ¸ā§āĻ¤ āĻĒāĻ°ā§€āĻ•ā§āĻˇāĻž āĻšāĻžāĻ˛āĻŋāĻ¯āĻŧā§‡āĻ›āĻŋ, āĻ¤āĻŦā§‡ āĻ†āĻŽāĻŋ āĻŽāĻ¨ā§‡ āĻ•āĻ°āĻŋ āĻĢāĻžāĻ¯āĻŧāĻžāĻ°āĻĢāĻ•ā§āĻ¸ā§‡ āĻ¸āĻŦāĻ•āĻŋāĻ›ā§ āĻāĻ•āĻ‡ āĻ•āĻžāĻœ āĻ•āĻ°āĻŦā§‡āĨ¤

āĻāĻ°āĻĒāĻ°, 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>

āĻ¸āĻ•ā§‡āĻŸā§‡āĻ° āĻ‰āĻĒāĻ° āĻāĻ•āĻŸāĻŋ āĻ­āĻŋāĻĄāĻŋāĻ“ āĻ¸ā§āĻŸā§āĻ°āĻŋāĻŽ āĻ¸āĻŽā§āĻĒā§āĻ°āĻšāĻžāĻ° āĻ•āĻ°āĻ¤ā§‡, āĻ†āĻĒāĻ¨āĻžāĻ•ā§‡ āĻāĻŸāĻŋāĻ•ā§‡ āĻ•ā§‹āĻĨāĻžāĻ“ āĻāĻ¨āĻ•ā§‹āĻĄ āĻ•āĻ°āĻ¤ā§‡ āĻšāĻŦā§‡, āĻāĻŸāĻŋāĻ•ā§‡ āĻŦāĻžāĻĢāĻžāĻ° āĻ•āĻ°āĻ¤ā§‡ āĻšāĻŦā§‡ āĻāĻŦāĻ‚ āĻāĻŸāĻŋāĻ•ā§‡ āĻ…āĻ‚āĻļā§‡ āĻĒā§āĻ°ā§‡āĻ°āĻŖ āĻ•āĻ°āĻ¤ā§‡ āĻšāĻŦā§‡āĨ¤ āĻ•āĻžāĻāĻšāĻž āĻ­āĻŋāĻĄāĻŋāĻ“ āĻ¸ā§āĻŸā§āĻ°ā§€āĻŽ āĻ“āĻ¯āĻŧā§‡āĻŦāĻ¸āĻ•ā§‡āĻŸ āĻŽāĻžāĻ§ā§āĻ¯āĻŽā§‡ āĻĒā§āĻ°ā§‡āĻ°āĻŖ āĻ•āĻ°āĻž āĻ¯āĻžāĻŦā§‡ āĻ¨āĻž. āĻāĻ–āĻžāĻ¨ā§‡āĻ‡ āĻ†āĻŽāĻžāĻĻā§‡āĻ° āĻ¸āĻžāĻšāĻžāĻ¯ā§āĻ¯ āĻ†āĻ¸ā§‡ 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>

āĻāĻ•āĻŸāĻŋ āĻĻā§€āĻ°ā§āĻ˜ āĻ¸āĻŽāĻ¯āĻŧā§‡āĻ° āĻœāĻ¨ā§āĻ¯ āĻ†āĻŽāĻŋ āĻŦā§‹āĻāĻžāĻ° āĻšā§‡āĻˇā§āĻŸāĻž āĻ•āĻ°ā§‡āĻ›āĻŋ āĻ•ā§‡āĻ¨ āĻ…āĻŦāĻŋāĻ˛āĻŽā§āĻŦā§‡ āĻĒā§āĻ°āĻžāĻĒā§āĻ¤ āĻŸā§āĻ•āĻ°ā§‹āĻ—ā§āĻ˛āĻŋ āĻĒā§āĻ˛ā§‡āĻŦā§āĻ¯āĻžāĻ•ā§‡āĻ° āĻœāĻ¨ā§āĻ¯ āĻ­āĻŋāĻĄāĻŋāĻ“ āĻ‰āĻĒāĻžāĻĻāĻžāĻ¨āĻŸāĻŋāĻ¤ā§‡ āĻĒā§āĻ°ā§‡āĻ°āĻŖ āĻ•āĻ°āĻž āĻ…āĻ¸āĻŽā§āĻ­āĻŦ, āĻ¤āĻŦā§‡ āĻĻā§‡āĻ–āĻž āĻ—ā§‡āĻ˛ āĻ¯ā§‡ āĻāĻŸāĻŋ āĻ•āĻ°āĻž āĻ¯āĻžāĻŦā§‡ āĻ¨āĻž, āĻ…āĻŦāĻļā§āĻ¯āĻ‡, āĻ†āĻĒāĻ¨āĻžāĻ•ā§‡ āĻĒā§āĻ°āĻĨāĻŽā§‡ āĻŸā§āĻ•āĻ°ā§‹āĻŸāĻŋāĻ•ā§‡ āĻāĻ•āĻŸāĻŋ āĻŦāĻŋāĻļā§‡āĻˇ āĻŦāĻžāĻĢāĻžāĻ°ā§‡ āĻ†āĻŦāĻĻā§āĻ§ āĻ°āĻžāĻ–āĻ¤ā§‡ āĻšāĻŦā§‡āĨ¤ āĻ­āĻŋāĻĄāĻŋāĻ“ āĻ‰āĻĒāĻžāĻĻāĻžāĻ¨, āĻāĻŦāĻ‚ āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° āĻ¤āĻžāĻ°āĻĒāĻ° āĻāĻŸāĻŋ āĻ­āĻŋāĻĄāĻŋāĻ“ āĻ¸ā§āĻŸā§āĻ°āĻŋāĻŽ āĻŦāĻžāĻœāĻžāĻ¨ā§‹ āĻļā§āĻ°ā§ āĻšāĻŦā§‡. āĻāĻ‡ āĻœāĻ¨ā§āĻ¯ āĻ†āĻĒāĻ¨āĻžāĻ° āĻĒā§āĻ°āĻ¯āĻŧā§‹āĻœāĻ¨ āĻšāĻŦā§‡ āĻŽāĻŋāĻĄāĻŋāĻ¯āĻŧāĻžāĻ¸ā§‹āĻ°ā§āĻ¸ āĻāĻĒāĻŋāĻ†āĻ‡ и āĻĢāĻžāĻ‡āĻ˛āĻ°āĻŋāĻĄāĻžāĻ° API.

āĻŽāĻŋāĻĄāĻŋāĻ¯āĻŧāĻžāĻ¸ā§‹āĻ°ā§āĻ¸ āĻŽāĻŋāĻĄāĻŋāĻ¯āĻŧāĻž āĻĒā§āĻ˛ā§‡āĻŦā§āĻ¯āĻžāĻ• āĻ…āĻŦāĻœā§‡āĻ•ā§āĻŸ āĻāĻŦāĻ‚ āĻāĻ‡ āĻŽāĻŋāĻĄāĻŋāĻ¯āĻŧāĻž āĻ¸ā§āĻŸā§āĻ°āĻŋāĻŽā§‡āĻ° āĻ‰āĻ¤ā§āĻ¸ā§‡āĻ° āĻŽāĻ§ā§āĻ¯ā§‡ āĻāĻ• āĻ§āĻ°āĻŖā§‡āĻ° āĻŽāĻ§ā§āĻ¯āĻ¸ā§āĻĨāĻ¤āĻžāĻ•āĻžāĻ°ā§€ āĻšāĻŋāĻ¸āĻžāĻŦā§‡ āĻ•āĻžāĻœ āĻ•āĻ°ā§‡āĨ¤ āĻŽāĻŋāĻĄāĻŋāĻ¯āĻŧāĻžāĻ¸ā§‹āĻ°ā§āĻ¸ āĻ…āĻŦāĻœā§‡āĻ•ā§āĻŸāĻŸāĻŋāĻ¤ā§‡ āĻ­āĻŋāĻĄāĻŋāĻ“/āĻ…āĻĄāĻŋāĻ“ āĻ¸ā§āĻŸā§āĻ°āĻŋāĻŽā§‡āĻ° āĻ‰ā§ŽāĻ¸ā§‡āĻ° āĻœāĻ¨ā§āĻ¯ āĻāĻ•āĻŸāĻŋ āĻĒā§āĻ˛āĻžāĻ—āĻ¯ā§‹āĻ—ā§āĻ¯ āĻŦāĻžāĻĢāĻžāĻ° āĻ°āĻ¯āĻŧā§‡āĻ›ā§‡āĨ¤ āĻāĻ•āĻŸāĻŋ āĻŦā§ˆāĻļāĻŋāĻˇā§āĻŸā§āĻ¯ āĻšāĻ˛ āĻŦāĻžāĻĢāĻžāĻ°āĻŸāĻŋ āĻļā§āĻ§ā§āĻŽāĻžāĻ¤ā§āĻ° 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

āĻāĻ•āĻŸāĻŋ āĻŽāĻ¨ā§āĻ¤āĻŦā§āĻ¯ āĻœā§āĻĄāĻŧā§āĻ¨