596cf1ccdc
Добавлены информационные тултипы для всех полей формы настройки камеры с подробными описаниями, примерами использования и рекомендациями. Улучшает пользовательский опыт и помогает пользователям правильно заполнить форму. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
467 lines
27 KiB
HTML
467 lines
27 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||
<meta name="theme-color" content="#0a0a0f">
|
||
<title>Strix - Camera Stream Discovery</title>
|
||
<link rel="stylesheet" href="css/main.css">
|
||
</head>
|
||
<body>
|
||
<!-- Mock Mode Indicator -->
|
||
<div id="mock-mode-badge" class="mock-badge hidden">
|
||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
|
||
<path d="M8 1v6l4 2" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||
<circle cx="8" cy="8" r="7" stroke="currentColor" stroke-width="2" fill="none"/>
|
||
</svg>
|
||
MOCK MODE
|
||
</div>
|
||
|
||
<div id="app">
|
||
<!-- Screen 1: Initial Address Input -->
|
||
<div id="screen-address" class="screen active">
|
||
<div class="container">
|
||
<div class="hero">
|
||
<svg class="logo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="800px" width="800px" version="1.1" id="Layer_1" viewBox="0 0 512.001 512.001" xml:space="preserve">
|
||
<g>
|
||
<path style="fill:#7E57C2;" d="M124.477,378.183L9.347,495.779c21.628,21.628,56.695,21.628,78.324,0L119,464.45 c21.628,21.628,56.696,21.628,78.324,0l28.375-28.375C187.373,426.203,151.825,405.106,124.477,378.183z"/>
|
||
<path style="fill:#7E57C2;" d="M447.27,55.383h-55.383V177.22c0.002-40.997,22.277-76.788,55.383-95.939 c16.293-9.425,35.207-14.822,55.383-14.822c0-6.982,0-11.077,0-11.077V0C472.065,0,447.27,24.796,447.27,55.383z"/>
|
||
</g>
|
||
<path style="fill:#9575CD;" d="M336.504,55.383C336.504,24.796,311.708,0,281.121,0v66.46c20.176,0,39.091,5.397,55.383,14.822 c33.107,19.153,55.383,54.946,55.383,95.945V55.383H336.504z"/>
|
||
<path style="fill:#E8E0F5;" d="M391.887,209.772v-27.116c0-3.312,0-5.432,0-5.432c0-40.997-22.276-76.791-55.383-95.942 c-16.293-9.425-35.207-14.822-55.383-14.822v155.073C311.213,191.443,357.554,187.532,391.887,209.772z M314.351,143.996 c0-12.234,9.918-22.153,22.153-22.153s22.153,9.919,22.153,22.153c0,12.235-9.918,22.153-22.153,22.153 S314.351,156.231,314.351,143.996z"/>
|
||
<path style="fill:#D1C4E9;" d="M391.887,177.221v32.551c5.151,3.336,10.037,7.246,14.55,11.76h96.216V66.46 c-20.176,0-39.091,5.397-55.383,14.822C414.164,100.434,391.888,136.225,391.887,177.221z M469.423,143.996 c0,12.235-9.918,22.153-22.153,22.153s-22.153-9.918-22.153-22.153c0-12.234,9.918-22.153,22.153-22.153 C459.504,121.843,469.423,131.762,469.423,143.996z"/>
|
||
<path style="fill:#9575CD;" d="M281.121,221.532l-10.2,10.2L281.121,221.532z"/>
|
||
<path style="fill:#B39DDB;" d="M406.438,221.533c34.606,34.606,34.606,90.712,0,125.319c-69.21,69.21-181.422,69.21-250.633,0.002 l-31.329,31.33c27.348,26.923,62.896,48.02,101.221,57.892c17.714,4.562,36.285,6.989,55.423,6.989 c122.349,0,221.532-99.182,221.532-221.531C502.653,221.533,406.437,221.532,406.438,221.533z"/>
|
||
<path style="fill:#9575CD;" d="M281.121,221.532l125.318,125.319c34.606-34.606,34.606-90.713,0-125.319 c-4.515-4.514-9.401-8.425-14.551-11.761C357.554,187.532,311.213,191.443,281.121,221.532z"/>
|
||
<path style="fill:#7E57C2;" d="M406.438,346.851L281.12,221.533l-10.199,10.2L155.802,346.851 C225.017,416.062,337.228,416.061,406.438,346.851z"/>
|
||
<circle style="fill:#9575CD;" cx="336.507" cy="143.996" r="22.153"/>
|
||
<circle style="fill:#7E57C2;" cx="447.274" cy="143.996" r="22.153"/>
|
||
</svg>
|
||
<h1 class="title">STRIX</h1>
|
||
<p class="subtitle">Camera Stream Discovery</p>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="network-address" class="label">Network Address</label>
|
||
<input
|
||
type="text"
|
||
id="network-address"
|
||
class="input input-large"
|
||
placeholder="192.168.1.100"
|
||
autocomplete="off"
|
||
spellcheck="false"
|
||
>
|
||
<p class="hint">IP, hostname or full stream URL</p>
|
||
</div>
|
||
|
||
<button id="btn-check-address" class="btn btn-primary btn-large">
|
||
Check Address
|
||
</button>
|
||
|
||
<div class="examples">
|
||
<p class="examples-title">Examples</p>
|
||
<ul class="examples-list">
|
||
<li>192.168.1.100</li>
|
||
<li>camera.local</li>
|
||
<li>rtsp://user:pass@192.168.1.100/stream</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Screen 2: Configuration Form -->
|
||
<div id="screen-config" class="screen">
|
||
<div class="container">
|
||
<button id="btn-back-to-address" class="btn-back">
|
||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
|
||
<path d="M12 4L6 10l6 6" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||
</svg>
|
||
Back
|
||
</button>
|
||
|
||
<h2 class="screen-title">Camera Configuration</h2>
|
||
|
||
<div class="form-group">
|
||
<label for="address-validated" class="label label-with-info">
|
||
Network Address
|
||
<span class="info-icon">
|
||
<svg viewBox="0 0 16 16" fill="none">
|
||
<circle cx="8" cy="8" r="7" stroke="currentColor" stroke-width="1.5"/>
|
||
<path d="M8 7v4M8 5v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||
</svg>
|
||
<div class="tooltip tooltip-down">
|
||
<div class="tooltip-title">Network Address</div>
|
||
<p class="tooltip-text">The IP address, hostname, or full RTSP URL of your camera. This is the network location where the camera can be reached.</p>
|
||
<div class="tooltip-examples">
|
||
<div class="tooltip-examples-title">Examples:</div>
|
||
<code class="tooltip-example">192.168.1.100</code>
|
||
<code class="tooltip-example">camera.local</code>
|
||
<code class="tooltip-example">rtsp://admin:pass@192.168.1.100</code>
|
||
</div>
|
||
<p class="tooltip-text">Find it in your camera's network settings or router's device list (DHCP leases).</p>
|
||
</div>
|
||
</span>
|
||
</label>
|
||
<div class="input-validated">
|
||
<input
|
||
type="text"
|
||
id="address-validated"
|
||
class="input"
|
||
readonly
|
||
>
|
||
<svg class="icon-check" width="20" height="20" viewBox="0 0 20 20" fill="none">
|
||
<path d="M4 10l4 4 8-8" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="camera-model" class="label label-with-info">
|
||
Camera Model <span class="optional">(optional)</span>
|
||
<span class="info-icon">
|
||
<svg viewBox="0 0 16 16" fill="none">
|
||
<circle cx="8" cy="8" r="7" stroke="currentColor" stroke-width="1.5"/>
|
||
<path d="M8 7v4M8 5v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||
</svg>
|
||
<div class="tooltip tooltip-down">
|
||
<div class="tooltip-title">Camera Model</div>
|
||
<p class="tooltip-text">The manufacturer and model of your IP camera. This helps the system use optimized stream paths for your specific camera brand.</p>
|
||
<div class="tooltip-examples">
|
||
<div class="tooltip-examples-title">Examples:</div>
|
||
<code class="tooltip-example">Hikvision: DS-2CD2142FWD</code>
|
||
<code class="tooltip-example">Dahua: IPC-HDW4433C</code>
|
||
<code class="tooltip-example">Amcrest: IP4M-1041</code>
|
||
<code class="tooltip-example">Reolink: RLC-410</code>
|
||
</div>
|
||
<p class="tooltip-text">Find it on the camera label, in the camera's web interface (Device Info), or in your purchase documentation. Leave empty for auto-detection.</p>
|
||
</div>
|
||
</span>
|
||
</label>
|
||
<div class="autocomplete-wrapper">
|
||
<input
|
||
type="text"
|
||
id="camera-model"
|
||
class="input"
|
||
placeholder="Start typing..."
|
||
autocomplete="off"
|
||
spellcheck="false"
|
||
>
|
||
<div id="autocomplete-dropdown" class="autocomplete-dropdown hidden"></div>
|
||
</div>
|
||
<p id="model-disabled-hint" class="hint hidden">Detected from URL, continue below</p>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="username" class="label label-with-info">
|
||
Username
|
||
<span class="info-icon">
|
||
<svg viewBox="0 0 16 16" fill="none">
|
||
<circle cx="8" cy="8" r="7" stroke="currentColor" stroke-width="1.5"/>
|
||
<path d="M8 7v4M8 5v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||
</svg>
|
||
<div class="tooltip">
|
||
<div class="tooltip-title">Username</div>
|
||
<p class="tooltip-text">The authentication username for accessing your camera's RTSP stream. This is required for most IP cameras to access video feeds.</p>
|
||
<div class="tooltip-examples">
|
||
<div class="tooltip-examples-title">Common defaults:</div>
|
||
<code class="tooltip-example">admin</code>
|
||
<code class="tooltip-example">root</code>
|
||
<code class="tooltip-example">user</code>
|
||
</div>
|
||
<p class="tooltip-text">Find it in your camera setup documentation or the camera's web interface under User Management. Change default credentials for security.</p>
|
||
</div>
|
||
</span>
|
||
</label>
|
||
<input
|
||
type="text"
|
||
id="username"
|
||
class="input"
|
||
placeholder="admin"
|
||
autocomplete="off"
|
||
>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="password" class="label label-with-info">
|
||
Password
|
||
<span class="info-icon">
|
||
<svg viewBox="0 0 16 16" fill="none">
|
||
<circle cx="8" cy="8" r="7" stroke="currentColor" stroke-width="1.5"/>
|
||
<path d="M8 7v4M8 5v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||
</svg>
|
||
<div class="tooltip">
|
||
<div class="tooltip-title">Password</div>
|
||
<p class="tooltip-text">The authentication password for your camera's RTSP stream. This credential is used together with the username to access the video feed.</p>
|
||
<p class="tooltip-text">For security reasons, always use a strong, unique password and avoid default passwords like "12345" or "password".</p>
|
||
<p class="tooltip-text">Find it in your camera's documentation, setup guide, or change it via the camera's web interface under Security/User Management settings.</p>
|
||
</div>
|
||
</span>
|
||
</label>
|
||
<div class="input-password-wrapper">
|
||
<input
|
||
type="password"
|
||
id="password"
|
||
class="input"
|
||
placeholder="••••••••"
|
||
autocomplete="off"
|
||
>
|
||
<button type="button" class="btn-toggle-password" aria-label="Toggle password visibility">
|
||
<svg class="icon-eye" width="20" height="20" viewBox="0 0 20 20" fill="none">
|
||
<circle cx="10" cy="10" r="3" stroke="currentColor" stroke-width="1.5"/>
|
||
<path d="M2 10c1.5-4 4-6.5 8-6.5s6.5 2.5 8 6.5c-1.5 4-4 6.5-8 6.5S3.5 14 2 10z" stroke="currentColor" stroke-width="1.5"/>
|
||
<circle cx="10" cy="10" r="1.5" fill="currentColor"/>
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="channel" class="label label-with-info">
|
||
Channel
|
||
<span class="info-icon">
|
||
<svg viewBox="0 0 16 16" fill="none">
|
||
<circle cx="8" cy="8" r="7" stroke="currentColor" stroke-width="1.5"/>
|
||
<path d="M8 7v4M8 5v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||
</svg>
|
||
<div class="tooltip">
|
||
<div class="tooltip-title">Channel Number</div>
|
||
<p class="tooltip-text">The channel number identifies which specific camera or video input to access on the device.</p>
|
||
<p class="tooltip-text"><strong>For standalone IP cameras:</strong> Always use 0 (default). Single cameras don't use channel numbers.</p>
|
||
<p class="tooltip-text"><strong>For NVR/DVR systems ONLY:</strong> Each connected camera has its own channel number. Channel numbering typically starts from 0.</p>
|
||
<div class="tooltip-examples">
|
||
<div class="tooltip-examples-title">NVR/DVR channel values:</div>
|
||
<code class="tooltip-example">0 - First camera on NVR/DVR</code>
|
||
<code class="tooltip-example">1 - Second camera on NVR/DVR</code>
|
||
<code class="tooltip-example">2-15 - Additional cameras (for 4, 8, 16-channel NVRs)</code>
|
||
</div>
|
||
<p class="tooltip-text">Check your NVR's camera list in the device web interface to see the correct channel assignment for each camera.</p>
|
||
</div>
|
||
</span>
|
||
</label>
|
||
<input
|
||
type="number"
|
||
id="channel"
|
||
class="input"
|
||
value="0"
|
||
min="0"
|
||
max="255"
|
||
>
|
||
</div>
|
||
|
||
<details class="advanced-section">
|
||
<summary class="advanced-toggle">Advanced</summary>
|
||
<div class="advanced-content">
|
||
|
||
<div class="form-group">
|
||
<label class="label label-with-info">
|
||
Resolution <span class="optional">(optional)</span>
|
||
<span class="info-icon">
|
||
<svg viewBox="0 0 16 16" fill="none">
|
||
<circle cx="8" cy="8" r="7" stroke="currentColor" stroke-width="1.5"/>
|
||
<path d="M8 7v4M8 5v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||
</svg>
|
||
<div class="tooltip">
|
||
<div class="tooltip-title">Resolution Filter</div>
|
||
<p class="tooltip-text">Optionally filter discovered streams by specific resolution. Leave empty to find all available resolutions. Use this to target specific stream qualities.</p>
|
||
<div class="tooltip-examples">
|
||
<div class="tooltip-examples-title">Common resolutions:</div>
|
||
<code class="tooltip-example">1920 × 1080 - Full HD (main stream)</code>
|
||
<code class="tooltip-example">1280 × 720 - HD (sub stream)</code>
|
||
<code class="tooltip-example">640 × 480 - VGA (low quality)</code>
|
||
<code class="tooltip-example">3840 × 2160 - 4K Ultra HD</code>
|
||
</div>
|
||
<p class="tooltip-text">Tip: Leave empty for initial discovery, then use specific values to find particular stream types (main vs sub streams).</p>
|
||
</div>
|
||
</span>
|
||
</label>
|
||
<div class="input-row">
|
||
<input
|
||
type="number"
|
||
id="width"
|
||
class="input"
|
||
placeholder="Width"
|
||
>
|
||
<span class="input-separator">×</span>
|
||
<input
|
||
type="number"
|
||
id="height"
|
||
class="input"
|
||
placeholder="Height"
|
||
>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label for="max-streams" class="label label-with-info">
|
||
Max Streams
|
||
<span class="info-icon">
|
||
<svg viewBox="0 0 16 16" fill="none">
|
||
<circle cx="8" cy="8" r="7" stroke="currentColor" stroke-width="1.5"/>
|
||
<path d="M8 7v4M8 5v.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||
</svg>
|
||
<div class="tooltip">
|
||
<div class="tooltip-title">Maximum Streams</div>
|
||
<p class="tooltip-text">The maximum number of stream URLs to test during discovery. Higher values increase scan time but may find more stream variants. Lower values speed up discovery.</p>
|
||
<div class="tooltip-examples">
|
||
<div class="tooltip-examples-title">Recommended values:</div>
|
||
<code class="tooltip-example">5 - Quick scan (faster)</code>
|
||
<code class="tooltip-example">10 - Balanced (default)</code>
|
||
<code class="tooltip-example">20-50 - Thorough scan (slower)</code>
|
||
</div>
|
||
<p class="tooltip-text">Purpose: Controls how many different RTSP URL patterns are tested. Most cameras have 2-5 valid streams (main, sub, mobile, etc.).</p>
|
||
</div>
|
||
</span>
|
||
</label>
|
||
<input
|
||
type="number"
|
||
id="max-streams"
|
||
class="input"
|
||
value="10"
|
||
min="1"
|
||
max="50"
|
||
>
|
||
</div>
|
||
</div>
|
||
</details>
|
||
|
||
<button id="btn-discover" class="btn btn-primary btn-large">
|
||
Discover Streams
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Screen 3: Stream Discovery -->
|
||
<div id="screen-discovery" class="screen">
|
||
<div class="container">
|
||
<button id="btn-back-to-config" class="btn-back">
|
||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
|
||
<path d="M12 4L6 10l6 6" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||
</svg>
|
||
Back to Configuration
|
||
</button>
|
||
|
||
<h2 class="screen-title">Discovering Streams</h2>
|
||
|
||
<div class="progress-container">
|
||
<div class="progress-bar">
|
||
<div id="progress-fill" class="progress-fill"></div>
|
||
</div>
|
||
<p id="progress-text" class="progress-text">Starting scan...</p>
|
||
</div>
|
||
|
||
|
||
<div id="streams-section" class="streams-section hidden">
|
||
<h3 class="section-title">Found Connections</h3>
|
||
|
||
<div id="streams-list" class="streams-list"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Screen 4: Configuration Output -->
|
||
<div id="screen-output" class="screen">
|
||
<div class="container">
|
||
<button id="btn-back-to-streams" class="btn-back">
|
||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
|
||
<path d="M12 4L6 10l6 6" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||
</svg>
|
||
Back to Streams
|
||
</button>
|
||
|
||
<h2 class="screen-title">Stream Configuration</h2>
|
||
|
||
<div class="stream-selection-container">
|
||
<div class="selected-stream-info">
|
||
<p class="stream-label">Main Stream</p>
|
||
<p id="selected-main-type" class="selected-type"></p>
|
||
<p id="selected-main-url" class="selected-url"></p>
|
||
</div>
|
||
|
||
<div id="sub-stream-info" class="selected-stream-info sub-stream hidden">
|
||
<p class="stream-label">Sub Stream</p>
|
||
<p id="selected-sub-type" class="selected-type"></p>
|
||
<p id="selected-sub-url" class="selected-url"></p>
|
||
<button id="btn-remove-sub" class="btn-remove-sub">Remove Sub Stream</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="tabs">
|
||
<div class="tabs-scroll">
|
||
<button class="tab active" data-tab="url">URL</button>
|
||
<button class="tab" data-tab="go2rtc">Go2RTC</button>
|
||
<button class="tab" data-tab="frigate">Frigate</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="tab-content">
|
||
<div class="tab-pane active" data-pane="url">
|
||
<pre id="config-url" class="config-code"></pre>
|
||
</div>
|
||
<div class="tab-pane" data-pane="go2rtc">
|
||
<pre id="config-go2rtc" class="config-code"></pre>
|
||
</div>
|
||
<div class="tab-pane" data-pane="frigate">
|
||
<!-- Input section for existing config -->
|
||
<div class="frigate-input-section">
|
||
<label class="frigate-label">
|
||
Your Current Frigate Config
|
||
<span class="hint">Paste your existing config.yml or leave the example below</span>
|
||
</label>
|
||
<textarea
|
||
id="existing-frigate-config"
|
||
class="textarea frigate-config-input"
|
||
rows="12"
|
||
placeholder="Paste your existing Frigate config here..."></textarea>
|
||
</div>
|
||
|
||
<!-- Generate button -->
|
||
<button id="btn-generate-frigate" class="btn btn-primary btn-generate">
|
||
Generate Config
|
||
</button>
|
||
|
||
<!-- Output section (hidden by default) -->
|
||
<div id="frigate-output-section" class="frigate-output-section hidden">
|
||
<label class="frigate-label">Updated Config (Camera Added)</label>
|
||
<pre id="config-frigate" class="config-code"></pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="actions">
|
||
<button id="btn-copy-config" class="btn btn-secondary">
|
||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
|
||
<rect x="6" y="6" width="10" height="10" rx="1" stroke="currentColor" stroke-width="1.5"/>
|
||
<path d="M4 4h10v2H5v9H4V4z" fill="currentColor"/>
|
||
</svg>
|
||
Copy
|
||
</button>
|
||
<button id="btn-download-config" class="btn btn-secondary">
|
||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
|
||
<path d="M10 3v10m0 0l-4-4m4 4l4-4M4 17h12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
|
||
</svg>
|
||
Download
|
||
</button>
|
||
</div>
|
||
|
||
<div class="secondary-actions">
|
||
<button id="btn-add-sub-stream" class="btn btn-primary">
|
||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
|
||
<path d="M10 4v12M4 10h12" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
|
||
</svg>
|
||
Add Sub Stream
|
||
</button>
|
||
<button id="btn-new-search" class="btn btn-outline">
|
||
Add Another Camera
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Toast Notification -->
|
||
<div id="toast" class="toast hidden"></div>
|
||
|
||
<script type="module" src="js/main.js"></script>
|
||
</body>
|
||
</html>
|