рдмреИрд░реАрдореЛрд░, рд╡реЛрдХреНрд╕рд┐рдордкреНрд▓рд╛рдВрдЯ рдХреЗ рдЖрд╕рдкрд╛рд╕ рдХреНрдпрд╛ рд╣реИ? рд▓рд╛рдЧреВ рд╡реЗрдм рд╕реЙрдХреЗрдЯ, рд╕рд░


WebSocket рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдордп рдореЗрдВ рдПрдХ рдЧреНрд░рд╛рд╣рдХ рдФрд░ рдПрдХ рддреГрддреАрдп-рдкрдХреНрд╖ рд╕реЗрд╡рд╛ рдХреЗ рдмреАрдЪ рдкреВрд░реНрдг-рджреНрд╡реИрдз (рджреЛ-рддрд░рдлрд╛) рд╕рдВрдЪрд╛рд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреНрд░рдЧрддрд┐рд╢реАрд▓ рдорд╛рдирдХ рд╣реИред рд╡реЗрдм рд╕реЙрдХреЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрддрд┐рд░рд┐рдХреНрдд HTTP рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рдмрд┐рдирд╛ рдирд┐рд░рдВрддрд░ рдбреЗрдЯрд╛ рд╡рд┐рдирд┐рдордп рдХреЛ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдФрд░ рд╣рдо рдЖрдкрдХреЛ рдпрд╣ рдмрддрд╛рддреЗ рд╣реБрдП рдкреНрд░рд╕рдиреНрди рд╣реЛ рд░рд╣реЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рд╕рдм рдирдП VoxEngine рдореЙрдбреНрдпреВрд▓ рдХреЗ рд▓рд┐рдП Voximplant рдзрдиреНрдпрд╡рд╛рдж рдХреЗ рд▓рд┐рдП рд╕рдВрднрд╡ рд╣реЛ рдЧрдпрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ - рдЖрд╢реНрдЪрд░реНрдп - WebSocket ред рдЕрдм рд╕реЗ, рдЖрдк рд╡реЗрдм рд╕реЙрдХреЗрдЯреНрд╕ рдХрд╛ рдкреВрд░рд╛ рдлрд╛рдпрджрд╛ рдЙрдард╛рддреЗ рд╣реБрдП рдЯреЗрдХреНрд╕реНрдЯ рдФрд░ рдСрдбрд┐рдпреЛ рдЯреНрд░рд╛рдВрд╕рдлрд░ рдХрд░ рдкрд╛рдПрдВрдЧреЗред рд╕реАрдзреЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ рдХрд╣реЗрдВ, рдЖрдкрдХреЗ рдкрд╛рд╕ рдЕрдкрдиреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдЕрдкрдЧреНрд░реЗрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдФрд░ рдЯреВрд▓ рд╣реИред

рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рдЖрдк рд╕реАрдЦреЗрдВрдЧреЗ рдХрд┐ рдПрдХ рдирд┐рд╡рд░реНрддрдорд╛рди WebSocket рдХрдиреЗрдХреНрд╢рди рдХреИрд╕реЗ рдмрдирд╛рдпрд╛ рдЬрд╛рдП, рдЗрд╕рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдПрдХ рдСрдбрд┐рдпреЛ рд╕реНрдЯреНрд░реАрдо рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░реЗрдВ рдФрд░ Google рдХреНрд▓рд╛рдЙрдб рд╕реНрдкреАрдЪ-рдЯреВ-рдЯреЗрдХреНрд╕реНрдЯ API рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕реЗ рдЯреЗрдХреНрд╕реНрдЯ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░реЗрдВред
рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╡рд╛рдХреНрд╕рд┐рдордкреНрд▓реЗрди рдореЗрдВ рд╡рд╛рдХреН-рд░реВрдкрд╛рдВрддрд░рдг рдХреЛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдордп рдореЗрдВ рдПрдПрд╕рдЖрд░ рдореЙрдбреНрдпреВрд▓ рдХреЗ рдирд┐рдпрдВрддреНрд░рдг рдореЗрдВ рдкрд╛рда рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рд╣реИред рдпрд╣ рдореЙрдбреНрдпреВрд▓ Google, Yandex рдФрд░ Tinkoff рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдпрд╣рд╛рдВ рд╡рд┐рд╡рд░рдг рджреЗрдЦреЗрдВред

рд╡рд░реНрддрдорд╛рди рд▓реЗрдЦ рдЙрд╕ рдорд╛рдорд▓реЗ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИ рдЬрдм рдЖрдк рднрд╛рд╖рдг рдХреЛ рдкрд╛рда рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдиреЗ рдФрд░ / рдпрд╛ рдЙрд╕рдХреЗ рдЦрд╛рддреЗ рд╕реЗ рдкреИрд╕рд╛ рдЦрд░реНрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддреАрд╕рд░реЗ рдкрдХреНрд╖ рдХреА рд╕реЗрд╡рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рди рдХрд┐ рд╡реЛрдХреНрд╕рд┐рдордкреНрд▓рд╛рдВрдЯ рдЦрд╛рддреЗ рд╕реЗред

рд╣рдорд╛рд░рд╛ рдореЙрдбреНрдпреВрд▓ рдХрд╛рдо рдХреЗ рджреЛ рдкреНрд░рд╛рд░реВрдк рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ:
  • рдПрдХ рдЖрдЙрдЯрдЧреЛрдЗрдВрдЧ рдХрдиреЗрдХреНрд╢рди рдмрдирд╛рдирд╛;
  • рдПрдХ рдЖрдиреЗ рд╡рд╛рд▓рд╛ рдХрдиреЗрдХреНрд╢рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдФрд░ рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рд╡реЗрдм рд╕реЙрдХреЗрдЯ рдмрдирд╛рдирд╛ред

рдЖрдЙрдЯрдмрд╛рдЙрдВрдб


рдЖрдЙрдЯрдмрд╛рдЙрдВрдб рдХрдиреЗрдХреНрд╢рди рдмрдирд╛рддреЗ рд╕рдордп рдкрд╣рд▓реА рдЪреАрдЬ рдЬреЛ рдЖрдкрдХреЛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рд╡рд╣ рд╣реИ рд╡реЛрдХреНрд╕рдЧрд╛рдЗрди рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рдЪрд▓рд╛рдирд╛ред рдЗрд╕рдХреЗ рдмрд╛рдж VoxEngine.createWebSocket рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░реЗрдВ, рдЬреЛ WebSocket рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдПрдЧреАред рдпрд╣ рд╡рд┐рдзрд┐ 2 рдкреИрд░рд╛рдореАрдЯрд░ рд▓реЗрддреА рд╣реИ: URL рдореЗрдВ 'wss: // + domain + path' рдФрд░ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ (рд╡реИрдХрд▓реНрдкрд┐рдХ)ред рдпрд╣рд╛рдВ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХреЛрдб рдореЗрдВ рдХреИрд╕рд╛ рджрд┐рдЦреЗрдЧрд╛:

VoxEngine.addEventListener(AppEvents.CallAlerting, function(e) { const webSocket = VoxEngine.createWebSocket( /*url*/ "wss://your_link/"); //       }); 

рдпрджрд┐ рд╕рдм рдХреБрдЫ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рддреЛ call.sendMediaTo рд╡рд┐рдзрд┐ рдСрдбрд┐рдпреЛ рд╕реНрдЯреНрд░реАрдо рдХреЛ рд╕реЙрдХреЗрдЯ рдореЗрдВ рднреЗрдЬ рджреЗрдЧреА, рдФрд░ WebSocket.send , рдмрджрд▓реЗ рдореЗрдВ рдЗрд╕рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ JSON рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдбрд┐рдХреЛрдб рдХрд┐рдП рдЧрдП рдСрдбрд┐рдпреЛ рд╕реНрдЯреНрд░реАрдо рдХреЛ рднреЗрдЬ рджреЗрдЧрд╛ред рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рдЖрдкрдХреЛ рдЕрдиреБрд░реЛрдз рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓реА рд╕реЗрд╡рд╛ рд╕реЗ рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рд╣реЛрдВрдЧреЗред

рдХрдиреЗрдХреНрд╢рди рдХреЛ рдмрдВрдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП WebSocket.close рд╡рд┐рдзрд┐ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдХрдиреЗрдХреНрд╢рди рдХреНрд▓рд╛рдЗрдВрдЯ рд╕рд╛рдЗрдб рдФрд░ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рджреЛрдиреЛрдВ рдкрд░ рдмрдВрдж рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рднреЗрдЬреЗ


рдЖрдиреЗ рд╡рд╛рд▓реЗ рдХрдиреЗрдХреНрд╢рдиреЛрдВ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ VoxEngine.allowWebSocketConnections рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реВрдЪрд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рдФрд░ AppEvents.WebSocket рдЗрд╡реЗрдВрдЯ рдХреА рд╕рджрд╕реНрдпрддрд╛ рднреА рд▓реЗрдиреА рдЪрд╛рд╣рд┐рдПред рдлрд┐рд░ рдЖрдиреЗ рд╡рд╛рд▓реЗ рдХрдиреЗрдХреНрд╢рди рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдирд╛ рдФрд░ WebSocket: event.WebSocket рдСрдмреНрдЬреЗрдХреНрдЯ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реЛрдЧрд╛ред рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рдХреЛрдб рдХреЛ рджреЗрдЦреЗрдВ:

 VoxEngine.allowWebSocketConnections(); VoxEngine.addEventListener(AppEvents.WebSocket, function(e) { //       }); 

рдПрдХ рдЖрдиреЗ рд╡рд╛рд▓реЗ рд╡реЗрдм рд╕реЙрдХреЗрдЯ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ AccessSecureURL рдирд┐рдпрдВрддреНрд░рдг рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдпрд╣ AppEvents.Started рдШрдЯрдирд╛ рдпрд╛ рд╕рддреНрд░ рд╢реБрд░реВ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ HTTP рдЕрдиреБрд░реЛрдз рдХреА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╕реЗ рд▓рд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ URL рдореЗрдВ "https" рдХреЛ 'wss' рдореЗрдВ рдмрджрд▓рдирд╛ рдЪрд╛рд╣рд┐рдПред

рд╢реЗрд╖ рдЪрд░рдг рдЖрдЙрдЯрдЧреЛрдЗрдВрдЧ рдХрдиреЗрдХреНрд╢рди рдпреЛрдЬрдирд╛ рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдП рдЧрдП рд╕рдорд╛рди рд╣реИрдВред

рдЖрдкрдХреЛ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА


рдЕрдкрдиреЗ рдЖрд╡реЗрджрди рдореЗрдВ WebSocket рдкреНрд░реМрджреНрдпреЛрдЧрд┐рдХреА рдФрд░ рд╡рд╛рдХреН рдкрд╣рдЪрд╛рди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА:
  • Voximplant рдЦрд╛рддрд╛ред рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдпрд╣ рдирд╣реАрдВ рд╣реИ, рддреЛ рдпрд╣рд╛рдВ рдкрдВрдЬреАрдХрд░рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рддрдВрддреНрд░ рдорд╣рд╕реВрд╕ рдХрд░реЗрдВ;
  • Voximplant рдЖрд╡реЗрджрди, рд╕рд╛рде рд╣реА рдПрдХ рд╕реНрдХреНрд░рд┐рдкреНрдЯ, рдПрдХ рдирд┐рдпрдо рдФрд░ рдПрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ред рдпрд╣ рд╕рдм рдЗрд╕ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдореЗрдВ рдмрдирд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛;
  • рд╕рд╛рдзрд╛рд░рдг рдмреИрдХрдПрдВрдб (рд╣рдо рдиреЛрдб.рдЬреЗрдПрд╕ рдкрд░ рд╕рд░реНрд╡рд░ рд╢реБрд░реВ рдХрд░реЗрдВрдЧреЗ) рд╕реНрдкреАрдЪ-рдЯреВ-рдЯреЗрдХреНрд╕реНрдЯ рдПрдкреАрдЖрдИ рдХреЗ рд▓рд┐рдП рдХреНрд▓рд╛рдЙрдб рдХреНрд▓рд╛рдЗрдВрдЯ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реЗ рдЬреБрдбрд╝реЗ;
  • рдПрдХ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡реЗрдм рдХреНрд▓рд╛рдЗрдВрдЯ (рд╣рдо phone.voximplant.com рдкрд░ рд╡реЗрдм рдлреЛрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ)ред

1. VOXIMPLANT рд╕реЗрдЯрд┐рдВрдЧреНрд╕


рдЖрд░рдВрдн рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, manage.voximplant.com/auth рдкрд░ рдЕрдкрдиреЗ рдЦрд╛рддреЗ рдореЗрдВ рд▓реЙрдЧ рдЗрди рдХрд░реЗрдВред рдмрд╛рдИрдВ рдУрд░ рдореЗрдиреВ рдореЗрдВ, "рдПрдкреНрд▓рд┐рдХреЗрд╢рди" рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВ, рдПрдХ рдирдпрд╛ рдмрдирд╛рдПрдВ рдФрд░ рдЗрд╕реЗ рд╡реЗрдмрд╕реНрдХреИрдЯ рдирд╛рдо рджреЗрдВред рдЕрдкрдиреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдЬрд╛рдПрдВ, рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЯреИрдм рдкрд░ рдЬрд╛рдПрдВ, рдПрдХ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдмрдирд╛рдПрдВ рдФрд░ рдЙрд╕рдореЗрдВ рдирд┐рдореНрди рдХреЛрдб рдкреЗрд╕реНрдЯ рдХрд░реЗрдВ:

 require(Modules.WebSocket); VoxEngine.addEventListener(AppEvents.CallAlerting, function(e) { call = e.call; call.answer(); const webSocket = VoxEngine.createWebSocket( /*url*/ "wss://your_ngrok_link/"); webSocket.addEventListener(WebSocketEvents.ERROR, function(e) { Logger.write("LOG OUTGOING: WebSocketEvents.ERROR"); call.sendMessage("LOG OUTGOING: WebSocketEvents.ERROR"); }); webSocket.addEventListener(WebSocketEvents.CLOSE, function(e) { Logger.write("LOG OUTGOING: WebSocketEvents.CLOSE: " + e.reason); call.sendMessage("LOG OUTGOING: WebSocketEvents.CLOSE: " + e.reason); }); webSocket.addEventListener(WebSocketEvents.OPEN, function(e) { Logger.write("LOG OUTGOING: WebSocketEvents.OPEN"); Logger.write(JSON.stringify(e)) call.sendMessage("LOG OUTGOING: WebSocketEvents.OPEN"); }); webSocket.addEventListener(WebSocketEvents.MESSAGE, function(e) { Logger.write("LOG OUTGOING: WebSocketEvents.MESSAGE: " + e.text); call.sendMessage("LOG OUTGOING: WebSocketEvents.MESSAGE: " + e.text); if (e.text == "Hi there, I am a WebSocket server") { call.sendMediaTo(webSocket, { encoding: WebSocketAudioEncoding.ULAW, "tag": "MyAudioStream", "customParameters": { "param1": "12345" } }); } }); call.addEventListener(CallEvents.Disconnected, function(e) { Logger.write("LOG OUTGOING: terminating in 1 sec"); webSocket.close(); setTimeout(VoxEngine.terminate, 1000); }); }); 

рдпрд╣ VoxEngine рд╕реНрдХреНрд░рд┐рдкреНрдЯ WebSocket рдХреЛ рдПрдХ рдСрдбрд┐рдпреЛ рд╕реНрдЯреНрд░реАрдо рднреЗрдЬрддрд╛ рд╣реИ, рдФрд░ рдЗрд╕рдХреЗ рдИрд╡реЗрдВрдЯ (ERROR, CLOSE, OPEN, MESSAGE) рдХреЛ рднреА рдЯреНрд░реИрдХ рдХрд░рддрд╛ рд╣реИред рд╣рдо рдереЛрдбрд╝реА рджреЗрд░ рдмрд╛рдж рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЗ рд╡рд┐рд╡рд░рдг рдореЗрдВ рддрд▓реНрд▓реАрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдЕрдм, "рд░реВрдЯрд┐рдВрдЧ" рдЯреИрдм рдкрд░ рдЬрд╛рдПрдВ, "рдиреНрдпреВ рд░реВрд▓" рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВ рдФрд░ рдЗрд╕реЗ рд╕реЙрдХреЗрдЯрд░реВрд▓ рдХрд╣реЗрдВред рдЕрдм рдпрд╣ рдХреЗрд╡рд▓ рдЖрдкрдХреА рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рдЪрдпрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдирд╛ рд╣реБрдЖ рд╣реИ, рдФрд░ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ (*ред) рдорд╛рд╕реНрдХ рдХреЛ рдЫреЛрдбрд╝ рджреЗрдВред


рдЕрдВрддрд┐рдо рдЪрд░рдг рдЖрдкрдХреЛ рдЗрд╕ рд╕реНрддрд░ рдкрд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдПрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдмрдирд╛рдПрдВред "рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛" рдЯреИрдм рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд░реЗрдВ, "рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдмрдирд╛рдПрдВ" рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВ, рдПрдХ рдирд╛рдо рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░реЗрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕реЙрдХреЗрдЯрдпреВрдЬрд╝рд░) рдФрд░ рдкрд╛рд╕рд╡рд░реНрдб, рдлрд┐рд░ "рдмрдирд╛рдПрдВ" рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВред рд╣рдореЗрдВ рдЕрдВрддрд┐рдо рдЪрд░рдг рдореЗрдВ рд╡реЗрдм рдХреНрд▓рд╛рдЗрдВрдЯ рдореЗрдВ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдХреЗ рд▓рд┐рдП рдЗрд╕ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо / рдкрд╛рд╕рд╡рд░реНрдб рдЬреЛрдбрд╝реА рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреАред


рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдкреВрд░реНрдг рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рд╣рдо рд╕рд░реНрд╡рд░ рдмрдирд╛рдирд╛ рд╢реБрд░реВ рдХрд░реЗрдВ, рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд░рд┐рджреГрд╢реНрдп рдореЗрдВ WebSocket рдореЙрдбреНрдпреВрд▓ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

2. рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рд╡рд┐рд╡рд░рдг


WebSocket рдореЙрдбреНрдпреВрд▓ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЛ рдПрдХ рд╕реНрдерд┐рд░ рдХрдиреЗрдХреНрд╢рди рдЦреЛрд▓рдиреЗ рдФрд░ рдЗрд╕рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдбреЗрдЯрд╛ рднреЗрдЬрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЗрд╕ рдореЙрдбреНрдпреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдЗрд╕реЗ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рдХрдиреЗрдХреНрдЯ рдХрд░рдирд╛ рд╣реЛрдЧрд╛:

 require(Modules.WebSocket); 

CreateWebSocket рд╡рд┐рдзрд┐ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ, рд╣рдо URL рдФрд░ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ (рд╡реИрдХрд▓реНрдкрд┐рдХ) рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдЖрдк рд╕реАрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдЕрдЧрд▓реЗ рдЕрдиреБрднрд╛рдЧ рд╕реЗ WebSocket рдХреЗ рд▓рд┐рдП URL рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред

 const webSocket = VoxEngine.createWebSocket( /*url*/ "wss://your_ngrok_link/"); 

WebSocket рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рд╣реИрдВрдбрд▓рд░ рдХреЗ рдЕрдВрджрд░ рдХреЙрд▓ рдХреЛ рдкреНрд░рдмрдВрдзрд┐рдд рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦрддреЗ рд╣реИрдВред рдЕрд░реНрдерд╛рддреН, рд╣рдо call.sendMediaTo рдкрджреНрдзрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдореАрдбрд┐рдпрд╛ рдХреЛ WebSocket рдСрдмреНрдЬреЗрдХреНрдЯ рдкрд░ рднреЗрдЬрддреЗ рд╣реИрдВред

рдпрд╣рд╛рдВ рдЖрдк рдкрд╕рдВрджреАрджрд╛ рдПрдиреНрдХреЛрдбрд┐рдВрдЧ рдкреНрд░рд╛рд░реВрдк, рдЯреИрдЧ рдФрд░ рдХреБрдЫ рдХрд╕реНрдЯрдо рдкреИрд░рд╛рдореАрдЯрд░ рд╕реЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдпрджрд┐ рдЖрдк рдПрдиреНрдХреЛрдбрд┐рдВрдЧ рд╕реЗрдЯ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ PCM8 рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

рд╕рдлрд▓ рдХрдиреЗрдХреНрд╢рди рд╕рдВрджреЗрд╢ рдкреНрд░рд╛рдкреНрдд рд╣реЛрдиреЗ рдкрд░ рдЗрд╕ рд╡рд┐рдзрд┐ рдХреЛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рд╣рдорд╛рд░реЗ рдкрд░рд┐рджреГрд╢реНрдп рдореЗрдВ, рдХреЙрд▓ рдХреЛрдб рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:

 call.sendMediaTo(webSocket, { encoding: WebSocketAudioEncoding.ULAW, "tag": "MyAudioStream", "customParameters": { "param1": "12345" } }); 

рдЕрдиреНрдп рд╕рднреА WebSocket рдИрд╡реЗрдВрдЯ рдЬреЛ рдЖрдк рдХреЛрдб рдореЗрдВ рджреЗрдЦрддреЗ рд╣реИрдВ рдбрд┐рдмрдЧрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рд╣реИрдВ, рд╡реЗ рд╡реЛрдХреНрд╕рд┐рдордкреНрд▓реЗрди рд╕рддреНрд░ рдХреЗ рд▓реЙрдЧ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рднреЗрдЬрддреЗ рд╣реИрдВред рдЖрдк рдЪрд╛рд╣реЗрдВ рддреЛ рдЙрдиреНрд╣реЗрдВ рдирд┐рдХрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВред

рдЕрдВрдд рдореЗрдВ, рд╣рдо рд╕рд╣реА рдбреЗрдЯрд╛ рдЯреНрд░рд╛рдВрд╕рдлрд░ рдкреВрд░рд╛ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рд╣реИрдВрдбрд▓рд░ рдХреЛ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╡реЙрдХреНрд╕рд┐рдордкреНрд▓рд╛рдВрдЯ рд╕рддреНрд░ рд╕реНрдерд╛рдкрд┐рдд рдХреЙрд▓ рдХреЗ рдЕрдВрдд рдХреЗ рдмрд╛рдж рдЕрдкрдирд╛ рдХрд╛рдо 1 рд╕реЗрдХрдВрдб рд╕рдорд╛рдкреНрдд рдХрд░ рджреЗрдЧрд╛ (рдЕрд╕рдореНрдмрджреНрдз):

 call.addEventListener(CallEvents.Disconnected, function(e) { Logger.write("LOG OUTGOING: terminating in 1 sec"); webSocket.close(); setTimeout(VoxEngine.terminate, 1000); }); 

рдЕрдм рдЬрдм рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХрд╛ рддрд░реНрдХ рд╕реНрдкрд╖реНрдЯ рд╣реИ, рдпрд╣ рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рдЕрдЧрд▓реЗ, рдмрд╣реБрдд рдорд╣рддреНрд╡рдкреВрд░реНрдг рднрд╛рдЧ рдкрд░ рдЖрдЧреЗ рдмрдврд╝рдиреЗ рдХрд╛ рд╕рдордп рд╣реИред

3. рдмреИрдХрдПрдВрдб


рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдЖрдкрдХреЗ рдХрдВрдкреНрдпреВрдЯрд░ рдкрд░ Node.js. рд╕реНрдерд╛рдкрд┐рдд рд╣реИред рдЖрдк рдЗрд╕реЗ Node.js рдореБрдЦреНрдп рд╕рд╛рдЗрдЯ рд╕реЗ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдлрд┐рд░, рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рдорд╛рд╣реМрд▓ рдХреЛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЯрд░реНрдорд┐рдирд▓ рд╡рд┐рдВрдбреЛ рдореЗрдВ рдПрдХ рдХреЗ рдмрд╛рдж рдПрдХ, рдирд┐рдореНрди рдХрдорд╛рдВрдбреНрд╕ рдЪрд▓рд╛рдПрдВ:

 npm install express npm install ws npm install @google-cloud/speech 

рдФрд░ рдЬрдм рдпрд╣ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдПрдХ рдЦрд╛рд▓реА рдЬреЗрдПрд╕ рдлрд╛рдЗрд▓ рдмрдирд╛рдПрдВ рдФрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдб рдХреЛ рд╡рд╣рд╛рдВ рд░рдЦреЗрдВ (рдХреЛрдб рдХреА рдмрд╛рд░реАрдХрд┐рдпреЛрдВ рдХреЛ рдиреАрдЪреЗ рд╣рд╛рдЗрд▓рд╛рдЗрдЯ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛):

 const app = require('express')(); const http = require('http').createServer(app); const WebSocket = require('ws'); const fs = require('fs'); const wss = new WebSocket.Server({ server: http }); //     Google Cloud const speech = require('@google-cloud/speech'); //    const client = new speech.SpeechClient(); const config = { encoding: 'MULAW', sampleRateHertz: 8000, languageCode: 'ru-RU', }; const request = { config, interimResults: true, }; let audioInput = []; let recognizeStream = null; process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0; app.get('/', function(req, res) { res.send('<h1>Hello world</h1>'); }); wss.on('connection', (ws) => { //  ,       var wstream = fs.createWriteStream('myBinaryFile'); //   audioInput audioInput = []; //    recognizeStream = client .streamingRecognize(request) .on('error', err => { ws.close(); }) .on('data', data => { ws.send(data.results[0].alternatives[0].transcript) process.stdout.write( data.results[0] && data.results[0].alternatives[0] ? `Transcription: ${data.results[0].alternatives[0].transcript}\n` : `\n\nError occurred, press Ctrl+C\n` ) }); ws.on('close', (message) => { console.log('The time limit for speech recognition has been reached. Please disconnect and call again.'); wstream.end(); }) //  ,     message ws.on('message', (message) => { //     base64  recognizeStream try { let data = JSON.parse(message) if (data.event == "media") { let b64data = data.media.payload; let buff = new Buffer.from(b64data, 'base64'); recognizeStream.write(buff); wstream.write(buff); } } catch (err) { console.log(message) } }); //      ws.send('Hi there, I am a WebSocket server'); }); http.listen(3000, function() { console.log('listening on *:3000'); }); 

рдЕрдм рдЬрдм рд╕рд░реНрд╡рд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ рдпрд╣ рд╣рдореЗрдВ рднрд╛рд╖рдг рдкрд╣рдЪрд╛рди рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдЧрд╛ред рд▓реЛрдХрд▓рд╣реЛрд╕реНрдЯ 3000 рдкрд░ рдПрдирд░реЛрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рд╕реБрд░рдВрдЧ рдмрдирд╛рдХрд░ рд╕реНрдерд╛рдиреАрдп рд░реВрдк рд╕реЗ рдЕрдкрдиреЗ рд╕рдорд╛рдзрд╛рди рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░реЗрдВред

рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЗрди рдЪрд░рдгреЛрдВ рдХрд╛ рдкрд╛рд▓рди рдХрд░реЗрдВ:
  1. рдЕрдкрдиреА рд╡реЗрдмрд╕рд╛рдЗрдЯ рдкрд░ рджрд┐рдП рдЧрдП рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХрд╛ рдкрд╛рд▓рди рдХрд░рдХреЗ рдПрдирд░реЛрдХ рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ ред
  2. рдЧреНрд░рд╛рд╣рдХ рдХреЛ рдЗрд╕ рдЦрд╛рддреЗ рдореЗрдВ рдмрд╛рдБрдзрдиреЗ рдХреЗ рд▓рд┐рдП ngrok рдХреЗ рд▓рд┐рдП рдЕрдкрдирд╛ рдУрдХрдЯреЛрдХреЗрди рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░реЗрдВред
  3. рдЕрдкрдиреЗ рд╕рд░реНрд╡рд░ рдХреЛ рд▓реЛрдХрд▓рд╣реЛрд╕реНрдЯ рдкрд░ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП node your_file_name.js рдЪрд▓рд╛рдПрдБ: 3000ред
  4. рдЕрдкрдиреЗ рдХрдВрдкреНрдпреВрдЯрд░ рдкрд░ ngrok рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рдЬрд╛рдПрдВ рдФрд░ рдЪрд▓ рд░рд╣реЗ рд╕реНрдерд╛рдиреАрдп рд╕рд░реНрд╡рд░ рдФрд░ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ URL рдХреЗ рдмреАрдЪ рдПрдХ рд╕реБрд░рдВрдЧ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП ./ngrok http 3000 рдХрдорд╛рдВрдб рдЪрд▓рд╛рдПрдБред

рдЬрдирд░реЗрдЯ рдХрд┐рдП рдЧрдП рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ URL рдкрд░ рдзреНрдпрд╛рди рджреЗрдВ, рд╣рдо рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдЙрдкрд╕рд░реНрдЧ 'wss' рдХреЗ рд╕рд╛рде WebSocket URL рдХреЗ рд░реВрдк рдореЗрдВ рдХрд░рддреЗ рд╣реИрдВ:



4. рд╡рд╛рдХреН рдкрд╣рдЪрд╛рди


рдЖрдкрдиреЗ рд╢рд╛рдпрдж рджреЗрдЦрд╛ рд╣реЛрдЧрд╛ рдХрд┐ рд╣рдорд╛рд░реЗ рдмреИрдХрдПрдВрдб рдХреЛрдб рдореЗрдВ Google рдХреНрд▓рд╛рдЙрдб рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд▓рд╛рдЗрдиреЗрдВ рд╣реИрдВред

рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╕реНрд╡рдпрдВ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдЖрдпрд╛рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:

 const speech = require('@google-cloud/speech'); 

рдЕрдм рдЖрдкрдХреЛ рдпрд╣ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рднрд╛рд╖рдг рдорд╛рдиреНрдпрддрд╛ рдЕрдиреБрд░реЛрдз рдХреЛ рдХреИрд╕реЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЬрдирд░реЗрдЯ рдХрд┐рдП рдЧрдП рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдореЗрдВ рдПрдиреНрдХреЛрдбрд┐рдВрдЧ, sampleRateHertz рдФрд░ languageCode рдХрд╛ рдЪрдпрди рдХрд░реЗрдВ:

 const config = { encoding: 'MULAW', sampleRateHertz: 8000, languageCode: 'en-US', }; 

рдЕрдЧрд▓рд╛, рдПрдХ рд▓рд┐рдЦрд┐рдд рд╕реНрдЯреНрд░реАрдо рдмрдирд╛рдПрдВ рдЬреЛ рдЖрдкрдХреЛ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдбреЗрдЯрд╛ рд╕рд╣реЗрдЬрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ:

 var wstream = fs.createWriteStream('myBinaryFile'); 

рдЬрдм рд╕рдм рдХреБрдЫ рд╕реЗрдЯ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЖрдкрдХреЛ рд╕рдВрджреЗрд╢ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реЛрддреА рд╣реИ рдФрд░ рдСрдбрд┐рдпреЛ рдбреЗрдЯрд╛ рдХреЛ рдЖрдзрд╛рд░ 64 рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдкрд╣рдЪрд╛рди рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд░рдЦрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП:

 let data = JSON.parse(message) if (data.event == "media") { b64data = data.media.payload; let buff = new Buffer.from(b64data, 'base64'); recognizeStream.write(buff); wstream.write(buff); } 

рдЗрд╕рдХреЗ рддреБрд░рдВрдд рдмрд╛рдж, рдПрдХ рдорд╛рдиреНрдпрддрд╛ рдЕрдиреБрд░реЛрдз рд╢реБрд░реВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдФрд░ рдЗрд╕ рдЕрдиреБрд░реЛрдз рдХрд╛ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рд╢реБрд░реВ рд╣реЛ рдЬрд╛рдПрдЧрд╛:

 recognizeStream = client .streamingRecognize(request) .on('data', data => { ws.send(data.results[0].alternatives[0].transcript) }); 

рдЕрдВрдд рдореЗрдВ, Google рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛ рдЗрд╕рдХреЗ рдмреИрдХрдПрдВрдб рд╕реЗ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ рд╕реЗрд╡рд╛ рдЦрд╛рддреЗ рдХреА рд╕рд╛рдЦ рдкреНрд░рджрд╛рди рдХрд░реЗрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, Google рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдкреГрд╖реНрда рдкрд░ рдЬрд╛рдПрдВ рдФрд░ рд╡рд╣рд╛рдВ рд╕реВрдЪреАрдмрджреНрдз рд╕рднреА рдЪрд░рдгреЛрдВ рдХрд╛ рдкрд╛рд▓рди рдХрд░реЗрдВред рдлрд┐рд░ рдирд┐рд░реНрдпрд╛рдд рдХрдорд╛рдВрдб рдХреЛ рдЙрд╕реА рдХрд╛рд░реНрдпрдХреНрд╖реЗрддреНрд░ рдореЗрдВ (рдЙрд╕реА "рдЯрд░реНрдорд┐рдирд▓" рдЯреИрдм рдореЗрдВ) node your_file_name.js: рд░реВрдк рдореЗрдВ node your_file_name.js:

 export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/[FILE_NAME].json" 

рд╕реЙрдХреЗрдЯ рд▓реЙрдиреНрдЪ рдХрд░реЗрдВ


Phone.voximplant.com рдЦреЛрд▓реЗрдВ, рдлрд╝реЙрд░реНрдо рднрд░реЗрдВ рдФрд░ рд╕рд╛рдЗрди рдЗрди рдХрд░реЗрдВ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо рдФрд░ рдкрд╛рд╕рд╡рд░реНрдб рдЪрд░рдг 1 рдореЗрдВ рдмрдирд╛рдП рдЧрдП рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИ:


рд╕рдлрд▓ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдХреЗ рдмрд╛рдж, рдХреЙрд▓ рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░реЗрдВ рдФрд░ рдмрд╛рдд рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░реЗрдВред рд╕реНрдкреАрдЪ-рдЯреВ-рдЯреЗрдХреНрд╕реНрдЯ рдХреНрд▓рд╛рдЙрдб рдЖрдкрдХреЗ рднрд╛рд╖рдг рдХреЛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдордп рдореЗрдВ рдЯреЗрдХреНрд╕реНрдЯ рдореЗрдВ рдмрджрд▓ рджреЗрдЧрд╛, рдФрд░ рдЖрдк рдЗрд╕ рд╡рд┐рдВрдбреЛ рдХреЛ рдЯрд░реНрдорд┐рдирд▓ рд╡рд┐рдВрдбреЛ рдореЗрдВ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред

рдЖрдкрдиреЗ рдЗрд╕реЗ рдХрд┐рдпрд╛, рдмрдзрд╛рдИ! рд╣рдореЗрдВ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдЖрдкрдХреЛ рд▓реЗрдЦ рдкрд╕рдВрдж рдЖрдпрд╛ рд╣реЛрдЧрд╛ рдФрд░ рдЖрдк рдЕрдзрд┐рдХ рдПрдХреАрдХрд░рдг рдФрд░ рдирдИ рдЪреБрдиреМрддрд┐рдпреЛрдВ рдХреА рдХрд╛рдордирд╛ рдХрд░реЗрдВрдЧреЗред

Source: https://habr.com/ru/post/hi476902/


All Articles