{"id":483065,"date":"2026-06-09T23:36:39","date_gmt":"2026-06-09T23:36:39","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=483065"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=483065","title":{"rendered":"\u0417\u0430\u043f\u0438\u0441\u044c \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0433\u043e \u0432\u0438\u0434\u0435\u043e \u0432 \u0440\u043e\u0443\u0442\u0435\u0440: MikroTik RouterOS Script"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d6f\/439\/c9c\/d6f439c9cda6067204b1fc5b9a7e3fb9.png\" width=\"780\" height=\"440\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/d6f\/439\/c9c\/d6f439c9cda6067204b1fc5b9a7e3fb9.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d6f\/439\/c9c\/d6f439c9cda6067204b1fc5b9a7e3fb9.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041e\u0434\u043d\u0430 \u0438\u0437 \u043c\u043e\u0438\u0445 IP \u043a\u0430\u043c\u0435\u0440 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u043b\u044f FTP \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u0430 \u0432 \u043d\u0435\u0433\u043e \u043f\u0438\u0441\u0430\u0442\u044c. \u0412 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u043c \u043e\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043f\u043e\u0442\u043e\u043a RTSP \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043c\u043e\u0436\u043d\u043e. \u041a\u0430\u043c\u0435\u0440\u0430 \u043f\u0438\u0441\u0430\u043b\u0430 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 DAV, \u0430 \u0440\u043e\u0443\u0442\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f.<\/p>\n<p> <code>\u0420\u043e\u0443\u0442\u0435\u0440 \u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439, \u0447\u0442\u043e \u043f\u0438\u0448\u0435\u0442 <\/code><a href=\"https:\/\/habr.com\/ru\/articles\/1033312\/\" rel=\"noopener noreferrer nofollow\"><code>\u043e\u043d\u043b\u0430\u0439\u043d \u0440\u0430\u0434\u0438\u043e \u0432 \u0441\u0435\u0431\u044f<\/code><\/a><code> \u0438 \u0434\u0435\u043b\u0430\u0435\u0442 \u0434\u0440\u0443\u0433\u0438\u0435 \u0431\u0435\u0437\u043e\u0431\u0440\u0430\u0437\u0438\u044f. \u041d\u0430\u0434\u043e \u0431\u044b \u0435\u043c\u0443, \u043d\u0430\u0432\u0435\u0440\u043d\u043e, \u0443\u0436\u0435 \u0438\u043c\u044f \u0434\u0430\u0442\u044c.<\/code> <\/p>\n<p>\u0410 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0442\u0430\u043a: rtsp \u0438\u0437 \u043a\u0430\u043c\u0435\u0440\u044b, \u0432 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e\u0435 \u043e\u0431\u043b\u0430\u043a\u043e, \u0438\u0437 \u043e\u0431\u043b\u0430\u043a\u0430 m4s \u043a\u0443\u0441\u043a\u0438 \u0432 \u0440\u043e\u0443\u0442\u0435\u0440 \u0438 \u043f\u043e\u0442\u043e\u043c ffmpeg \u0441\u043a\u043b\u0435\u0438\u0442 \u0438\u0445 \u0432 mp4 \u043d\u0430 \u043a\u043e\u043c\u043f\u0435.<\/p>\n<p>\u0411\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u043c \u043e\u0431\u043b\u0430\u043a\u043e\u043c \u0431\u0443\u0434\u0435\u0442 rtsp.me, \u043f\u0440\u0430\u0432\u0434\u0430, \u0443 \u043c\u0435\u043d\u044f \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u043a\u0430\u0447\u0430\u0442\u044c HD \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 (2048&#215;1536). \u0418\u0445 \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0441\u043b\u0430\u0442\u044c 6 \u0441\u0435\u043a\u0443\u043d\u0434\u043d\u044b\u0435 \u043a\u0443\u0441\u043a\u0438 \u0440\u0430\u0437 \u0432 30-40 \u0441\u0435\u043a\u0443\u043d\u0434, \u043d\u0443 \u0447\u0442\u043e \u044d\u0442\u043e \u0442\u0430\u043a\u043e\u0435. \u0410 \u043c\u043e\u0436\u0435\u0442 \u0438 \u043a\u0430\u043c\u0435\u0440\u0430 \u0432\u0438\u043d\u043e\u0432\u0430\u0442\u0430. \u0412\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0431\u0443\u0434\u0435\u043c \u043a\u0430\u0447\u0430\u0442\u044c, \u0447\u0442\u043e \u0435\u0441\u0442\u044c, \u0434\u043e\u043f. \u043f\u043e\u0442\u043e\u043a  704\u0445576.  \u0427\u0442\u043e\u0431 \u0434\u0432\u0430 \u0440\u0430\u0437\u0430 \u043d\u0435 \u0432\u0441\u0442\u0430\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0438\u0448\u0435\u043c \u0438 IPTV \u043a\u0430\u043a\u043e\u0439 \u043d\u0438\u0431\u0443\u0434\u044c, \u0442\u0430\u043c \u0441\u043a\u0440\u0438\u043f\u0442 \u0435\u0449\u0451 \u043f\u0440\u043e\u0449\u0435 \u0438 \u0442\u044f\u043d\u0435\u0442 1920&#215;1080.<\/p>\n<p>\u041f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u043d\u0443\u0436\u043d\u0430 \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0432\u0430\u0448\u0443 \u0442\u0440\u0430\u043d\u0441\u043b\u044f\u0446\u0438\u044e \u0432 \u043e\u0431\u043b\u0430\u043a\u0435, \u0442\u0430\u043a\u043e\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0430 <code>https:\/\/rtsp.me\/embed\/kB0DezA0\/<\/code><\/p>\n<p>\u0418\u0437 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043f\u043e \u044d\u0442\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0435 \u043c\u044b \u043f\u0430\u0440\u0441\u0438\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430&#8230; \u043f\u043b\u0435\u0439\u043b\u0438\u0441\u0442 \u043f\u043e\u0445\u043e\u0436\u0435, \u0442\u0430\u043a\u043e\u0433\u043e \u0432\u0438\u0434\u0430  <em>https:\/\/spb.rtsp.me\/twZbVylpWvRB88822cHJuA\/1781030350\/hls\/kB0DezA0.m3u8?ip=41.109.233.11 <\/em> <\/p>\n<p>\u0420\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u043c \u0435\u0451 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0447\u0430\u0441\u0442\u044c, ID \u0438 \u0445\u0432\u043e\u0441\u0442\u0438\u043a \u0441 \u043d\u0430\u0448\u0438\u043c IP. \u0420\u0430\u0437\u043e\u0431\u0440\u0430\u0432 \u0441\u0441\u044b\u043b\u043a\u0443, \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c \u0432 \u0446\u0438\u043a\u043b\u0435 \u043f\u043b\u0435\u0439\u043b\u0438\u0441\u0442 \u0438 \u043a\u0430\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u0447\u0430\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u0449\u0451 \u043d\u0435 \u0441\u043a\u0430\u0447\u0430\u043d\u044b. \u041c\u0435\u0436\u0434\u0443 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430\u043c\u0438 \u0447\u0430\u0441\u0442\u0435\u0439 \u0434\u0435\u043b\u0430\u0435\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0443\u044e \u043f\u0430\u0443\u0437\u0443, \u043c\u0435\u0436\u0434\u0443 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430\u043c\u0438 \u043f\u043b\u0435\u0439\u043b\u0438\u0441\u0442\u043e\u0432 \u0442\u043e\u0436\u0435. \u041f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0441\u0442\u043e\u0438\u0442 \u043f\u0430\u0443\u0437\u0430 10 \u0441\u0435\u043a\u0443\u043d\u0434 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0441\u0435\u0440\u0432\u0435\u0440 \u0445\u043e\u0442\u044f \u0431\u044b \u043d\u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043e\u0442\u0432\u0435\u0442\u0438\u043b \u043d\u0435 403, \u0430 \u043f\u043b\u0435\u0439\u043b\u0438\u0441\u0442\u043e\u043c. \u0412 \u0446\u0435\u043b\u043e\u043c \u043f\u0430\u0443\u0437\u044b, \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043f\u043e\u0434\u043e\u0431\u0440\u0430\u043d\u044b \u0443\u0434\u0430\u0447\u043d\u043e. \u042f \u0431\u044b \u0438\u0445 \u043d\u0435 \u043c\u0435\u043d\u044f\u043b.  <\/p>\n<p>\u0421\u043a\u0440\u0438\u043f\u0442 rtspRecorder<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">:local rtspMeUrl \"https:\/\/rtsp.me\/embed\/kB0DezA0\/\":local diskSlot \"usb1\":local freeSpace (([\/disk print as-value where slot=$diskSlot]-&gt;0)-&gt;\"free\")# \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0434\u0438\u0441\u043a \u0438 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e, \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\u0435 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e (100 MB):if (([:len \"$freeSpace\"] = 0) || ($freeSpace &lt; 104857600)) do={    :log warning (\"low disk space on \" . $diskSlot)    :quit}:local getFolderPath do={    :local sDate [\/system clock get date]    :local sTime [\/system clock get time]    :return (\"usb1\/cam_video\/\" . [:pick $sDate 0 4] . [:pick $sDate 5 7] . [:pick $sDate 8 10] . \"\/\" . [:pick $sTime 0 2])}:local videoDateFolder [$getFolderPath]:do {    :local rtspMeUrlHtml ([\/tool fetch url=$rtspMeUrl output=user as-value]-&gt;\"data\")    :local streamLinkStartMarker \".get('\"    :local streamLinkEndMarker \"')\"    :local startMarkerPos [:find $rtspMeUrlHtml $streamLinkStartMarker]    :if ([:len $startMarkerPos] != 0) do={        :set startMarkerPos ($startMarkerPos + [:len $streamLinkStartMarker])        :local endMarkerPos [:find $rtspMeUrlHtml $streamLinkEndMarker $startMarkerPos]        :if ([:len $endMarkerPos] != 0) do={            :local hlsUrl [:pick $rtspMeUrlHtml $startMarkerPos $endMarkerPos]            #:log warning \"HLS_Parser SUCCESS! Found URL: $hlsUrl\"                        # \u0412\u042b\u0420\u0415\u0417\u0410\u0415\u041c \u0411\u0410\u0417\u041e\u0412\u042b\u0419 URL, ID \u041f\u041e\u0422\u041e\u041a\u0410 \u0418 \u041f\u0410\u0420\u0410\u041c\u0415\u0422\u0420\u042b            :local hlsPathMarker \"\/hls\/\"            :local hlsPathPos [:find $hlsUrl $hlsPathMarker]                        # \u0412\u044b\u0440\u0435\u0437\u0430\u0435\u043c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 URL            :local baseUrl [:pick $hlsUrl 0 ($hlsPathPos + [:len $hlsPathMarker])]                        # \u0412\u044b\u0440\u0435\u0437\u0430\u0435\u043c ID \u043f\u043e\u0442\u043e\u043a\u0430            :local m3u8Pos [:find $hlsUrl \".m3u8\"]            :local streamId [:pick $hlsUrl ($hlsPathPos + 5) $m3u8Pos]                        # \u0412\u044b\u0440\u0435\u0437\u0430\u0435\u043c GET-\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b            :local paramPos [:find $hlsUrl \"?\"]            :local urlParams \"\"            :if ([:len $paramPos] != 0) do={                :set urlParams [:pick $hlsUrl $paramPos [:len $hlsUrl]]            }            :local playlistContent            :local startPosMsLink            :local endPosMsLink            :set playlistContent ([\/tool fetch url=$hlsUrl  output=user as-value]-&gt;\"data\")            :delay 10s            :local hasChunks true            :local hasChunk true            :local playlistDelay 2            :while ($hasChunks) do={                :set videoDateFolder [$getFolderPath]                :local baseFileLocalPath ($videoDateFolder . \"\/\" . $streamId . \".mp4\")                :if ([:len [\/file find where name=$baseFileLocalPath]] = 0) do={                    :set freeSpace (([\/disk print as-value where slot=$diskSlot]-&gt;0)-&gt;\"free\")                    :if (([:len \"$freeSpace\"] = 0) || ($freeSpace &lt; 104857600)) do={                        :log warning (\"low disk space on \" . $diskSlot)                        :quit                    }                    :delay 1s                    \/tool fetch url=($baseUrl . $streamId . \".mp4\") dst-path=$baseFileLocalPath keep-result=yes                }                :delay $playlistDelay                :set playlistContent ([\/tool fetch url=$hlsUrl output=user as-value]-&gt;\"data\")                #:log warning (\"playlistContent : \" . $playlistContent)                :local searchPosPointer 0                :local startPosMsLink [:find $playlistContent ($streamId . \"-\") $searchPosPointer]                :if ([:len $startPosMsLink] = 0) do={                    :log info (\"No Links in List\")                    :set hasChunks false                    :set hasChunk false                } else={                    :set hasChunk true                }                :local downloadedCount 0                :while ($hasChunk) do={                    :local endPosMsLink [:find $playlistContent \"\\n\" $startPosMsLink]                    :local segmentFile [:pick $playlistContent $startPosMsLink $endPosMsLink]                    #:log info (\"Found chunk: \" . $segmentFile)                    :local chunkFileLocalPath ($videoDateFolder . \"\/\" . $segmentFile)                    :if ([:len [\/file find where name=$chunkFileLocalPath]] = 0) do={                        :local chunkFileUrl ($baseUrl . $segmentFile)                        :log warning (\"Downloading: \" . $chunkFileUrl)                        :do {                            :set freeSpace (([\/disk print as-value where slot=$diskSlot]-&gt;0)-&gt;\"free\")                            :if (([:len \"$freeSpace\"] = 0) || ($freeSpace &lt; 104857600)) do={                                :log warning (\"low disk space on \" . $diskSlot)                                :quit                            }                            :delay 1                            \/tool fetch url=$chunkFileUrl dst-path=$chunkFileLocalPath keep-result=yes                            :set downloadedCount ($downloadedCount + 1)                        } on-error={                            :log warning (\"Failed to download chunk: \" . $chunkFileUrl)                        }                    }                    :set searchPosPointer ($endPosMsLink + 1)                    :set startPosMsLink [:find $playlistContent ($streamId . \"-\") $searchPosPointer]                    :if ([:len $startPosMsLink] = 0) do={                        :log info (\"End Links\")                        :set hasChunk false                    }                }                :if ($hasChunks) do={                    :if ($downloadedCount &gt; 0) do={                        :local calculatedDelay (10 - (2 * $downloadedCount))                        :if ($calculatedDelay &lt; 2) do={                            :set calculatedDelay 2                        }                        :set playlistDelay $calculatedDelay                        :log info \"HLS_Parser: Downloaded $downloadedCount chunks. Next playlist check in $playlistDelay s.\"                    } else={                        :set playlistDelay 10                        :log info \"HLS_Parser: No NEW chunks in playlist. Cooling down for 6s.\"                    }                }            }            :log info \"HLS_Parser: All segments from current playlist verified.\"        } else={            :log error \"HLS_Parser: End marker not found.\"        }    } else={        :log error \"HLS_Parser: Start marker not found on page.\"    }} on-error={    :log error (\"HLS_Parser ERROR: \")}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u041f\u043e \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u0438 \u0441\u043a\u0440\u0438\u043f\u0442 \u0432 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0441 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u043e\u0439. \u041a\u0430\u0436\u0434\u044b\u0435 15 \u0441\u0435\u043a\u0443\u043d\u0434<\/p>\n<pre><code class=\"java\">:if ([:len [\/system script job find script=rtspRecorder]] = 0) do={    \/system script run rtspRecorder} else={    :log warning \"\u0421\u043a\u0440\u0438\u043f\u0442 rtspRecorder \u0443\u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\"}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041e\u043d \u043f\u0438\u0448\u0435\u0442 \u043d\u0430 \u0434\u0438\u0441\u043a usb1, \u0432 \u043f\u0430\u043f\u043a\u0443 <code>usb1\/cam_video\/\u0413\u043e\u0434\u041c\u0435\u0441\u044f\u0446\u0414\u0435\u043d\u044c\/\u0427\u0430\u0441<\/code>  , \u043f\u0438\u0448\u0435\u0442 \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u043e, \u043f\u043e\u043a\u0430 \u0435\u0441\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0438 \u043f\u0430\u043c\u044f\u0442\u044c \u043d\u0430 \u0434\u0438\u0441\u043a\u0435. \u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432\u0438\u0434\u0435\u043e, \u043a\u0430\u0447\u0430\u0435\u043c \u0438\u0437 \u0440\u043e\u0443\u0442\u0435\u0440\u0430 \u043f\u0430\u043f\u043a\u0443 \u0441 \u043d\u0443\u0436\u043d\u044b\u043c \u0447\u0430\u0441\u043e\u043c, \u043a\u043b\u0430\u0434\u0451\u043c \u0432 \u044d\u0442\u0443 \u0436\u0435 \u043f\u0430\u043f\u043a\u0443 \u0444\u0430\u0439\u043b ffmpeg.exe. \u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 \u043f\u0440\u044f\u043c\u043e \u0432 \u044d\u0442\u043e\u0439 \u043f\u0430\u043f\u043a\u0435. <span class=\"habrahidden\">\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0432 \u0430\u0434\u0440\u0435\u0441\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0435 \u043f\u0440\u043e\u0432\u043e\u0434\u043d\u0438\u043a\u0430 cmd \u0438 \u043d\u0430\u0436\u043c\u0438\u0442\u0435 Enter<\/span>   \u0418 \u0432\u0432\u043e\u0434\u0438\u043c \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0434\u0432\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b. <code>kB0DezA0 <\/code> \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u0445, \u044d\u0442\u043e ID \u043f\u043e\u0442\u043e\u043a\u0430, \u0443 \u0432\u0430\u0441 \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0434\u0440\u0443\u0433\u043e\u0439.<\/p>\n<pre><code class=\"java\">copy \/b kB0DezA0.mp4 + kB0DezA0-*.m4s merged_raw.mp4ffmpeg -i merged_raw.mp4 -c copy ready_video.mp4<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0424\u0430\u0439\u043b ready_video.mp4 \u043d\u0430\u0434\u043e \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u043c\u043e\u0436\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c.<\/p>\n<p>\u0421 IPTV \u0434\u0435\u043b\u043e \u043e\u0431\u0441\u0442\u043e\u0438\u0442 \u0435\u0449\u0451 \u043f\u0440\u043e\u0449\u0435, \u044f \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b \u043a\u0430\u0447\u0430\u0442\u044c SD \u0438 HD \u043a\u0430\u043d\u0430\u043b, \u043a\u0430\u0447\u0430\u044e\u0442\u0441\u044f \u043e\u0431\u0430. \u0412\u043e\u0442 \u0435\u0441\u0442\u044c \u043a\u0430\u043a\u043e\u0439 \u0442\u043e \u043a\u0430\u043d\u0430\u043b<\/p>\n<pre><code class=\"java\">#EXTINF:-1 tvg-id=\"360.ru@SD\",360\u00b0 (1080p)https:\/\/cdn-evacoder-tv.facecast.io\/evacoder_hls_hi\/CkxfR1xNUAJwTgtXTBZTAJli\/index.m3u8<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041e\u043d \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0432 \u0442\u0430\u043a\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435<\/p>\n<pre><code class=\"java\">#EXTM3U#EXT-X-MEDIA-SEQUENCE:5485341#EXT-X-TARGETDURATION:11#EXTINF:10,0_5485236.ts#EXTINF:10,0_5485237.ts#EXTINF:10,0_5485238.ts#EXTINF:10,0_5485239.ts#EXTINF:10,0_5485240.ts<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0418 \u0441\u043a\u0440\u0438\u043f\u0442 \u0434\u043b\u044f \u043d\u0435\u0433\u043e<\/p>\n<p>\u0421\u043a\u0440\u0438\u043f\u0442 hdIptvRecorder<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">:local iptvBaseUrl \"https:\/\/cdn-evacoder-tv.facecast.io\/evacoder_hls_hi\/CkxfR1xNUAJwTgtXTBZTAJli\/\":local iptvListUrl ($iptvBaseUrl . \"0.m3u8\"):local diskSlot \"usb1\":local freeSpace (([\/disk print as-value where slot=$diskSlot]-&gt;0)-&gt;\"free\")# \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0434\u0438\u0441\u043a \u0438 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e, \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\u0435 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e (100 MB):if (([:len \"$freeSpace\"] = 0) || ($freeSpace &lt; 104857600)) do={    :log warning (\"low disk space on \" . $diskSlot)    :quit}:local getFolderPath do={    :local sDate [\/system clock get date]    :local sTime [\/system clock get time]    :return (\"usb1\/hd_iptv_channel\/\" . [:pick $sDate 0 4] . [:pick $sDate 5 7] . [:pick $sDate 8 10] . \"\/\" . [:pick $sTime 0 2])}:local videoDateFolder [$getFolderPath]:do {    :local playlistContent    :local startPosTsLink    :local endPosTsLink    :local hasChunks true    :local hasChunk true    :local playlistDelay 1    :while ($hasChunks) do={        :delay $playlistDelay        :set playlistContent ([\/tool fetch url=$iptvListUrl output=user as-value]-&gt;\"data\")        #:log warning (\"playlistContent : \" . $playlistContent)        :local searchPosPointer 0        :local startPosTsLink [:find $playlistContent (\"0_\") $searchPosPointer]        :if ([:len $startPosTsLink] = 0) do={            :log info (\"No Links in List\")            :set hasChunks false            :set hasChunk false        } else={            :set hasChunk true        }        :local downloadedCount 0        :while ($hasChunk) do={            :local endPosTsLink [:find $playlistContent \"\\n\" $startPosTsLink]            :local segmentFile [:pick $playlistContent $startPosTsLink $endPosTsLink]            #:log info (\"Found chunk: \" . $segmentFile)            :set videoDateFolder [$getFolderPath]            :local chunkFileLocalPath ($videoDateFolder . \"\/\" . $segmentFile)            :if ([:len [\/file find where name=$chunkFileLocalPath]] = 0) do={                :set freeSpace (([\/disk print as-value where slot=$diskSlot]-&gt;0)-&gt;\"free\")                :if (([:len \"$freeSpace\"] = 0) || ($freeSpace &lt; 104857600)) do={                    :log warning (\"low disk space on \" . $diskSlot)                    :quit                }                :local chunkFileUrl ($iptvBaseUrl . $segmentFile)                :log warning (\"Downloading: \" . $chunkFileUrl)                :do {                    :delay 1                    \/tool fetch url=$chunkFileUrl dst-path=$chunkFileLocalPath keep-result=yes                    :set downloadedCount ($downloadedCount + 1)                } on-error={                    :log warning (\"Failed to download chunk: \" . $chunkFileUrl)                }            }            :set searchPosPointer ($endPosTsLink + 1)            :set startPosTsLink [:find $playlistContent (\"0_\") $searchPosPointer]            :if ([:len $startPosTsLink] = 0) do={                :log info (\"End Links\")                :set hasChunk false            }        }        :if ($hasChunks) do={            :if ($downloadedCount &gt; 0) do={                :local calculatedDelay (10 - (2 * $downloadedCount))                :if ($calculatedDelay &lt; 2) do={                    :set calculatedDelay 1                }                :set playlistDelay $calculatedDelay                :log info \"HLS_Parser: Downloaded $downloadedCount chunks. Next playlist check in $playlistDelay s.\"            } else={                :set playlistDelay 10                :log info \"HLS_Parser: No NEW chunks in playlist. Cooling down for 6s.\"            }        }    }    :log info \"HLS_Parser: All segments from current playlist verified.\"} on-error={    :log error (\"HLS_Parser ERROR: \")}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<p>\u0421\u043a\u0440\u0438\u043f\u0442 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0442\u0430\u043a \u0436\u0435 \u0432 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0435, \u0440\u0430\u0437 \u0432 15 \u0441\u0435\u043a\u0443\u043d\u0434 \u0441 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u043e\u0439. \u041a\u0430\u0447\u0430\u0435\u0442 \u0442\u0430\u043a \u0436\u0435, \u0432 \u043f\u0430\u043f\u043a\u0438 \u0441 \u0434\u0430\u0442\u043e\u0439 \u0438 \u0447\u0430\u0441\u043e\u043c. \u0421\u043a\u043b\u0435\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0435\u0449\u0451 \u043f\u0440\u043e\u0449\u0435, \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u043c\u0438<\/p>\n<pre><code class=\"java\">copy \/b *.ts merged.tsffmpeg -i merged.ts -c copy ready_video.mp4<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0418 \u0442\u0430\u043a \u0436\u0435 \u0441\u043c\u043e\u0442\u0440\u0438\u043c ready_video.mp4 , \u0430 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u043f\u043e\u0441\u043b\u0435 \u0441\u043a\u043b\u0435\u0438\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>\u0414\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u043a\u0430\u043d\u0430\u043b\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u0432 \u0442\u0430\u043a\u043e\u043c \u0436\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u0430\u043d\u0430\u043b<\/p>\n<pre><code class=\"java\">#EXTINF:-1 tvg-id=\"\",Gaki no Tsukai (English Subs) (720p)https:\/\/hamada.gaki-no-tsukai.stream\/hls\/test.m3u8<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0441 \u043e\u0442\u0432\u0435\u0442\u043e\u043c<\/p>\n<pre><code class=\"java\">#EXTM3U#EXT-X-VERSION:3#EXT-X-MEDIA-SEQUENCE:2479#EXT-X-TARGETDURATION:11#EXTINF:3.567,test-2479.ts#EXTINF:6.033,test-2480.ts#EXTINF:8.334,test-2481.ts#EXTINF:3.333,test-2482.ts<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0432 \u0441\u043a\u0440\u0438\u043f\u0442\u0435 \u043d\u0430\u0434\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0441\u044b\u043b\u043a\u0443, \u0440\u0430\u0437\u0440\u0435\u0437\u0430\u0432 \u0435\u0451 \u043d\u0430 \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u0438 \u0445\u0432\u043e\u0441\u0442\u0438\u043a.<br \/>\u0418 \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u0432 2\u0445 \u043c\u0435\u0441\u0442\u0430\u0445 \u043c\u0430\u0440\u043a\u0435\u0440 \u043f\u043e\u0438\u0441\u043a\u0430 \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0447\u0430\u0441\u0442\u044c, \u0442\u043e \u0435\u0441\u0442\u044c \u0438\u0441\u043a\u0430\u0442\u044c \u043d\u0435 <code>0_ <\/code>, \u0430 <code>test- <\/code>  \u0438 \u0432\u0441\u0451.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u043d\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0442\u043e \u0432\u043e\u0442 \u0442\u0430\u043a<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">:local iptvBaseUrl \"https:\/\/hamada.gaki-no-tsukai.stream\/hls\/\":local iptvListUrl ($iptvBaseUrl . \"test.m3u8\"):local diskSlot \"usb1\":local freeSpace (([\/disk print as-value where slot=$diskSlot]-&gt;0)-&gt;\"free\")# \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0434\u0438\u0441\u043a \u0438 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e, \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\u0435 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e (100 MB):if (([:len \"$freeSpace\"] = 0) || ($freeSpace &lt; 104857600)) do={    :log warning (\"low disk space on \" . $diskSlot)    :quit}:local getFolderPath do={    :local sDate [\/system clock get date]    :local sTime [\/system clock get time]    :return (\"usb1\/iptv_channel\/\" . [:pick $sDate 0 4] . [:pick $sDate 5 7] . [:pick $sDate 8 10] . \"\/\" . [:pick $sTime 0 2])}:local videoDateFolder [$getFolderPath]:do {    :local playlistContent    :local startPosTsLink    :local endPosTsLink    :local hasChunks true    :local hasChunk true    :local playlistDelay 1    :while ($hasChunks) do={        :delay $playlistDelay        :set playlistContent ([\/tool fetch url=$iptvListUrl output=user as-value]-&gt;\"data\")        #:log warning (\"playlistContent : \" . $playlistContent)        :local searchPosPointer 0        :local startPosTsLink [:find $playlistContent (\"test-\") $searchPosPointer]        :if ([:len $startPosTsLink] = 0) do={            :log info (\"No Links in List\")            :set hasChunks false            :set hasChunk false        } else={            :set hasChunk true        }        :local downloadedCount 0        :while ($hasChunk) do={            :local endPosTsLink [:find $playlistContent \"\\n\" $startPosTsLink]            :local segmentFile [:pick $playlistContent $startPosTsLink $endPosTsLink]            #:log info (\"Found chunk: \" . $segmentFile)            :set videoDateFolder [$getFolderPath]            :local chunkFileLocalPath ($videoDateFolder . \"\/\" . $segmentFile)            :if ([:len [\/file find where name=$chunkFileLocalPath]] = 0) do={                :set freeSpace (([\/disk print as-value where slot=$diskSlot]-&gt;0)-&gt;\"free\")                :if (([:len \"$freeSpace\"] = 0) || ($freeSpace &lt; 104857600)) do={                    :log warning (\"low disk space on \" . $diskSlot)                    :quit                }                :local chunkFileUrl ($iptvBaseUrl . $segmentFile)                :log warning (\"Downloading: \" . $chunkFileUrl)                :do {                    :delay 1                    \/tool fetch url=$chunkFileUrl dst-path=$chunkFileLocalPath keep-result=yes                    :set downloadedCount ($downloadedCount + 1)                } on-error={                    :log warning (\"Failed to download chunk: \" . $chunkFileUrl)                }            }            :set searchPosPointer ($endPosTsLink + 1)            :set startPosTsLink [:find $playlistContent (\"test-\") $searchPosPointer]            :if ([:len $startPosTsLink] = 0) do={                :log info (\"End Links\")                :set hasChunk false            }        }        :if ($hasChunks) do={            :if ($downloadedCount &gt; 0) do={                :local calculatedDelay (10 - (2 * $downloadedCount))                :if ($calculatedDelay &lt; 2) do={                    :set calculatedDelay 1                }                :set playlistDelay $calculatedDelay                :log info \"HLS_Parser: Downloaded $downloadedCount chunks. Next playlist check in $playlistDelay s.\"            } else={                :set playlistDelay 10                :log info \"HLS_Parser: No NEW chunks in playlist. Cooling down for 6s.\"            }        }    }    :log info \"HLS_Parser: All segments from current playlist verified.\"} on-error={    :log error (\"HLS_Parser ERROR: \")}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<\/div>\n<\/details>\n<\/div>\n<p>\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\/1045708\/\">https:\/\/habr.com\/ru\/articles\/1045708\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u041e\u0434\u043d\u0430 \u0438\u0437 \u043c\u043e\u0438\u0445 IP \u043a\u0430\u043c\u0435\u0440 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u043b\u044f FTP \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u0430 \u0432 \u043d\u0435\u0433\u043e \u043f\u0438\u0441\u0430\u0442\u044c. \u0412 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u043c \u043e\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043f\u043e\u0442\u043e\u043a RTSP \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043c\u043e\u0436\u043d\u043e. \u041a\u0430\u043c\u0435\u0440\u0430 \u043f\u0438\u0441\u0430\u043b\u0430 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 DAV, \u0430 \u0440\u043e\u0443\u0442\u0435\u0440 \u0431\u0443\u0434\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f. \u0420\u043e\u0443\u0442\u0435\u0440 \u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439, \u0447\u0442\u043e \u043f\u0438\u0448\u0435\u0442 \u043e\u043d\u043b\u0430\u0439\u043d \u0440\u0430\u0434\u0438\u043e \u0432 \u0441\u0435\u0431\u044f \u0438 \u0434\u0435\u043b\u0430\u0435\u0442 \u0434\u0440\u0443\u0433\u0438\u0435 \u0431\u0435\u0437\u043e\u0431\u0440\u0430\u0437\u0438\u044f. \u041d\u0430\u0434\u043e \u0431\u044b \u0435\u043c\u0443, \u043d\u0430\u0432\u0435\u0440\u043d\u043e, \u0443\u0436\u0435 \u0438\u043c\u044f \u0434\u0430\u0442\u044c. \u0410 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0442\u0430\u043a: rtsp \u0438\u0437 \u043a\u0430\u043c\u0435\u0440\u044b, \u0432 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e\u0435 \u043e\u0431\u043b\u0430\u043a\u043e, \u0438\u0437 \u043e\u0431\u043b\u0430\u043a\u0430 m4s \u043a\u0443\u0441\u043a\u0438 \u0432 \u0440\u043e\u0443\u0442\u0435\u0440 \u0438 \u043f\u043e\u0442\u043e\u043c ffmpeg \u0441\u043a\u043b\u0435\u0438\u0442 \u0438\u0445 \u0432 mp4 \u043d\u0430 \u043a\u043e\u043c\u043f\u0435.\u0411\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u043c \u043e\u0431\u043b\u0430\u043a\u043e\u043c \u0431\u0443\u0434\u0435\u0442 rtsp.me, \u043f\u0440\u0430\u0432\u0434\u0430, \u0443 \u043c\u0435\u043d\u044f \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u043a\u0430\u0447\u0430\u0442\u044c HD \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 (2048&#215;1536). \u0418\u0445 \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0441\u043b\u0430\u0442\u044c 6 \u0441\u0435\u043a\u0443\u043d\u0434\u043d\u044b\u0435 \u043a\u0443\u0441\u043a\u0438 \u0440\u0430\u0437 \u0432 30-40 \u0441\u0435\u043a\u0443\u043d\u0434, \u043d\u0443 \u0447\u0442\u043e \u044d\u0442\u043e \u0442\u0430\u043a\u043e\u0435. \u0410 \u043c\u043e\u0436\u0435\u0442 \u0438 \u043a\u0430\u043c\u0435\u0440\u0430 \u0432\u0438\u043d\u043e\u0432\u0430\u0442\u0430. \u0412\u0441\u0451 \u0440\u0430\u0432\u043d\u043e \u0431\u0443\u0434\u0435\u043c \u043a\u0430\u0447\u0430\u0442\u044c, \u0447\u0442\u043e \u0435\u0441\u0442\u044c, \u0434\u043e\u043f. \u043f\u043e\u0442\u043e\u043a  704\u0445576.  \u0427\u0442\u043e\u0431 \u0434\u0432\u0430 \u0440\u0430\u0437\u0430 \u043d\u0435 \u0432\u0441\u0442\u0430\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0438\u0448\u0435\u043c \u0438 IPTV \u043a\u0430\u043a\u043e\u0439 \u043d\u0438\u0431\u0443\u0434\u044c, \u0442\u0430\u043c \u0441\u043a\u0440\u0438\u043f\u0442 \u0435\u0449\u0451 \u043f\u0440\u043e\u0449\u0435 \u0438 \u0442\u044f\u043d\u0435\u0442 1920&#215;1080.\u041f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u043d\u0443\u0436\u043d\u0430 \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0432\u0430\u0448\u0443 \u0442\u0440\u0430\u043d\u0441\u043b\u044f\u0446\u0438\u044e \u0432 \u043e\u0431\u043b\u0430\u043a\u0435, \u0442\u0430\u043a\u043e\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0430 https:\/\/rtsp.me\/embed\/kB0DezA0\/\u0418\u0437 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043f\u043e \u044d\u0442\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0435 \u043c\u044b \u043f\u0430\u0440\u0441\u0438\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430&#8230; \u043f\u043b\u0435\u0439\u043b\u0438\u0441\u0442 \u043f\u043e\u0445\u043e\u0436\u0435, \u0442\u0430\u043a\u043e\u0433\u043e \u0432\u0438\u0434\u0430  https:\/\/spb.rtsp.me\/twZbVylpWvRB88822cHJuA\/1781030350\/hls\/kB0DezA0.m3u8?ip=41.109.233.11  \u0420\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u043c \u0435\u0451 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0447\u0430\u0441\u0442\u044c, ID \u0438 \u0445\u0432\u043e\u0441\u0442\u0438\u043a \u0441 \u043d\u0430\u0448\u0438\u043c IP. \u0420\u0430\u0437\u043e\u0431\u0440\u0430\u0432 \u0441\u0441\u044b\u043b\u043a\u0443, \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c \u0432 \u0446\u0438\u043a\u043b\u0435 \u043f\u043b\u0435\u0439\u043b\u0438\u0441\u0442 \u0438 \u043a\u0430\u0447\u0430\u0435\u043c \u0432\u0441\u0435 \u0447\u0430\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u0449\u0451 \u043d\u0435 \u0441\u043a\u0430\u0447\u0430\u043d\u044b. \u041c\u0435\u0436\u0434\u0443 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430\u043c\u0438 \u0447\u0430\u0441\u0442\u0435\u0439 \u0434\u0435\u043b\u0430\u0435\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0443\u044e \u043f\u0430\u0443\u0437\u0443, \u043c\u0435\u0436\u0434\u0443 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430\u043c\u0438 \u043f\u043b\u0435\u0439\u043b\u0438\u0441\u0442\u043e\u0432 \u0442\u043e\u0436\u0435. \u041f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0441\u0442\u043e\u0438\u0442 \u043f\u0430\u0443\u0437\u0430 10 \u0441\u0435\u043a\u0443\u043d\u0434 \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0441\u0435\u0440\u0432\u0435\u0440 \u0445\u043e\u0442\u044f \u0431\u044b \u043d\u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043e\u0442\u0432\u0435\u0442\u0438\u043b \u043d\u0435 403, \u0430 \u043f\u043b\u0435\u0439\u043b\u0438\u0441\u0442\u043e\u043c. \u0412 \u0446\u0435\u043b\u043e\u043c \u043f\u0430\u0443\u0437\u044b, \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043f\u043e\u0434\u043e\u0431\u0440\u0430\u043d\u044b \u0443\u0434\u0430\u0447\u043d\u043e. \u042f \u0431\u044b \u0438\u0445 \u043d\u0435 \u043c\u0435\u043d\u044f\u043b.  \u0421\u043a\u0440\u0438\u043f\u0442 rtspRecorder\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442:local rtspMeUrl &#171;https:\/\/rtsp.me\/embed\/kB0DezA0\/&#187;:local diskSlot &#171;usb1&#8243;:local freeSpace (([\/disk print as-value where slot=$diskSlot]-&gt;0)-&gt;&#187;free&#187;)# \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0434\u0438\u0441\u043a \u0438 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e, \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\u0435 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e (100 MB):if (([:len &#171;$freeSpace&#187;] = 0) || ($freeSpace &lt; 104857600)) do={    :log warning (&#171;low disk space on &#187; . $diskSlot)    :quit}:local getFolderPath do={    :local sDate [\/system clock get date]    :local sTime [\/system clock get time]    :return (&#171;usb1\/cam_video\/&#187; . [:pick $sDate 0 4] . [:pick $sDate 5 7] . [:pick $sDate 8 10] . &#171;\/&#187; . [:pick $sTime 0 2])}:local videoDateFolder [$getFolderPath]:do {    :local rtspMeUrlHtml ([\/tool fetch url=$rtspMeUrl output=user as-value]-&gt;&#187;data&#187;)    :local streamLinkStartMarker &#171;.get(&#8216;&#187;    :local streamLinkEndMarker &#171;&#8216;)&#187;    :local startMarkerPos [:find $rtspMeUrlHtml $streamLinkStartMarker]    :if ([:len $startMarkerPos] != 0) do={        :set startMarkerPos ($startMarkerPos + [:len $streamLinkStartMarker])        :local endMarkerPos [:find $rtspMeUrlHtml $streamLinkEndMarker $startMarkerPos]        :if ([:len $endMarkerPos] != 0) do={            :local hlsUrl [:pick $rtspMeUrlHtml $startMarkerPos $endMarkerPos]            #:log warning &#171;HLS_Parser SUCCESS! Found URL: $hlsUrl&#187;                        # \u0412\u042b\u0420\u0415\u0417\u0410\u0415\u041c \u0411\u0410\u0417\u041e\u0412\u042b\u0419 URL, ID \u041f\u041e\u0422\u041e\u041a\u0410 \u0418 \u041f\u0410\u0420\u0410\u041c\u0415\u0422\u0420\u042b            :local hlsPathMarker &#171;\/hls\/&#187;            :local hlsPathPos [:find $hlsUrl $hlsPathMarker]                        # \u0412\u044b\u0440\u0435\u0437\u0430\u0435\u043c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 URL            :local baseUrl [:pick $hlsUrl 0 ($hlsPathPos + [:len $hlsPathMarker])]                        # \u0412\u044b\u0440\u0435\u0437\u0430\u0435\u043c ID \u043f\u043e\u0442\u043e\u043a\u0430            :local m3u8Pos [:find $hlsUrl &#171;.m3u8&#187;]            :local streamId [:pick $hlsUrl ($hlsPathPos + 5) $m3u8Pos]                        # \u0412\u044b\u0440\u0435\u0437\u0430\u0435\u043c GET-\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b            :local paramPos [:find $hlsUrl &#171;?&#187;]            :local urlParams &#171;&#187;            :if ([:len $paramPos] != 0) do={                :set urlParams [:pick $hlsUrl $paramPos [:len $hlsUrl]]            }            :local playlistContent            :local startPosMsLink            :local endPosMsLink            :set playlistContent ([\/tool fetch url=$hlsUrl  output=user as-value]-&gt;&#187;data&#187;)            :delay 10s            :local hasChunks true            :local hasChunk true            :local playlistDelay 2            :while ($hasChunks) do={                :set videoDateFolder [$getFolderPath]                :local baseFileLocalPath ($videoDateFolder . &#171;\/&#187; . $streamId . &#171;.mp4&#8243;)                :if ([:len [\/file find where name=$baseFileLocalPath]] = 0) do={                    :set freeSpace (([\/disk print as-value where slot=$diskSlot]-&gt;0)-&gt;&#187;free&#187;)                    :if (([:len &#171;$freeSpace&#187;] = 0) || ($freeSpace &lt; 104857600)) do={                        :log warning (&#171;low disk space on &#187; . $diskSlot)                        :quit                    }                    :delay 1s                    \/tool fetch url=($baseUrl . $streamId . &#171;.mp4&#8243;) dst-path=$baseFileLocalPath keep-result=yes                }                :delay $playlistDelay                :set playlistContent ([\/tool fetch url=$hlsUrl output=user as-value]-&gt;&#187;data&#187;)                #:log warning (&#171;playlistContent : &#187; . $playlistContent)                :local searchPosPointer 0                :local startPosMsLink [:find $playlistContent ($streamId . &#171;-&#171;) $searchPosPointer]                :if ([:len $startPosMsLink] = 0) do={                    :log info (&#171;No Links in List&#187;)                    :set hasChunks false                    :set hasChunk false                } else={                    :set hasChunk true                }                :local downloadedCount 0                :while ($hasChunk) do={                    :local endPosMsLink [:find $playlistContent &#171;\\n&#187; $startPosMsLink]                    :local segmentFile [:pick $playlistContent $startPosMsLink $endPosMsLink]                    #:log info (&#171;Found chunk: &#187; . $segmentFile)                    :local chunkFileLocalPath ($videoDateFolder . &#171;\/&#187; . $segmentFile)                    :if ([:len [\/file find where name=$chunkFileLocalPath]] = 0) do={                        :local chunkFileUrl ($baseUrl . $segmentFile)                        :log warning (&#171;Downloading: &#187; . $chunkFileUrl)                        :do {                            :set freeSpace (([\/disk print as-value where slot=$diskSlot]-&gt;0)-&gt;&#187;free&#187;)                            :if (([:len &#171;$freeSpace&#187;] = 0) || ($freeSpace &lt; 104857600)) do={                                :log warning (&#171;low disk space on &#187; . $diskSlot)                                :quit                            }                            :delay 1                            \/tool fetch url=$chunkFileUrl dst-path=$chunkFileLocalPath keep-result=yes                            :set downloadedCount ($downloadedCount + 1)                        } on-error={                            :log warning (&#171;Failed to download chunk: &#187; . $chunkFileUrl)                        }                    }                    :set searchPosPointer ($endPosMsLink + 1)                    :set startPosMsLink [:find $playlistContent ($streamId . &#171;-&#171;) $searchPosPointer]                    :if ([:len $startPosMsLink] = 0) do={                        :log info (&#171;End Links&#187;)                        :set hasChunk false                    }                }                :if ($hasChunks) do={                    :if ($downloadedCount &gt; 0) do={                        :local calculatedDelay (10 &#8212; (2 * $downloadedCount))                        :if ($calculatedDelay &lt; 2) do={                            :set calculatedDelay 2                        }                        :set playlistDelay $calculatedDelay                        :log info &#171;HLS_Parser: Downloaded $downloadedCount chunks. Next playlist check in $playlistDelay s.&#187;                    } else={                        :set playlistDelay 10                        :log info &#171;HLS_Parser: No NEW chunks in playlist. Cooling down for 6s.&#187;                    }                }            }            :log info &#171;HLS_Parser: All segments from current playlist verified.&#187;        } else={            :log error &#171;HLS_Parser: End marker not found.&#187;        }    } else={        :log error &#171;HLS_Parser: Start marker not found on page.&#187;    }} on-error={    :log error (&#171;HLS_Parser ERROR: &#171;)}\u041f\u043e \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u0438 \u0441\u043a\u0440\u0438\u043f\u0442 \u0432 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0441 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u043e\u0439. \u041a\u0430\u0436\u0434\u044b\u0435 15 \u0441\u0435\u043a\u0443\u043d\u0434:if ([:len [\/system script job find script=rtspRecorder]] = 0) do={    \/system script run rtspRecorder} else={    :log warning &#171;\u0421\u043a\u0440\u0438\u043f\u0442 rtspRecorder \u0443\u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442&#187;}\u041e\u043d \u043f\u0438\u0448\u0435\u0442 \u043d\u0430 \u0434\u0438\u0441\u043a usb1, \u0432 \u043f\u0430\u043f\u043a\u0443 usb1\/cam_video\/\u0413\u043e\u0434\u041c\u0435\u0441\u044f\u0446\u0414\u0435\u043d\u044c\/\u0427\u0430\u0441  , \u043f\u0438\u0448\u0435\u0442 \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u043e, \u043f\u043e\u043a\u0430 \u0435\u0441\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0438 \u043f\u0430\u043c\u044f\u0442\u044c \u043d\u0430 \u0434\u0438\u0441\u043a\u0435. \u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432\u0438\u0434\u0435\u043e, \u043a\u0430\u0447\u0430\u0435\u043c \u0438\u0437 \u0440\u043e\u0443\u0442\u0435\u0440\u0430 \u043f\u0430\u043f\u043a\u0443 \u0441 \u043d\u0443\u0436\u043d\u044b\u043c \u0447\u0430\u0441\u043e\u043c, \u043a\u043b\u0430\u0434\u0451\u043c \u0432 \u044d\u0442\u0443 \u0436\u0435 \u043f\u0430\u043f\u043a\u0443 \u0444\u0430\u0439\u043b ffmpeg.exe. \u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 \u043f\u0440\u044f\u043c\u043e \u0432 \u044d\u0442\u043e\u0439 \u043f\u0430\u043f\u043a\u0435. \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0432 \u0430\u0434\u0440\u0435\u0441\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0435 \u043f\u0440\u043e\u0432\u043e\u0434\u043d\u0438\u043a\u0430 cmd \u0438 \u043d\u0430\u0436\u043c\u0438\u0442\u0435 Enter   \u0418 \u0432\u0432\u043e\u0434\u0438\u043c \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0434\u0432\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b. kB0DezA0  \u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u0445, \u044d\u0442\u043e ID \u043f\u043e\u0442\u043e\u043a\u0430, \u0443 \u0432\u0430\u0441 \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0434\u0440\u0443\u0433\u043e\u0439.copy \/b kB0DezA0.mp4 + kB0DezA0-*.m4s merged_raw.mp4ffmpeg -i merged_raw.mp4 -c copy ready_video.mp4\u0424\u0430\u0439\u043b ready_video.mp4 \u043d\u0430\u0434\u043e \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u043c\u043e\u0436\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c.\u0421 IPTV \u0434\u0435\u043b\u043e \u043e\u0431\u0441\u0442\u043e\u0438\u0442 \u0435\u0449\u0451 \u043f\u0440\u043e\u0449\u0435, \u044f \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b \u043a\u0430\u0447\u0430\u0442\u044c SD \u0438 HD \u043a\u0430\u043d\u0430\u043b, \u043a\u0430\u0447\u0430\u044e\u0442\u0441\u044f \u043e\u0431\u0430. \u0412\u043e\u0442 \u0435\u0441\u0442\u044c \u043a\u0430\u043a\u043e\u0439 \u0442\u043e \u043a\u0430\u043d\u0430\u043b#EXTINF:-1 tvg-id=&#187;360.ru@SD&#187;,360\u00b0 (1080p)https:\/\/cdn-evacoder-tv.facecast.io\/evacoder_hls_hi\/CkxfR1xNUAJwTgtXTBZTAJli\/index.m3u8\u041e\u043d \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0432 \u0442\u0430\u043a\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435#EXTM3U#EXT-X-MEDIA-SEQUENCE:5485341#EXT-X-TARGETDURATION:11#EXTINF:10,0_5485236.ts#EXTINF:10,0_5485237.ts#EXTINF:10,0_5485238.ts#EXTINF:10,0_5485239.ts#EXTINF:10,0_5485240.ts\u0418 \u0441\u043a\u0440\u0438\u043f\u0442 \u0434\u043b\u044f \u043d\u0435\u0433\u043e\u0421\u043a\u0440\u0438\u043f\u0442 hdIptvRecorder\u0421\u043a\u0440\u044b\u0442\u044b\u0439 \u0442\u0435\u043a\u0441\u0442:local iptvBaseUrl &#171;https:\/\/cdn-evacoder-tv.facecast.io\/evacoder_hls_hi\/CkxfR1xNUAJwTgtXTBZTAJli\/&#187;:local iptvListUrl ($iptvBaseUrl . &#171;0.m3u8&#187;):local diskSlot &#171;usb1&#8243;:local freeSpace (([\/disk print as-value where slot=$diskSlot]-&gt;0)-&gt;&#187;free&#187;)# \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0434\u0438\u0441\u043a \u0438 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e, \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\u0435 \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0435 \u043c\u0435\u0441\u0442\u043e (100 MB):if (([:len &#171;$freeSpace&#187;] = 0) || ($freeSpace &lt; 104857600)) do={    :log warning (&#171;low disk space on &#187; . $diskSlot)    :quit}:local getFolderPath do={    :local sDate [\/system clock get date]    :local sTime [\/system clock get time]    :return (&#171;usb1\/hd_iptv_channel\/&#187; . [:pick $sDate 0 4] . [:pick $sDate 5 7] . [:pick $sDate 8 10] . &#171;\/&#187; . [:pick $sTime 0 2])}:local videoDateFolder [$getFolderPath]:do {    :local playlistContent    :local startPosTsLink    :local endPosTsLink&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-483065","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/483065","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=483065"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/483065\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=483065"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=483065"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=483065"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}