{"id":391567,"date":"2024-06-29T09:53:51","date_gmt":"2024-06-29T09:53:51","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=391567"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=391567","title":{"rendered":"<span>JavaScript: \u0437\u0430\u0445\u0432\u0430\u0442 \u043c\u0435\u0434\u0438\u0430\u043f\u043e\u0442\u043e\u043a\u0430 \u0438\u0437 DOM \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/cm\/yu\/dk\/cmyudkffaaxue4r760lyvmate6i.png\" data-src=\"https:\/\/habrastorage.org\/webt\/cm\/yu\/dk\/cmyudkffaaxue4r760lyvmate6i.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0434\u0440\u0443\u0437\u044c\u044f!<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u044e \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043f\u043e \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u043c\u0435\u0434\u0438\u0430, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0435 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430\u043c\u0438, \u0438 \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0432\u0430\u043c \u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0437\u0430\u0445\u0432\u0430\u0442\u0430 \u0438 \u0437\u0430\u043f\u0438\u0441\u0438 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0430\u0443\u0434\u0438\u043e \u0438 \u0432\u0438\u0434\u0435\u043e\u0444\u0430\u0439\u043b\u043e\u0432.<\/p>\n<p>  <\/p>\n<p>\u041c\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0430\u0443\u0434\u0438\u043e \u0438 \u0432\u0438\u0434\u0435\u043e \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u043e\u043c:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u043e\u0434\u043d\u043e \u0432\u0438\u0434\u0435\u043e \u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0430\u0443\u0434\u0438\u043e, \u0445\u0440\u0430\u043d\u044f\u0449\u0438\u0445\u0441\u044f \u0432 \u0435\u0433\u043e \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435;<\/li>\n<li>\u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u0442 \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0437\u0430\u043f\u0438\u0441\u0438, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432, \u0437\u0430\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0438\u0445 \u043c\u0435\u0434\u0438\u0430\u043f\u043e\u0442\u043e\u043a\u0438;<\/li>\n<li>\u0437\u0430\u0445\u0432\u0430\u0447\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u0442\u043e\u043a\u0438 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u044e\u0442\u0441\u044f \u0432 \u043e\u0434\u0438\u043d \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438;<\/li>\n<li>\u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u043c\u0435\u043d\u044f\u0442\u044c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0430\u0443\u0434\u0438\u043e\u0434\u0430\u043d\u043d\u044b\u0445;<\/li>\n<li>\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u0430\u0443\u0434\u0438\u043e\u0434\u0430\u043d\u043d\u044b\u0445) \u0438 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u044c;<\/li>\n<li>\u043f\u043e \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044e \u0437\u0430\u043f\u0438\u0441\u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432\u0438\u0434\u0435\u043e\u0444\u0430\u0439\u043b \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/WebM\"><code>WebM<\/code><\/a> \u2014 \u043f\u0440\u0435\u0432\u044c\u044e \u0441\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430 \u0438 \u0441\u0441\u044b\u043b\u043a\u0430 \u0434\u043b\u044f \u0435\u0433\u043e \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0434\u043b\u044f \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u044f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/ru.reactjs.org\/\"><code>React<\/code><\/a>, \u043e\u0434\u043d\u0430\u043a\u043e \u0432\u0441\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u043e \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u043c\u0435\u0434\u0438\u0430 \u0431\u0443\u0434\u0443\u0442 \u0430\u0432\u0442\u043e\u043d\u043e\u043c\u043d\u044b\u043c\u0438 (\u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u0430 \u044d\u0442\u0438\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0431\u0443\u0434\u0435\u0442 framework agnostic), \u0442\u0430\u043a \u0447\u0442\u043e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u044e\u0431\u043e\u0439 \u0434\u0440\u0443\u0433\u043e\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0438\u043b\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c\u0441\u044f \u0447\u0438\u0441\u0442\u044b\u043c <code>JavaScript<\/code>.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0430:<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<div class=\"oembed\">\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/61e98b14abb378f6450d1bbd\" data-style=\"\" id=\"61e98b14abb378f6450d1bbd\" width=\"\"><\/div>\n<\/div>\n<\/div><\/div>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/harryheman\/Blog-Posts\/tree\/master\/capture-stream\">\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439<\/a>.<\/p>\n<p>  <\/p>\n<p>\u041e \u0442\u043e\u043c, \u043a\u0430\u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0430\u0443\u0434\u0438\u043e\u0437\u0430\u043c\u0435\u0442\u043e\u043a, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 <a href=\"https:\/\/habr.com\/ru\/company\/timeweb\/blog\/581086\/\">\u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a>, \u0430 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0437\u0430\u0445\u0432\u0430\u0442\u0430 \u0438 \u0437\u0430\u043f\u0438\u0441\u0438 \u044d\u043a\u0440\u0430\u043d\u0430 \u2014 \u0432 <a href=\"https:\/\/habr.com\/ru\/company\/timeweb\/blog\/591417\/\">\u044d\u0442\u043e\u0439<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u044d\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u043f\u0440\u043e\u0448\u0443 \u043f\u043e\u0434 \u043a\u0430\u0442.<\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0438\u0437\u0443\u0447\u0438\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043d\u0430\u0448\u0435\u0433\u043e \u0431\u0443\u0434\u0443\u0449\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0442\u043e \u043c\u043e\u0433\u043b\u0438 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u043e \u0432\u0438\u0434\u0435\u043e \u0438 \u0438\u043c\u0435\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043c\u0435\u043d\u044f\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0430\u0443\u0434\u0438\u043e\u0434\u0430\u043d\u043d\u044b\u0445. \u042d\u0442\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u043d\u0430 \u0441\u0435\u0433\u043e\u0434\u043d\u044f\u0448\u043d\u0438\u0439 \u0434\u0435\u043d\u044c \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u0430 \u0437\u0430\u043c\u0435\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0430\u0443\u0434\u0438\u043e\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 (\u0431\u0435\u0437 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 <code>MediaRecorder<\/code>).<\/p>\n<p>  <\/p>\n<p>\u0412 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043e\u043f\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 (\u0447\u0435\u0440\u043d\u043e\u0432\u0438\u043a\u0438 \u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0446\u0438\u044e):<\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/www.w3.org\/TR\/mediacapture-fromelement\/\">Media Capture from DOM Elements<\/a> \u2014 \u0437\u0430\u0445\u0432\u0430\u0442 \u043c\u0435\u0434\u0438\u0430\u043f\u043e\u0442\u043e\u043a\u0430 \u0438\u0437 DOM \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432;<\/li>\n<li><a href=\"https:\/\/www.w3.org\/TR\/mediastream-recording\/\">MediaStream Recording<\/a> \u2014 \u0437\u0430\u043f\u0438\u0441\u044c \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445;<\/li>\n<li><a href=\"https:\/\/w3c.github.io\/mediacapture-main\/#stream-api\">Media Capture and Streams. MediaStream API<\/a> \u2014 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043c\u0435\u0434\u0438\u0430\u043f\u043e\u0442\u043e\u043a\u043e\u0432;<\/li>\n<li><a href=\"https:\/\/www.w3.org\/TR\/webaudio\/#MediaStreamAudioDestinationNode\">Web Audio API. MediaStreamAudioDestinationNode \u0438 MediaStreamAudioSourceNode<\/a> \u2014 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u0430\u0443\u0434\u0438\u043e\u0434\u0430\u043d\u043d\u044b\u0445;<\/li>\n<li><a href=\"https:\/\/w3c.github.io\/FileAPI\/#blob-section\">File API. The Blob Interface and Binary Data \u0438 A URL for Blob and MediaSource reference<\/a> \u2014 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 <code>Blob<\/code> \u0438 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043d\u0435\u0433\u043e.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0421\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u044b <code>MDN<\/code> \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u043f\u043e \u043c\u0435\u0440\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438.<\/p>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0448\u0430\u0431\u043b\u043e\u043d <code>React-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/code> \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"https:\/\/create-react-app.dev\/\"><code>create-react-app<\/code><\/a>:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">yarn create react-app capture-stream # or npx create-react-app capture-stream<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u043a\u0430 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0448\u0430\u0431\u043b\u043e\u043d, \u043f\u043e\u0433\u043e\u0432\u043e\u0440\u0438\u043c \u043e\u0431 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430\u0445 \u0438 \u043c\u0435\u0442\u043e\u0434\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c.<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0414\u043b\u044f \u0437\u0430\u0445\u0432\u0430\u0442\u0430 \u043c\u0435\u0434\u0438\u0430\u043f\u043e\u0442\u043e\u043a\u0430 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0430\u0443\u0434\u0438\u043e \u0438\u043b\u0438 \u0432\u0438\u0434\u0435\u043e, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 <code>canvas<\/code>, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434 <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/HTMLMediaElement\/captureStream\"><code>captureStream<\/code><\/a>. \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u043d\u0430 \u0441\u0435\u0433\u043e\u0434\u043d\u044f\u0448\u043d\u0438\u0439 \u0434\u0435\u043d\u044c \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f Safari, \u0430 \u0432 Firefox \u043e\u043d \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u043e\u043c (<code>mozCaptureStream<\/code>):<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"javascript\">const audio$ = document.querySelector('audio') audio$.play()  const stream = audio$.captureStream()<\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li>\u0414\u043b\u044f \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/MediaStream\"><code>MediaStream<\/code><\/a>:<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"javascript\">const audioStream = audio$.captureStream() const videoStream = video$.captureStream()  const audioTracks = audioStream.getAudioTracks() const videoTracks = videoStream.getVideoTracks()  const mediaStream = new MediaStream([...audioTracks, ...videoTracks])<\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li>\u0414\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u043c\u0435\u0434\u0438\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/MediaRecorder\"><code>MediaRecorder<\/code><\/a>:<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"javascript\">const mediaChunks = [] const mediaRecorder = new MediaRecorder(mediaRecorder, {  mimeType: 'video\/webm',  \/\/ \u0434\u0440\u0443\u0433\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 })  \/\/ \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 mediaRecorder.ondataavailable = (e) => {  \/\/ \u0447\u0430\u0441\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0432\u0438\u0434\u0435 `Blob`  mediaChunks.push(e.data) }  \/\/ \u043c\u0435\u0442\u043e\u0434 `start` \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 `timeslice` - \u0432\u0440\u0435\u043c\u044f \u0432 \u043c\u0441, \/\/ \u043f\u043e \u0438\u0441\u0442\u0435\u0447\u0435\u043d\u0438\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 `dataavailable` mediaRecorder.start(250)  \/\/ \u0434\u0440\u0443\u0433\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b mediaRecorder.stop() mediaRecorder.pause() mediaRecorder.resume()  \/\/ \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \/\/ \u043d\u0435\u0430\u043a\u0442\u0438\u0432\u0435\u043d mediaRecorder.inactive \/\/ \u0438\u0434\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u044c mediaRecorder.recording \/\/ \u0437\u0430\u043f\u0438\u0441\u044c \u043f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0430 mediaRecorder.paused<\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li>\u0414\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0441\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u0438\u0434\u0435\u043e\u0444\u0430\u0439\u043b\u0430 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Blob\"><code>Blob<\/code><\/a> \u0432 \u0441\u043e\u0447\u0435\u0442\u0430\u043d\u0438\u0438 \u0441 \u043c\u0435\u0442\u043e\u0434\u043e\u043c <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/URL\/createObjectURL\"><code>createObjectURL<\/code><\/a>:<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"javascript\">const blob = new Blob(mediaChunks, {  type: 'video\/webm',  \/\/ \u0434\u0440\u0443\u0433\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 })  \/\/ \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u043f\u0443\u0442\u044c \u043a \u0444\u0430\u0439\u043b\u0443, \u0445\u0440\u0430\u043d\u044f\u0449\u0435\u043c\u0443\u0441\u044f \u0432 \u043f\u0430\u043c\u044f\u0442\u0438, \/\/ \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c `video` \u0438 `a` const url = URL.createObjectURL(blob)<\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li>\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u0430\u0443\u0434\u0438\u043e\u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u043e\u0447\u0435\u0442\u0430\u043d\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432 <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/AudioContext\"><code>AudioContext<\/code><\/a>, <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/MediaStreamAudioDestinationNode\"><code>MediaStreamAudioDestinationNode<\/code><\/a> \u0438 <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/MediaStreamAudioSourceNode\"><code>MediaStreamAudioSourceNode<\/code><\/a>:<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0430\u0443\u0434\u0438\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 const audioContext = new AudioContext() \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u0447\u0438\u043a \u0430\u0443\u0434\u0438\u043e const mediaStreamAudioDestinationNode = new MediaStreamAudioDestinationNode(  audioContext ) \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0430\u0443\u0434\u0438\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0430\u0443\u0434\u0438\u043e\u043f\u043e\u0442\u043e\u043a\u0430, \u0437\u0430\u0445\u0432\u0430\u0447\u0435\u043d\u043d\u043e\u0433\u043e \u0438\u0437 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 `audio` \/\/ \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u0447\u0438\u043a\u0430 \u0438 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u043c const mediaStreamAudioSourceNode = new MediaStreamAudioSourceNode(audioContext, {  mediaStream: audioStream }) \/\/ \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u043a \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u0447\u0438\u043a\u0443 mediaStreamAudioSourceNode.connect(mediaStreamAudioDestinationNode) \/\/ \u0434\u0430\u043b\u0435\u0435 \u0432\u043c\u0435\u0441\u0442\u043e `audioStream.getAudioTracks()` \u0432 `new MediaStream()` \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f mediaStreamAudioDestinationNode.stream.getAudioTracks()<\/code><\/pre>\n<p>  <\/p>\n<p>\u0428\u0430\u0431\u043b\u043e\u043d \u0433\u043e\u0442\u043e\u0432. \u041f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>src<\/code> \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">- assets - 2 \u0430\u0443\u0434\u0438\u043e\u0444\u0430\u0439\u043b\u0430 \u0438 1 \u0432\u0438\u0434\u0435\u043e\u0444\u0430\u0439\u043b (\u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0438) - components - \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b  - AudioSelector.js - \u0434\u043b\u044f \u0432\u044b\u0431\u043e\u0440\u0430 \u0430\u0443\u0434\u0438\u043e  - VideoSelector.js - \u0434\u043b\u044f \u0432\u044b\u0431\u043e\u0440\u0430 \u0432\u0438\u0434\u0435\u043e  - Recorder.js - \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438  - Result.js - \u0434\u043b\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0437\u0430\u043f\u0438\u0441\u0438 - hook - \u0445\u0443\u043a\u0438  - usePrevious.js - \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f - utils - \u0443\u0442\u0438\u043b\u0438\u0442\u044b  - verifySupport.js - \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0439  - recording.js - \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0438 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0435\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430  - createStore.js - \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f - App.js - App.scss - index.js - ...<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435, \u0434\u043b\u044f \u0441\u0442\u0438\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0441\u044f <a href=\"https:\/\/sass-lang.com\/\"><code>Sass<\/code><\/a>:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">yarn add -D sass # or npm i -D sass<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f (<code>App.js<\/code>).<\/p>\n<p>  <\/p>\n<p>\u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u0443\u0442\u0438\u043b\u0438\u0442\u0443 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u0441\u0442\u0438\u043b\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import { VideoSelector, AudioSelector, Recorder, Result } from 'components' import { createStore } from 'utils\/createStore' import '.\/App.scss'<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0445\u0443\u043a\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">const store = {  state: {    \/\/ \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u0430\u0443\u0434\u0438\u043e    audio: '',    \/\/ ... \u0432\u0438\u0434\u0435\u043e    video: '',    \/\/ \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0437\u0430\u043f\u0438\u0441\u0438    result: ''  },  setters: {    \/\/ \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b    setAudio: (_, audio) => ({ audio }),    setVideo: (_, video) => ({ video }),    setResult: (_, result) => ({ result })  } }  export const [Provider, useStore, useSetters] = createStore(store)<\/code><\/pre>\n<p>  <\/p>\n<p>\u0421 \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0435\u043d\u0438\u044f, \u044f \u043d\u0435 \u0431\u0443\u0434\u0443 \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0443\u0442\u0438\u043b\u0438\u0442\u0435 (\u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u043e \u043d\u0435\u0439 \u043c\u043e\u0436\u043d\u043e <a href=\"https:\/\/habr.com\/ru\/company\/timeweb\/blog\/597109\/\">\u0437\u0434\u0435\u0441\u044c<\/a>). \u0421\u043f\u0440\u0430\u0432\u0435\u0434\u043b\u0438\u0432\u043e\u0441\u0442\u0438 \u0440\u0430\u0434\u0438 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u044f \u0432\u0441\u0435 \u0447\u0430\u0449\u0435 \u043f\u0440\u0438\u0431\u0435\u0433\u0430\u044e \u043a \u043f\u043e\u043c\u043e\u0449\u0438 <a href=\"https:\/\/github.com\/pmndrs\/zustand\"><code>zustand<\/code><\/a>.<\/p>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0438 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">function App() {  return (    &lt;Provider>      &lt;div className='container common'>        &lt;VideoSelector \/>        &lt;AudioSelector \/>      &lt;\/div>      &lt;Recorder \/>      &lt;Result \/>    &lt;\/Provider>  ) }  export default App<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0434\u043b\u044f \u0432\u044b\u0431\u043e\u0440\u0430 \u0432\u0438\u0434\u0435\u043e (<code>components\/VideoSelector.js<\/code>):<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import { useState, useEffect, useRef } from 'react' import { useSetters } from 'App'  export const VideoSelector = () => {  \/\/ \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u043b\u044f \u043f\u0443\u0442\u0438 \u043a \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u043c\u0443 \u0432\u0438\u0434\u0435\u043e  const [fileUrl, setFileUrl] = useState()  \/\/ \u0438\u043c\u043c\u0443\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u0430\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0434\u043b\u044f \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 `video`  const videoRef = useRef()  \/\/ \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 `video`  const { setVideo } = useSetters()   \/\/ \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 `video` \u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438  \/\/ \u043f\u0443\u0442\u0438 \u043a \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u043c\u0443 \u0444\u0430\u0439\u043b\u0443 \u0438 \u0441\u0430\u043c\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430  useEffect(() => {    if (fileUrl &amp;&amp; videoRef.current) {      setVideo(videoRef.current)    }  }, [fileUrl, setVideo])   \/\/ \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u0432\u044b\u0431\u043e\u0440\u0430 \u0444\u0430\u0439\u043b\u0430  const selectFile = (e) => {    if (e.target.files.length) {      const url = URL.createObjectURL(e.target.files[0])      setFileUrl(url)    }  }   \/\/ \u0438\u043d\u043f\u0443\u0442 \u0434\u043b\u044f \u0432\u044b\u0431\u043e\u0440\u0430 \u0444\u0430\u0439\u043b\u0430  const Input = () => (    &lt;div className='input video'>      &lt;label htmlFor='file'>Choose video file&lt;\/label>      &lt;input type='file' id='file' accept='video\/*' onChange={selectFile} \/>    &lt;\/div>  )   \/\/ \u043f\u0440\u0435\u0432\u044c\u044e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430  const File = () => (    &lt;div className='container video'>      &lt;div className='item video'>        &lt;video src={fileUrl} controls muted ref={videoRef} \/>      &lt;\/div>    &lt;\/div>  )   \/\/ \u0443\u0441\u043b\u043e\u0432\u043d\u044b\u0439 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433  return &lt;div className='selector video'>{fileUrl ? &lt;File \/> : &lt;Input \/>}&lt;\/div> }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0434\u043b\u044f \u0432\u044b\u0431\u043e\u0440\u0430 \u0430\u0443\u0434\u0438\u043e (<code>components\/AudioSelector.js<\/code>). \u0421\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u0430 \u0434\u0430\u043d\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0441\u043b\u043e\u0436\u043d\u0435\u0435 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0430\u0439\u043b\u043e\u0432, \u043d\u043e, \u0432 \u0446\u0435\u043b\u043e\u043c, \u0432\u0441\u0435 \u0442\u043e\u0436\u0435 \u0441\u0430\u043c\u043e\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import { useState, useEffect, useRef } from 'react' import { useSetters } from 'App'  export const AudioSelector = () => {  const [fileUrls, setFileUrls] = useState()  const inputRef = useRef()  const { setAudio } = useSetters()   useEffect(() => {    \/\/ \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u0444\u0430\u0439\u043b \u043f\u043e \u0441\u043f\u0438\u0441\u043a\u0443 \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438    if (inputRef.current) {      inputRef.current.click()    }  }, [fileUrls])   const selectFiles = (e) => {    if (e.target.files.length) {      const urls = [...e.target.files].map((f) => URL.createObjectURL(f))      setFileUrls(urls)    }  }   \/\/ \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u0432\u044b\u0431\u043e\u0440\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 `audio`  const selectAudio = (e) => {    setAudio(e.target.nextElementSibling)  }   const Input = () => (    &lt;div className='input audio'>      &lt;label htmlFor='file'>Choose audio files&lt;\/label>      &lt;input        type='file'        id='file'        accept='audio\/*'        multiple        onChange={selectFiles}      \/>    &lt;\/div>  )   const Files = () => (    &lt;div className='container audio'>      &lt;h2>Select audio&lt;\/h2>      {fileUrls?.map((u, i) => (        &lt;div key={i} className='item audio'>          &lt;input            type='radio'            name='audio'            onChange={selectAudio}            ref={i === 0 ? inputRef : null}          \/>          &lt;audio src={u} controls \/>        &lt;\/div>      ))}    &lt;\/div>  )   return (    &lt;div className='selector audio'>{fileUrls ? &lt;Files \/> : &lt;Input \/>}&lt;\/div>  ) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u0440\u0430\u0442\u043a\u043e \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0443\u0442\u0438\u043b\u0438\u0442\u0443 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0439 (<code>utils\/verifySupport.js<\/code>):<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ \u0443\u0442\u0438\u043b\u0438\u0442\u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043c\u0430\u0441\u0441\u0438\u0432 \u043d\u0435\u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \"\u0444\u0438\u0447\" export default function verifySupport() {  const unsupportedFeatures = []   if (    !('captureStream' in HTMLAudioElement.prototype) &amp;&amp;    !('mozCaptureStream' in HTMLAudioElement.prototype)  ) {    unsupportedFeatures.push('captureStream()')  }   ;[    'MediaStream',    'MediaRecorder',    'Blob',    'AudioContext',    'MediaStreamAudioSourceNode',    'MediaStreamAudioDestinationNode'  ].forEach((f) => {    if (!(f in window)) {      unsupportedFeatures.push(f)    }  })   return unsupportedFeatures }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u0441\u0430\u043c\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438.<\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0438 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0435\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 (<code>utils\/recording.js<\/code>).<\/p>\n<p>  <\/p>\n<p>\u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0443\u0442\u0438\u043b\u0438\u0442\u0443 \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435 (\u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u043c\u043e\u0434\u0443\u043b\u044f) \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import verifySupport from '.\/verifySupport'  let mediaChunks = [] let mediaRecorder let audioContext let mediaStreamAudioDestinationNode let mediaStreamAudioSourceNode<\/code><\/pre>\n<p>  <\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0437\u0430\u043f\u0438\u0441\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b `audio` \u0438 `video`, \u0430 \u0442\u0430\u043a\u0436\u0435 `timeslice` export const startRecording = ({ audio, video, timeslice = 250 }) => {  \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443  const unsupportedFeatures = verifySupport()  if (unsupportedFeatures.length)    return console.error(`${unsupportedFeatures.join(', ')} not supported`)   \/\/ \u0437\u0430\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u0442\u043e\u043a\u0438  const videoStream =     (video.captureStream &amp;&amp; video.captureStream()) || video.mozCaptureStream()   const audioStream =     (audio.captureStream &amp;&amp; audio.captureStream()) || audio.mozCaptureStream()   \/\/ \u0441\u043c. \u0432\u044b\u0448\u0435  audioContext = new AudioContext()  mediaStreamAudioDestinationNode = new MediaStreamAudioDestinationNode(    audioContext  )  mediaStreamAudioSourceNode = new MediaStreamAudioSourceNode(audioContext, {    mediaStream: audioStream  })  mediaStreamAudioSourceNode.connect(mediaStreamAudioDestinationNode)   \/\/ \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u043c \u043f\u043e\u0442\u043e\u043a\u0438  const mediaStream = new MediaStream([    ...videoStream.getVideoTracks(),    ...mediaStreamAudioDestinationNode.stream.getAudioTracks()  ])   \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \"\u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u0435\u043b\u044f\" \u043c\u0435\u0434\u0438\u0430,  \/\/ \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u044f \u0435\u043c\u0443 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a \u0438 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044f \u0442\u0438\u043f \u0434\u0430\u043d\u043d\u044b\u0445  mediaRecorder = new MediaRecorder(mediaStream, { mimeType: 'video\/webm' })   \/\/ \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u044c \u0434\u0430\u043d\u043d\u044b\u0445  mediaRecorder.ondataavailable = (e) => {    mediaChunks.push(e.data)  }   \/\/ \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u043c \u043e \u043d\u0430\u0447\u0430\u043b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438  console.log('*** Start recording')  \/\/ \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u044c  mediaRecorder.start(timeslice) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0437\u0430\u043f\u0438\u0441\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">export const stopRecording = () => {  \/\/ \u0435\u0441\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u044c \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b\u0430\u0441\u044c, \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u043c  if (!mediaRecorder) return   \/\/ \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u044c  console.log('*** Stop recording')  mediaRecorder.stop()   \/\/ \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 - \u0432\u0438\u0434\u0435\u043e \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 `WebM`  const result = new Blob(mediaChunks, { type: 'video\/webm' })   \/\/ \u043e\u0447\u0438\u0441\u0442\u043a\u0430  mediaRecorder = null  mediaChunks = []   \/\/ \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442  return result }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0437\u0430\u043c\u0435\u043d\u044b \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u0430\u0443\u0434\u0438\u043e\u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 `audio` export const replaceAudioInStream = (audio) => {  \/\/ \u0437\u0430\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0435\u043c \u043f\u043e\u0442\u043e\u043a  const audioStream = audio.captureStream()  \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0430\u0443\u0434\u0438\u043e \u0434\u0430\u043d\u043d\u044b\u0445  const newMediaStreamAudioSourceNode = new MediaStreamAudioSourceNode(    audioContext,    { mediaStream: audioStream }  )  \/\/ \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u043a \u0441\u0442\u0430\u0440\u043e\u043c\u0443 \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u0447\u0438\u043a\u0443  newMediaStreamAudioSourceNode.connect(mediaStreamAudioDestinationNode)  \/\/ \u043e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0441\u0442\u0430\u0440\u044b\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a  mediaStreamAudioSourceNode.disconnect()  \/\/ \u0440\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430  mediaStreamAudioSourceNode = newMediaStreamAudioSourceNode }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u043f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0438 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">export const pauseRecording = () => {  if (!mediaRecorder) return  console.log('*** Pause recording')  mediaRecorder.pause() }  export const resumeRecording = () => {  if (!mediaRecorder) return  console.log('*** Resume recording')  mediaRecorder.resume() }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438 (<code>components\/Recorder.js<\/code>).<\/p>\n<p>  <\/p>\n<p>\u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0445\u0443\u043a\u0438 \u0438 \u0443\u0442\u0438\u043b\u0438\u0442\u044b:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import { useState } from 'react' import { useSetters, useStore } from 'App' import { usePrevious } from 'hooks\/usePrevious'  import {  startRecording,  stopRecording,  pauseRecording,  resumeRecording,  replaceAudioInStream } from 'utils\/recording'  export const Recorder = () => {  \/\/ TODO }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u043c \u0441\u0435\u0442\u0442\u0435\u0440 \u0438 \u0447\u0430\u0441\u0442\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430, \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 <code>audio<\/code> \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u043b\u044f \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440\u0430 \u043f\u0430\u0443\u0437\u044b \u0438 \u043d\u0430\u0447\u0430\u043b\u0430 \u0437\u0430\u043f\u0438\u0441\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">const { setResult } = useSetters() const { audio, video } = useStore() const previousAudio = usePrevious(audio)  const [paused, setPaused] = useState(false) const [recordingStarted, setRecordingStarted] = useState(false)<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435\u043c \u0430\u0443\u0434\u0438\u043e \u0438 \u0432\u0438\u0434\u0435\u043e:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0442\u0438\u043f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 const toggleAudioVideo = (action) => {  switch (action) {    \/\/ \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435    case 'play': {      if (audio.paused) {        audio.play()      }      if (video.paused) {        video.play()      }      break    }    \/\/ \u043f\u0430\u0443\u0437\u0430    case 'pause': {      if (!audio.paused) {        audio.pause()      }      if (!video.paused) {        video.pause()      }      break    }    \/\/ \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430    \/\/ HTMLAudioElement.prototype \u0438 HTMLVideoElement.prototype    \/\/ \u043d\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u043c\u0435\u0442\u043e\u0434\u0430 `stop`    case 'stop': {      \/\/ \u0441\u0442\u0430\u0432\u0438\u043c \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043d\u0430 \u043f\u0430\u0443\u0437\u0443      toggleAudioVideo('pause')      \/\/ \u043e\u0431\u043d\u0443\u043b\u044f\u0435\u043c \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f      audio.currentTime = 0      video.currentTime = 0      break    }    default:      return  } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0437\u0430\u043f\u0438\u0441\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">const start = () => {  \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043d\u0430\u043b\u0438\u0447\u0438\u0435\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 `audio` \u0438 `video` \u0438 \u0442\u043e,  \/\/ \u0447\u0442\u043e \u0437\u0430\u043f\u0438\u0441\u044c \u0435\u0449\u0435 \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b\u0430\u0441\u044c  if (video &amp;&amp; audio &amp;&amp; !recordingStarted.current) {    \/\/ \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435    toggleAudioVideo('play')    \/\/ \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0443\u0442\u0438\u043b\u0438\u0442\u0435    startRecording({ audio, video })    \/\/ \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435    setRecordingStarted(true)  } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438\/\u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">const pauseResume = () => {  if (!paused) {    toggleAudioVideo('pause')    pauseRecording()  } else {    toggleAudioVideo('play')     \/\/ \u0435\u0441\u043b\u0438 \u043f\u0440\u0438 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442 `audio`    \/\/ \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430, \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043d\u043e\u0433\u043e \u0432 `previousAudio`,    \/\/ \u0437\u043d\u0430\u0447\u0438\u0442, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0430\u0443\u0434\u0438\u043e \u0434\u0430\u043d\u043d\u044b\u0445    if (previousAudio !== audio) {      console.log('*** New audio')      replaceAudioInStream(audio)    }     resumeRecording()  }  setPaused(!paused) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0437\u0430\u043f\u0438\u0441\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">const stop = () => {  toggleAudioVideo('stop')  const result = stopRecording()  setResult(result)  setRecordingStarted(false) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0443 \u0438, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">if (!audio || !video) return null  return (  &lt;div className='container recorder'>    {!recordingStarted ? (      &lt;button onClick={start} className='start'>        Start recording      &lt;\/button>    ) : (      &lt;>        &lt;button onClick={pauseResume} className={paused ? 'resume' : 'pause'}>          {paused ? 'Resume' : 'Pause'}        &lt;\/button>        &lt;button onClick={stop} className='stop'>          Stop        &lt;\/button>      &lt;\/>    )}  &lt;\/div> )<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u2014 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0437\u0430\u043f\u0438\u0441\u0438 (<code>components\/Result.js<\/code>):<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import { useStore } from 'App'  export function Result() {  const { result } = useStore()   if (!result) return null   const url = URL.createObjectURL(result)   return (    &lt;div className='container result'>      &lt;video src={url} controls>&lt;\/video>      &lt;a href={url} download={`${Date.now()}.webm`}>        Download      &lt;\/a>    &lt;\/div>  ) }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u0443\u043c\u0430\u044e, \u0442\u0443\u0442 \u0432\u0441\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e.<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0440\u0430\u0431\u043e\u0442\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>yarn start<\/code> \u0438\u043b\u0438 <code>npm start<\/code>:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/mr\/gq\/cc\/mrgqccgyflhdaohl1a8jbjbsdfu.png\" data-src=\"https:\/\/habrastorage.org\/webt\/mr\/gq\/cc\/mrgqccgyflhdaohl1a8jbjbsdfu.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u0412\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0438\u0434\u0435\u043e \u0438 \u0430\u0443\u0434\u0438\u043e\u0444\u0430\u0439\u043b\u044b:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/mq\/jf\/wu\/mqjfwu3mxcu0sivodl9ldr2kz0m.png\" data-src=\"https:\/\/habrastorage.org\/webt\/mq\/jf\/wu\/mqjfwu3mxcu0sivodl9ldr2kz0m.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 <code>Start recording<\/code>:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/rm\/su\/jb\/rmsujbrvtfvlbnq8hi6i5tphul4.png\" data-src=\"https:\/\/habrastorage.org\/webt\/rm\/su\/jb\/rmsujbrvtfvlbnq8hi6i5tphul4.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0438 \u0437\u0430\u043f\u0438\u0441\u044c \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c <code>Pause<\/code>, \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u0434\u0440\u0443\u0433\u043e\u0439 \u0430\u0443\u0434\u0438\u043e \u0444\u0430\u0439\u043b \u0438 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u043c <code>Resume<\/code>:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/yg\/df\/5f\/ygdf5frw6wwgaxdsyb_gcj6r3im.png\" data-src=\"https:\/\/habrastorage.org\/webt\/yg\/df\/5f\/ygdf5frw6wwgaxdsyb_gcj6r3im.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0436\u0438\u043c\u0430\u0435\u043c <code>Stop<\/code>:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/mt\/2j\/ms\/mt2jmszwbqdxhy6r0wyxkqy1qvy.png\" data-src=\"https:\/\/habrastorage.org\/webt\/mt\/2j\/ms\/mt2jmszwbqdxhy6r0wyxkqy1qvy.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0441\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043d\u0442, \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0435\u0432\u044c\u044e \u0438 \u0441\u0441\u044b\u043b\u043a\u0430 \u0434\u043b\u044f \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430.<\/p>\n<p>  <\/p>\n<p>\u0412\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043a\u0430\u043a \u043e\u0436\u0438\u0434\u0430\u0435\u0442\u0441\u044f.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u0436\u0430\u043b\u0443\u0439, \u044d\u0442\u043e \u0432\u0441\u0435, \u0447\u0435\u043c \u044f \u0445\u043e\u0442\u0435\u043b \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441 \u0432\u0430\u043c\u0438 \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435.<\/p>\n<p>  <\/p>\n<p>\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044e \u0437\u0430 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0438 happy coding!<\/p>\n<p>  <\/p>\n<p><a href=\"https:\/\/cloud.timeweb.com\/?utm_source=habr&amp;utm_medium=banner&amp;utm_campaign=cloud&amp;utm_content=direct&amp;utm_term=low\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/bh\/0m\/fv\/bh0mfviu_rma7be5uylpewumuxi.png\" data-src=\"https:\/\/habrastorage.org\/webt\/bh\/0m\/fv\/bh0mfviu_rma7be5uylpewumuxi.png\"\/><\/a><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/646831\/\"> https:\/\/habr.com\/ru\/articles\/646831\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/cm\/yu\/dk\/cmyudkffaaxue4r760lyvmate6i.png\" data-src=\"https:\/\/habrastorage.org\/webt\/cm\/yu\/dk\/cmyudkffaaxue4r760lyvmate6i.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0434\u0440\u0443\u0437\u044c\u044f!<\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u044e \u0438\u0441\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043f\u043e \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u043c\u0435\u0434\u0438\u0430, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0435 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430\u043c\u0438, \u0438 \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0432\u0430\u043c \u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0437\u0430\u0445\u0432\u0430\u0442\u0430 \u0438 \u0437\u0430\u043f\u0438\u0441\u0438 \u043c\u0435\u0434\u0438\u0430\u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0430\u0443\u0434\u0438\u043e \u0438 \u0432\u0438\u0434\u0435\u043e\u0444\u0430\u0439\u043b\u043e\u0432.<\/p>\n<p>  <\/p>\n<p>\u041c\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0430\u0443\u0434\u0438\u043e \u0438 \u0432\u0438\u0434\u0435\u043e \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u043e\u043c:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u043e\u0434\u043d\u043e \u0432\u0438\u0434\u0435\u043e \u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0430\u0443\u0434\u0438\u043e, \u0445\u0440\u0430\u043d\u044f\u0449\u0438\u0445\u0441\u044f \u0432 \u0435\u0433\u043e \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435;<\/li>\n<li>\u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u0442 \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 \u0434\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0437\u0430\u043f\u0438\u0441\u0438, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432, \u0437\u0430\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0438\u0445 \u043c\u0435\u0434\u0438\u0430\u043f\u043e\u0442\u043e\u043a\u0438;<\/li>\n<li>\u0437\u0430\u0445\u0432\u0430\u0447\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u0442\u043e\u043a\u0438 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u044e\u0442\u0441\u044f \u0432 \u043e\u0434\u0438\u043d \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u0437\u0430\u043f\u0438\u0441\u0438;<\/li>\n<li>\u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u043c\u0435\u043d\u044f\u0442\u044c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a \u0430\u0443\u0434\u0438\u043e\u0434\u0430\u043d\u043d\u044b\u0445;<\/li>\n<li>\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u0430\u0443\u0434\u0438\u043e\u0434\u0430\u043d\u043d\u044b\u0445) \u0438 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u044c;<\/li>\n<li>\u043f\u043e \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044e \u0437\u0430\u043f\u0438\u0441\u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432\u0438\u0434\u0435\u043e\u0444\u0430\u0439\u043b \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/WebM\"><code>WebM<\/code><\/a> \u2014 \u043f\u0440\u0435\u0432\u044c\u044e \u0441\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0430 \u0438 \u0441\u0441\u044b\u043b\u043a\u0430 \u0434\u043b\u044f \u0435\u0433\u043e \u0441\u043a\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u044f.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0434\u043b\u044f \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u044f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/ru.reactjs.org\/\"><code>React<\/code><\/a>, \u043e\u0434\u043d\u0430\u043a\u043e \u0432\u0441\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u043e \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u043c\u0435\u0434\u0438\u0430 \u0431\u0443\u0434\u0443\u0442 \u0430\u0432\u0442\u043e\u043d\u043e\u043c\u043d\u044b\u043c\u0438 (\u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u0430 \u044d\u0442\u0438\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0431\u0443\u0434\u0435\u0442 framework agnostic), \u0442\u0430\u043a \u0447\u0442\u043e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043b\u044e\u0431\u043e\u0439 \u0434\u0440\u0443\u0433\u043e\u0439 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0438\u043b\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c\u0441\u044f \u0447\u0438\u0441\u0442\u044b\u043c <code>JavaScript<\/code>.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u041f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0430:<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<div class=\"oembed\">\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/61e98b14abb378f6450d1bbd\" data-style=\"\" id=\"61e98b14abb378f6450d1bbd\" width=\"\"><\/div>\n<\/div>\n<\/div><\/div>\n<p>  <\/p>\n<p><a href=\"https:\/\/github.com\/harryheman\/Blog-Posts\/tree\/master\/capture-stream\">\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439<\/a>.<\/p>\n<p>  <\/p>\n<p>\u041e \u0442\u043e\u043c, \u043a\u0430\u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0430\u0443\u0434\u0438\u043e\u0437\u0430\u043c\u0435\u0442\u043e\u043a, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 <a href=\"https:\/\/habr.com\/ru\/company\/timeweb\/blog\/581086\/\">\u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a>, \u0430 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0437\u0430\u0445\u0432\u0430\u0442\u0430 \u0438 \u0437\u0430\u043f\u0438\u0441\u0438 \u044d\u043a\u0440\u0430\u043d\u0430 \u2014 \u0432 <a href=\"https:\/\/habr.com\/ru\/company\/timeweb\/blog\/591417\/\">\u044d\u0442\u043e\u0439<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u044d\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u043f\u0440\u043e\u0448\u0443 \u043f\u043e\u0434 \u043a\u0430\u0442.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-391567","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/391567","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=391567"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/391567\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=391567"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=391567"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=391567"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}