﻿{"id":1567,"date":"2026-10-09T10:38:45","date_gmt":"2026-10-09T03:38:45","guid":{"rendered":"https:\/\/sangnguyen.drayddns.com\/?p=1567"},"modified":"2026-10-23T09:59:40","modified_gmt":"2026-10-23T02:59:40","slug":"huong-dan-toan-tap-he-thong-xem-camera-hikvision-qua-web-webrtc-mediamtx","status":"publish","type":"post","link":"https:\/\/sangnguyen.drayddns.com\/index.php\/2026\/10\/09\/huong-dan-toan-tap-he-thong-xem-camera-hikvision-qua-web-webrtc-mediamtx\/","title":{"rendered":"H\u01b0\u1edbng d\u1eabn to\u00e0n t\u1eadp: h\u1ec7 th\u1ed1ng xem camera hikvision qua web (webrtc &amp; mediamtx)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">M\u1ee5c ti\u00eau: X\u00e2y d\u1ef1ng trang web xem camera IP n\u1ed9i b\u1ed9 t\u1eeb xa qua m\u1ea1ng 4G v\u1edbi \u0111\u1ed9 tr\u1ec5 c\u1ef1c th\u1ea5p (WebRTC), giao di\u1ec7n \u0111\u00e1p \u1ee9ng m\u1ecdi thi\u1ebft b\u1ecb (\u0111\u1eb7c bi\u1ec7t l\u00e0 t\u1ef1 \u0111\u1ed9ng xoay ngang tr\u00ean iPhone), v\u00e0 h\u1ea1 t\u1ea7ng b\u1ea3o m\u1eadt an to\u00e0n sau t\u01b0\u1eddng l\u1eeda FortiGate.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>B\u01b0\u1edbc 1: T\u1ed1i \u01b0u Camera Hikvision v\u00e0 t\u1ea1o Link RTSP<\/strong>.<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Tr\u01b0\u1edbc khi \u0111\u1ee5ng \u0111\u1ebfn ph\u1ea7n m\u1ec1m hay code, camera c\u1ee7a b\u1ea1n ph\u1ea3i ph\u00e1t ra lu\u1ed3ng d\u1eef li\u1ec7u chu\u1ea9n \u0111\u1ec3 tr\u00ecnh duy\u1ec7t web c\u00f3 th\u1ec3 \u0111\u1ecdc \u0111\u01b0\u1ee3c.<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>D\u00f9ng tr\u00ecnh duy\u1ec7t \u0111\u0103ng nh\u1eadp v\u00e0o \u0111\u1ecba ch\u1ec9 IP n\u1ed9i b\u1ed9 c\u1ee7a Camera Hikvision (V\u00ed d\u1ee5: 172.16.40.10).<\/li>\n\n\n\n<li>V\u00e0o <strong>Configuration (C\u1ea5u h\u00ecnh) -&gt; Video\/Audio<\/strong>.<\/li>\n\n\n\n<li>Ch\u1ec9nh th\u00f4ng s\u1ed1:\n<ul class=\"wp-block-list\">\n<li><strong>Video Encoding:<\/strong> Ch\u1ecdn <strong>H.264<\/strong> (B\u1eaft bu\u1ed9c).<\/li>\n\n\n\n<li><strong>H.264+ (Smart Codec):<\/strong> Ch\u1ecdn <strong>OFF<\/strong>.<\/li>\n\n\n\n<li>L\u01b0u l\u1ea1i c\u00e0i \u0111\u1eb7t.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Ghi ra gi\u1ea5y \u0111\u01b0\u1eddng link RTSP c\u1ee7a camera n\u00e0y theo c\u00f4ng th\u1ee9c: rtsp:\/\/[t\u00ean_\u0111\u0103ng_nh\u1eadp]:[m\u1eadt_kh\u1ea9u]@[IP_Camera]:554\/Streaming\/Channels\/102 <em>(V\u00ed d\u1ee5: rtsp:\/\/admin:matkhau123@172.16.40.10:554\/Streaming\/Channels\/102)<\/em>.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>B\u01b0\u1edbc 2: T\u1ea3i ph\u1ea7n m\u1ec1m MediaMTX<\/strong>.<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">MediaMTX l\u00e0 l\u00f5i m\u00e1y ch\u1ee7 gi\u00fap chuy\u1ec3n \u0111\u1ed5i lu\u1ed3ng RTSP (\u1edf B\u01b0\u1edbc 1) sang chu\u1ea9n WebRTC si\u00eau t\u1ed1c.<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>L\u00ean m\u00e1y ch\u1ee7 Windows Server c\u1ee7a b\u1ea1n, m\u1edf tr\u00ecnh duy\u1ec7t v\u00e0o trang Github c\u1ee7a MediaMTX: <strong><em>https:\/\/github.com\/bluenviron\/mediamtx\/releases<\/em><\/strong><\/li>\n\n\n\n<li>T\u1ea3i b\u1ea3n d\u00e0nh cho Windows (file c\u00f3 \u0111u\u00f4i &#8230;windows_amd64.zip).<\/li>\n\n\n\n<li>T\u1ea1o m\u1ed9t th\u01b0 m\u1ee5c \u1ed5 C (V\u00ed d\u1ee5: C:\\MediaMTX) v\u00e0 gi\u1ea3i n\u00e9n to\u00e0n b\u1ed9 file v\u1eeba t\u1ea3i v\u00e0o \u0111\u00f3. B\u1ea1n s\u1ebd th\u1ea5y 2 file quan tr\u1ecdng nh\u1ea5t l\u00e0 mediamtx.exe v\u00e0 mediamtx.yml.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>B\u01b0\u1edbc 3: C\u1ea5u h\u00ecnh MediaMTX<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">B\u00e2y gi\u1edd ch\u00fang ta s\u1ebd n\u1ea1p link camera \u1edf B\u01b0\u1edbc 1 v\u00e0o MediaMTX.<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>M\u1edf file <strong>mediamtx.yml<\/strong> b\u1eb1ng Notepad.<\/li>\n\n\n\n<li>T\u00ecm d\u00f2ng webrtcICEHostNAT1To1IPs (n\u1eb1m \u1edf kho\u1ea3ng gi\u1eefa file). X\u00f3a d\u1ea5u # \u1edf \u0111\u1ea7u d\u00f2ng v\u00e0 \u0111i\u1ec1n \u0111\u1ecba ch\u1ec9 IP WAN (IP m\u1eb7t ti\u1ec1n Internet c\u1ee7a nh\u00e0 b\u1ea1n, ho\u1eb7c c\u00f3 th\u1ec3 l\u00e0 domain) v\u00e0o.\n<ul class=\"wp-block-list\">\n<li><em>V\u00ed d\u1ee5:<\/em> webrtcICEHostNAT1To1IPs: [&#8220;sangngnuyen.drayddns.com&#8221;]<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>Cu\u1ed9n xu\u1ed1ng d\u01b0\u1edbi c\u00f9ng file, t\u00ecm m\u1ee5c <strong>paths:<\/strong>. Khai b\u00e1o link camera c\u1ee7a b\u1ea1n v\u00e0o \u0111\u00e2y:<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">YAML<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>paths:\n  cam_noi_bo:\n    source: rtsp:\/\/admin:matkhau123@192.168.1.10:554\/Streaming\/Channels\/102\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong><em>&nbsp;&nbsp;&nbsp; source: rtsp:\/\/admin:matkhau123@192.168.1.10:554\/Streaming\/Channels\/102<\/em><\/strong><\/p>\n\n\n\n<ol start=\"4\" class=\"wp-block-list\">\n<li>L\u01b0u file mediamtx.yml l\u1ea1i.<\/li>\n\n\n\n<li>Click \u0111\u00fap chu\u1ed9t ch\u1ea1y file <strong>mediamtx.exe<\/strong>. M\u1ed9t c\u1eeda s\u1ed5 m\u00e0u \u0111en (CMD) hi\u1ec7n l\u00ean b\u00e1o ch\u1eef &#8220;\u0111ang ch\u1ea1y&#8221; l\u00e0 th\u00e0nh c\u00f4ng. C\u1ee9 \u0111\u1ec3 c\u1eeda s\u1ed5 \u0111\u00f3 ch\u1ea1y ng\u1ea7m.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>B\u01b0\u1edbc 4: NAT Port (Modem Draytek v\u00e0 M\u1edf c\u1eeda t\u01b0\u1eddng l\u1eeda)<\/strong>.<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">MediaMTX \u0111\u00e3 ch\u1ea1y, nh\u01b0ng n\u00f3 \u0111ang b\u1ecb nh\u1ed1t trong m\u1ea1ng n\u1ed9i b\u1ed9. B\u1ea1n ph\u1ea3i \u0111\u1ee5c t\u01b0\u1eddng l\u1eeda \u0111\u1ec3 h\u00ecnh \u1ea3nh \u0111i ra ngo\u00e0i 4G. (Do m\u00ecnh \u0111ang s\u1eed d\u1ee5ng t\u01b0\u1eddng l\u1eefa fortinet v\u00e0 Modem draytek n\u00ean c\u1ea7n ph\u1ea3i Nat port 2 l\u1ea7n).<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Truy c\u1eadp Modem nh\u00e0 m\u1ea1ng (Viettel\/VNPT\/FPT):<\/strong><ol><li>M\u1edf (NAT\/Port Forwarding) c\u1ed5ng <strong>443<\/strong> (giao th\u1ee9c <strong>TCP<\/strong>). Tr\u1ecf v\u1ec1 IP c\u1ee7a FortiGate.<\/li><\/ol>\n<ol class=\"wp-block-list\">\n<li>M\u1edf c\u1ed5ng <strong>8189<\/strong> (giao th\u1ee9c <strong>UDP<\/strong>). Tr\u1ecf v\u1ec1 IP c\u1ee7a FortiGate.<\/li>\n<\/ol>\n<\/li>\n\n\n\n<li><strong>Truy c\u1eadp t\u01b0\u1eddng l\u1eeda FortiGate:<\/strong>\n<ol class=\"wp-block-list\">\n<li>T\u1ea1o Virtual IP (VIP) m\u1edf c\u1ed5ng <strong>443 (TCP)<\/strong> tr\u1ecf v\u1ec1 m\u00e1y ch\u1ee7 IIS\/MediaMTX (V\u00ed d\u1ee5: 172.16.10.16).<\/li>\n<\/ol>\n<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">T\u1ea1o Virtual IP m\u1edf c\u1ed5ng <strong>8189 (UDP)<\/strong> tr\u1ecf v\u1ec1 m\u00e1y ch\u1ee7 IIS\/MediaMTX<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>B\u01b0\u1edbc 5: C\u1ea5u h\u00ecnh m\u00e1y ch\u1ee7 IIS Reverse Proxy<\/strong>.<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">\u0110\u1ebfn b\u01b0\u1edbc n\u00e0y, b\u00ean ngo\u00e0i \u0111\u00e3 c\u00f3 th\u1ec3 \u0111\u00e2m xuy\u00ean t\u01b0\u1eddng l\u1eeda v\u00e0o m\u00e1y ch\u1ee7 qua c\u1ed5ng 443. Gi\u1edd ta ph\u1ea3i nh\u1edd IIS d\u1eabn \u0111\u01b0\u1eddng ti\u1ebfp.<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>M\u1edf IIS Manager tr\u00ean m\u00e1y ch\u1ee7. \u0110\u1ea3m b\u1ea3o b\u1ea1n \u0111\u00e3 c\u00e0i ch\u1ee9ng ch\u1ec9 SSL cho t\u00ean mi\u1ec1n sangnguyen.drayddns.com \u0111\u1ec3 ch\u1ea1y HTTPS (Port 443).<\/li>\n\n\n\n<li>T\u1ea3i v\u00e0 c\u00e0i \u0111\u1eb7t 2 module cho IIS: <strong>ARR (Application Request Routing)<\/strong> v\u00e0 <strong>URL Rewrite<\/strong>.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">&#8211; \u0110\u1ec3 c\u00e0i \u0111\u1eb7t Application Request Routing (ARR) v\u00e0 URL Rewrite tr\u00ean IIS, b\u1ea1n ph\u1ea3i c\u00e0i \u0111\u1eb7t <strong>URL Rewrite tr\u01b0\u1edbc<\/strong>, sau \u0111\u00f3 m\u1edbi c\u00e0i ARR v\u00ec ARR y\u00eau c\u1ea7u c\u00e1c th\u01b0 vi\u1ec7n c\u1ee7a module Rewrite \u0111\u1ec3 c\u00f3 th\u1ec3 ho\u1ea1t \u0111\u1ed9ng.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Do Microsoft hi\u1ec7n \u0111\u00e3 ng\u1eebng h\u1ed7 tr\u1ee3 c\u00f4ng c\u1ee5 Web Platform Installer (WebPI), b\u1ea1n s\u1ebd c\u1ea7n t\u1ea3i v\u00e0 c\u00e0i \u0111\u1eb7t tr\u1ef1c ti\u1ebfp qua c\u00e1c file .msi t\u1eeb trang ch\u1ee7.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>T\u1ea3i v\u00e0 c\u00e0i \u0111\u1eb7t URL Rewrite Module 2.1:B\u1eaft bu\u1ed9c c\u00e0i \u0111\u1eb7t tr\u01b0\u1edbc.<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Truy c\u1eadp trang t\u1ea3i xu\u1ed1ng ch\u00ednh th\u1ee9c c\u1ee7a Microsoft: <a href=\"https:\/\/www.iis.net\/downloads\/microsoft\/url-rewrite\" target=\"_blank\" rel=\"noopener\">URL Rewrite Module 2.1<\/a>.<\/li>\n\n\n\n<li>Cu\u1ed9n trang xu\u1ed1ng ph\u1ea7n <strong>Download URL Rewrite Module 2.1<\/strong>, ch\u1ecdn t\u1ea3i phi\u00ean b\u1ea3n <strong>x64<\/strong> (d\u00e0nh cho Windows Server b\u1ea3n 64-bit).<\/li>\n\n\n\n<li>Ch\u1ea1y file c\u00e0i \u0111\u1eb7t .msi v\u1eeba t\u1ea3i v\u1ec1 v\u00e0 ch\u1ecdn Next li\u00ean t\u1ee5c \u0111\u1ec3 ho\u00e0n t\u1ea5t.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>T\u1ea3i v\u00e0 c\u00e0i \u0111\u1eb7t Application Request Routing (ARR) 3.0:<\/strong>C\u00e0i \u0111\u1eb7t sau URL Rewrite.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Truy c\u1eadp trang Microsoft Download Center: <a href=\"https:\/\/www.microsoft.com\/en-us\/download\/details.aspx?id=47333\" target=\"_blank\" rel=\"noopener\">ARR 3.0 (x64)<\/a>.<\/li>\n\n\n\n<li>Nh\u1ea5n n\u00fat <strong>Download<\/strong> \u0111\u1ec3 t\u1ea3i file requestRouter_amd64.msi.<\/li>\n\n\n\n<li>Ch\u1ea1y file c\u00e0i \u0111\u1eb7t v\u00e0 l\u00e0m theo tr\u00ecnh h\u01b0\u1edbng d\u1eabn tr\u00ean m\u00e0n h\u00ecnh.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">M\u1edf <strong>Command Prompt<\/strong> ho\u1eb7c <strong>PowerShell<\/strong> b\u1eb1ng quy\u1ec1n Qu\u1ea3n tr\u1ecb (Run as Administrator) v\u00e0 ch\u1ea1y l\u1ec7nh sau \u0111\u1ec3 bu\u1ed9c IIS nh\u1eadn di\u1ec7n module v\u1eeba c\u00e0i:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">DOS<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Iisreset<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>K\u00edch ho\u1ea1t t\u00ednh n\u0103ng Reverse Proxy tr\u00ean ARR:<\/strong>C\u1ea5u h\u00ecnh h\u1ec7 th\u1ed1ng \u0111i\u1ec1u h\u01b0\u1edbng.<\/li>\n\n\n\n<li>M\u1edf <strong>Internet Information Services (IIS) Manager<\/strong>.<\/li>\n\n\n\n<li>\u1ede c\u1ed9t <strong>Connections<\/strong> b\u00ean tr\u00e1i, nh\u1ea5p ch\u1ecdn tr\u1ef1c ti\u1ebfp v\u00e0o <strong>t\u00ean m\u00e1y ch\u1ee7 (Server Name)<\/strong> c\u1ee7a b\u1ea1n.<\/li>\n\n\n\n<li>\u1ede khung gi\u1eefa, t\u00ecm v\u00e0 nh\u1ea5p \u0111\u00fap v\u00e0o bi\u1ec3u t\u01b0\u1ee3ng <strong>Application Request Routing Cache<\/strong>.<\/li>\n\n\n\n<li>Nh\u00ecn sang c\u1ed9t <strong>Actions<\/strong> b\u00ean ph\u1ea3i, nh\u1ea5p v\u00e0o <strong>Server Proxy Settings&#8230;<\/strong><\/li>\n\n\n\n<li>\u0110\u00e1nh d\u1ea5u tick v\u00e0o \u00f4 <strong>Enable proxy<\/strong>.<\/li>\n\n\n\n<li>Nh\u1ea5n <strong>Apply<\/strong> \u1edf c\u1ed9t Actions b\u00ean ph\u1ea3i \u0111\u1ec3 l\u01b0u c\u1ea5u h\u00ecnh.<\/li>\n<\/ul>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li>C\u1ea5u h\u00ecnh quy t\u1eafc URL Rewrite:\n<ul class=\"wp-block-list\">\n<li><strong>Name<\/strong>: T\u1ef1 \u0111\u1eb7t t\u00ean<\/li>\n\n\n\n<li><strong>Pattern:<\/strong> ^(cam_noi_bo|cua_sau|cua_truoc|truoc_cua_kg)(.*) <strong><em>(ph\u1ea7n n\u00e0y li\u00ean quan ch\u1ed5 file mediamtx.yml c\u1ee7a Mediamxt)<\/em><\/strong><\/li>\n\n\n\n<li><strong>Rewrite URL<\/strong>: <a href=\"http:\/\/172.16.10.16:8889\/%7bR:1%7d%7bR:2%7d\">http:\/\/172.16.10.16:8889\/{R<strong>:<\/strong>1}{R<strong>:<\/strong>2}<\/a> (IP m\u00e1y ch\u1ee7 web)<\/li>\n\n\n\n<li>Sau \u0111\u00f3 b\u1ea5m Apply.<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"826\" src=\"https:\/\/sangnguyen.drayddns.com\/wp-content\/uploads\/2026\/10\/1-1-1024x826.png\" alt=\"\" class=\"wp-image-1568\" style=\"width:576px;height:auto\" srcset=\"https:\/\/sangnguyen.drayddns.com\/wp-content\/uploads\/2026\/10\/1-1-1024x826.png 1024w, https:\/\/sangnguyen.drayddns.com\/wp-content\/uploads\/2026\/10\/1-1-300x242.png 300w, https:\/\/sangnguyen.drayddns.com\/wp-content\/uploads\/2026\/10\/1-1-767x619.png 767w, https:\/\/sangnguyen.drayddns.com\/wp-content\/uploads\/2026\/10\/1-1.png 1242w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\"><strong>B\u01b0\u1edbc 6: \u0110\u01b0a code PHP l\u00ean Website hi\u1ec3n th\u1ecb<\/strong>.<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">H\u1ea1 t\u1ea7ng m\u1ea1ng v\u00e0 m\u00e1y ch\u1ee7 \u0111\u00e3 xong ho\u00e0n to\u00e0n. B\u01b0\u1edbc cu\u1ed1i c\u00f9ng l\u00e0 t\u1ea1o m\u1eb7t ti\u1ec1n trang web cho ng\u01b0\u1eddi d\u00f9ng b\u1ea5m xem.<\/p>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>V\u00e0o th\u01b0 m\u1ee5c ch\u1ee9a m\u00e3 ngu\u1ed3n website tr\u00ean m\u00e1y ch\u1ee7 IIS (Th\u01b0\u1eddng l\u00e0 C:\\inetpub\\wwwroot ho\u1eb7c th\u01b0 m\u1ee5c web b\u1ea1n t\u1ef1 t\u1ea1o).<\/li>\n\n\n\n<li>T\u1ea1o m\u1ed9t file m\u1edbi t\u00ean l\u00e0 <strong>xemcamerahik.php<\/strong>.<\/li>\n\n\n\n<li>Copy to\u00e0n b\u1ed9 \u0111o\u1ea1n code PHP, HTML, CSS (Code b\u00ean d\u01b0\u1edbi, Code n\u00e0y g\u1ed3m c\u00f3 4 khung camera + b\u1ea3o m\u1eadt khi xem ) d\u00e1n v\u00e0o file n\u00e0y v\u00e0 l\u01b0u l\u1ea1i.<\/li>\n<\/ol>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?php\n\/\/ ==============================================================================\n\/\/ PH\u1ea6N 1: B\u1ea2O M\u1eacT GIAO DI\u1ec6N (CH\u1ed0NG XEM TR\u1ed8M)\n\/\/ ==============================================================================\n\n\/\/ \u0110\u1eb6T M\u1eacT KH\u1ea8U QU\u1ea2N TR\u1eca C\u1ee6A B\u1ea0N \u1ede \u0110\u00c2Y\n$password = 'Nh\u1eadp mk \u1edf \u0111\u00e2y'; \n$da_dang_nhap = false;\n\n\/\/ Ki\u1ec3m tra xem ng\u01b0\u1eddi d\u00f9ng \u0111\u00e3 nh\u1eadp \u0111\u00fang m\u1eadt kh\u1ea9u ch\u01b0a\nif (isset($_POST&#91;'mat_khau']) &amp;&amp; $_POST&#91;'mat_khau'] === $password) {\n    $da_dang_nhap = true; \/\/ Cho ph\u00e9p \u0111i ti\u1ebfp n\u1ebfu \u0111\u00fang\n}\n\n\/\/ N\u1ebfu ch\u01b0a nh\u1eadp ho\u1eb7c nh\u1eadp sai m\u1eadt kh\u1ea9u -&gt; Hi\u1ec3n th\u1ecb form v\u00e0 kh\u00f3a c\u00e1c d\u00f2ng code ph\u00eda d\u01b0\u1edbi\nif (!$da_dang_nhap) {\n    echo '\n    &lt;!DOCTYPE html&gt;\n    &lt;html lang=\"vi\"&gt;\n    &lt;head&gt;\n        &lt;meta charset=\"UTF-8\"&gt;\n        &lt;title&gt;H\u1ec7 Th\u1ed1ng An Ninh&lt;\/title&gt;\n        &lt;style&gt;\n            \/* CSS trang tr\u00ed cho khung \u0111\u0103ng nh\u1eadp *\/\n            body { font-family: Arial, sans-serif; background: #111; color: #fff; text-align: center; padding-top: 150px; }\n            .login-box { background: #222; padding: 30px; border-radius: 8px; border: 2px solid #444; display: inline-block; box-shadow: 0 4px 15px rgba(0,0,0,0.5); }\n            input { padding: 10px; width: 200px; border-radius: 4px; border: 1px solid #555; background: #333; color: #fff; outline: none; margin-bottom: 15px; }\n            button { padding: 10px 20px; background: #00bcd4; color: #fff; border: none; border-radius: 4px; cursor: pointer; font-weight: bold; }\n            button:hover { background: #0097a7; }\n        &lt;\/style&gt;\n    &lt;\/head&gt;\n    &lt;body&gt;\n        &lt;div class=\"login-box\"&gt;\n            &lt;h3 style=\"margin-top:0; color:#00bcd4;\"&gt;NH\u1eacP M\u1eacT KH\u1ea8U QU\u1ea2N TR\u1eca&lt;\/h3&gt;\n            &lt;form method=\"POST\"&gt;\n                &lt;input type=\"password\" name=\"mat_khau\" placeholder=\"M\u1eadt kh\u1ea9u...\" required autofocus&gt;&lt;br&gt;\n                &lt;button type=\"submit\"&gt;Truy c\u1eadp Camera&lt;\/button&gt;\n            &lt;\/form&gt;\n        &lt;\/div&gt;\n    &lt;\/body&gt;\n    &lt;\/html&gt;\n    ';\n    exit; \/\/ L\u1ec7nh exit ch\u1eb7n kh\u00f4ng cho ch\u1ea1y ph\u1ea7n load Camera API \u1edf d\u01b0\u1edbi khi ch\u01b0a c\u00f3 m\u1eadt kh\u1ea9u\n}\n?&gt;\n\n&lt;!-- \u0110O\u1ea0N SCRIPT X\u00d3A D\u1ea4U V\u1ebeT: \u00c9p tr\u00ecnh duy\u1ec7t qu\u00ean m\u1eadt kh\u1ea9u ngay sau khi load xong. N\u1ebfu \u1ea5n F5 l\u00e0 kh\u00f3a l\u1ea1i ngay --&gt;\n&lt;script&gt;\n    if (window.history.replaceState) {\n        window.history.replaceState(null, null, window.location.href);\n    }\n&lt;\/script&gt;\n&lt;?php\n\/\/ ==============================================================================\n\/\/ PH\u1ea6N 2: C\u1ea4U H\u00ccNH DATA 4 CAMERA (Ch\u1ea1y b\u1eb1ng MediaMTX)\n\/\/ ==============================================================================\n$camData = &#91;\n    &#91;\n        'index' =&gt; 0, \n        'name' =&gt; 'CAMERA HIK N\u1ed8I B\u1ed8', \n        'url' =&gt; 'https:\/\/sangnguyen.drayddns.com\/cam_noi_bo\/', \/\/ Ch\u1ea1y WebRTC\n        'error' =&gt; ''\n    ],\n    &#91;\n        'index' =&gt; 1, \n        'name' =&gt; 'C\u1eecA SAU NH\u00c0 HG', \n        'url' =&gt; '', \/\/ \u0110\u1ec3 tr\u1ed1ng link t\u1ea1m th\u1eddi\n        'error' =&gt; 'Ch\u1edd c\u1ea5u h\u00ecnh m\u1ea1ng (NAT)'\n    ],\n    &#91;\n        'index' =&gt; 2, \n        'name' =&gt; 'C\u1eecA TR\u01af\u01a0C NH\u00c0 HG', \n        'url' =&gt; '',\n        'error' =&gt; 'Ch\u1edd c\u1ea5u h\u00ecnh m\u1ea1ng (NAT)'\n    ],\n    &#91;\n        'index' =&gt; 3, \n        'name' =&gt; 'TR\u01af\u1edaC C\u1eecA NH\u00c0 KG', \n        'url' =&gt; '',\n        'error' =&gt; 'Ch\u1edd c\u1ea5u h\u00ecnh m\u1ea1ng (NAT)'\n    ]\n];\n?&gt;\n\n&lt;!DOCTYPE html&gt;\n&lt;html lang=\"vi\"&gt;\n&lt;head&gt;\n    &lt;meta charset=\"UTF-8\"&gt;\n    &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"&gt;\n    &lt;title&gt;H\u1ec7 th\u1ed1ng Gi\u00e1m s\u00e1t \u0110a m\u00e0n h\u00ecnh&lt;\/title&gt;\n    &lt;script src=\"https:\/\/cdn.jsdelivr.net\/npm\/hls.js@latest\"&gt;&lt;\/script&gt;\n    &lt;style&gt;\n        body { font-family: Arial, sans-serif; background: #111; color: #fff; margin: 0; padding: 10px; text-align: center; }\n        h2 { margin-top: 10px; margin-bottom: 15px; color: #00bcd4; text-transform: uppercase; letter-spacing: 1px; }\n        .grid-container { display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px; max-width: 80%; margin: 0 auto; }\n        .cam-box { background: #222; border: 2px solid #444; border-radius: 8px; position: relative; aspect-ratio: 16\/9; overflow: hidden; box-shadow: 0 4px 10px rgba(0,0,0,0.5); }\n        .cam-name { position: absolute; top: 25px; left: 10px; background: rgba(0,0,0,0.7); color: #fff; padding: 5px 10px; font-size: 14px; font-weight: bold; border-radius: 4px; z-index: 10; }\n        video { width: 100%; height: 100%; object-fit: cover; background: #000; }\n        .error-msg { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: #ff4444; font-size: 14px; width: 80%; }\n        @media (max-width: 768px) { .grid-container { grid-template-columns: 1fr; max-width: 95%; } }\n        \n       \/* CSS cho n\u00fat b\u1ea5m ph\u00f3ng to *\/\n        .rotate-btn {\n            position: absolute;\n            top: 25px; \/* \u0110\u1ed5i bottom th\u00e0nh top v\u00e0 \u0111\u1ec3 25px cho ngang h\u00e0ng v\u1edbi t\u00ean cam *\/\n            right: 10px; \/* Gi\u1eef nguy\u00ean right \u0111\u1ec3 n\u1eb1m b\u00ean ph\u1ea3i *\/\n            background: rgba(0, 0, 0, 0.7);\n            color: #fff;\n            border: 1px solid #444;\n            padding: 6px 12px;\n            font-size: 14px;\n            border-radius: 4px;\n            cursor: pointer;\n            z-index: 999; \n        }\n        .rotate-btn:hover { background: #00bcd4; color: #000; }\n\n        \/* CSS \u0111\u1eb7c tr\u1ecb Fullscreen ngang cho iPhone (d\u00f9ng d\u1ef1 ph\u00f2ng) *\/\n        .ios-fullscreen {\n            position: fixed !important;\n            top: 50% !important;\n            left: 50% !important;\n            width: 100vh !important; \n            height: 100vw !important; \n            transform: translate(-50%, -50%) rotate(90deg) !important;\n            z-index: 9999 !important;\n            background: #000 !important;\n            border: none !important;\n            border-radius: 0 !important;\n            max-width: none !important;\n        }\n    &lt;\/style&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;h2&gt;XEM CAMERA NH\u00c0 \u00d4NG 6 D\u0168NG HIHI&lt;\/h2&gt;\n    &lt;div class=\"grid-container\"&gt;\n        &lt;?php foreach ($camData as $c): ?&gt;\n            &lt;div class=\"cam-box\"&gt;\n                &lt;!-- Ch\u1eef t\u00ean Cam \u0111\u00e3 \u0111\u01b0\u1ee3c h\u1ea1 xu\u1ed1ng 25px trong CSS --&gt;\n                &lt;div class=\"cam-name\"&gt;&lt;?php echo htmlspecialchars($c&#91;'name']); ?&gt;&lt;\/div&gt;\n                \n                &lt;?php if ($c&#91;'url']): ?&gt;\n                    &lt;!-- Iframe WebRTC (\u0111\u00e3 b\u1eadt quy\u1ec1n allowfullscreen) --&gt;\n                    &lt;iframe src=\"&lt;?php echo $c&#91;'url']; ?&gt;\" width=\"100%\" height=\"100%\" style=\"border:none; position:absolute; top:0; left:0; z-index: 1;\" scrolling=\"no\" allow=\"fullscreen\" allowfullscreen&gt;&lt;\/iframe&gt;\n                    \n                    &lt;!-- N\u00daT B\u1ea4M PH\u00d3NG TO --&gt;\n                    &lt;button class=\"rotate-btn\" onclick=\"fullScreenLandscape(this)\"&gt;\ud83d\udd32 Xoay H\u00ecnh &lt;\/button&gt;\n                    \n                &lt;?php else: ?&gt;\n                    &lt;div class=\"error-msg\"&gt;&lt;?php echo $c&#91;'error']; ?&gt;&lt;\/div&gt;\n                &lt;?php endif; ?&gt;\n            &lt;\/div&gt;\n        &lt;?php endforeach; ?&gt;\n    &lt;\/div&gt;\n\n  &lt;script&gt;\nfunction fullScreenLandscape(btn) {\n    let camBox = btn.closest('.cam-box');\n    if (!camBox) return;\n\n    \/\/ Nh\u1eadn di\u1ec7n iPhone \/ iPad\n    let isIOS = \/iPad|iPhone|iPod\/.test(navigator.userAgent) || (navigator.platform === 'MacIntel' &amp;&amp; navigator.maxTouchPoints &gt; 1);\n\n    if (isIOS) {\n        \/\/ \u0110\u1eb6C TR\u1eca IPHONE: D\u00f9ng CSS \u00e9p khung h\u00ecnh quay ngang 90 \u0111\u1ed9, ph\u1ee7 k\u00edn m\u00e0n h\u00ecnh\n        \/\/ B\u1ea5t ch\u1ea5p \u0111i\u1ec7n tho\u1ea1i \u0111ang c\u1ea7m d\u1ecdc hay b\u1eadt kh\u00f3a xoay\n        if (camBox.classList.contains('ios-fullscreen')) {\n            camBox.classList.remove('ios-fullscreen');\n            btn.innerHTML = \"\ud83d\udd32 Xoay h\u00ecnh\";\n        } else {\n            camBox.classList.add('ios-fullscreen');\n            btn.innerHTML = \"\u274c Thu nh\u1ecf\";\n        }\n        return; \n    }\n\n    \/\/ ==========================================\n    \/\/ D\u00c0NH CHO ANDROID V\u00c0 M\u00c1Y T\u00cdNH (V\u1eabn ch\u1ea1y Fullscreen chu\u1ea9n)\n    \/\/ ==========================================\n    function lockLandscape() {\n        if (screen.orientation &amp;&amp; screen.orientation.lock) {\n            screen.orientation.lock('landscape').catch(e =&gt; {});\n        }\n    }\n    \n    if (!document.fullscreenElement &amp;&amp; !document.webkitFullscreenElement) {\n        if (camBox.requestFullscreen) {\n            camBox.requestFullscreen().then(lockLandscape).catch(e =&gt; {});\n        } else if (camBox.webkitRequestFullscreen) {\n            camBox.webkitRequestFullscreen();\n            lockLandscape();\n        }\n    } else {\n        if (document.exitFullscreen) document.exitFullscreen();\n        else if (document.webkitExitFullscreen) document.webkitExitFullscreen();\n    }\n}\n&lt;\/script&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">4. C\u1ea7m \u0111i\u1ec7n tho\u1ea1i, t\u1eaft Wifi b\u1eadt 4G, v\u00e0o link https:\/\/sangnguyen.drayddns.com, nh\u1eadp m\u1eadt kh\u1ea9u \u0111\u00e3 c\u1ea5u h\u00ecnh v\u00e0 t\u1eadn h\u01b0\u1edfng th\u00e0nh qu\u1ea3!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>M\u1ee5c ti\u00eau: X\u00e2y d\u1ef1ng trang web xem camera IP n\u1ed9i b\u1ed9 t\u1eeb xa qua m\u1ea1ng 4G v\u1edbi \u0111\u1ed9 tr\u1ec5 c\u1ef1c th\u1ea5p (WebRTC), giao di\u1ec7n \u0111\u00e1p \u1ee9ng m\u1ecdi thi\u1ebft b\u1ecb (\u0111\u1eb7c bi\u1ec7t l\u00e0 t\u1ef1 \u0111\u1ed9ng xoay ngang tr\u00ean iPhone), v\u00e0 h\u1ea1 t\u1ea7ng b\u1ea3o m\u1eadt an to\u00e0n sau t\u01b0\u1eddng l\u1eeda FortiGate. B\u01b0\u1edbc 1: T\u1ed1i \u01b0u Camera Hikvision [&#8230;]\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1567","post","type-post","status-publish","format-standard","hentry","category-chia-se-hoac-kien-thuc-cntt"],"_links":{"self":[{"href":"https:\/\/sangnguyen.drayddns.com\/index.php\/wp-json\/wp\/v2\/posts\/1567","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sangnguyen.drayddns.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sangnguyen.drayddns.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sangnguyen.drayddns.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sangnguyen.drayddns.com\/index.php\/wp-json\/wp\/v2\/comments?post=1567"}],"version-history":[{"count":3,"href":"https:\/\/sangnguyen.drayddns.com\/index.php\/wp-json\/wp\/v2\/posts\/1567\/revisions"}],"predecessor-version":[{"id":1585,"href":"https:\/\/sangnguyen.drayddns.com\/index.php\/wp-json\/wp\/v2\/posts\/1567\/revisions\/1585"}],"wp:attachment":[{"href":"https:\/\/sangnguyen.drayddns.com\/index.php\/wp-json\/wp\/v2\/media?parent=1567"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sangnguyen.drayddns.com\/index.php\/wp-json\/wp\/v2\/categories?post=1567"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sangnguyen.drayddns.com\/index.php\/wp-json\/wp\/v2\/tags?post=1567"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}