Add informational tooltips for stream types and update mock data
- Add tooltips for all 7 stream types: FFMPEG, ONVIF, MJPEG, HLS, BUBBLE, JPEG, HTTP_VIDEO - Each tooltip explains protocol features, use cases, and compatibility - Add BUBBLE protocol icon and detailed description (XMEye/DVRIP cameras) - Update mock streams to show one example of each type - Remove unused mock-data.js file to reduce confusion - Add CSS styles for stream type info icons
This commit is contained in:
@@ -1110,6 +1110,29 @@ body {
|
|||||||
height: 18px;
|
height: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Info icon inside stream type badge */
|
||||||
|
.info-icon-stream {
|
||||||
|
position: relative;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
margin-left: var(--space-2);
|
||||||
|
cursor: help;
|
||||||
|
color: var(--text-tertiary);
|
||||||
|
transition: color var(--transition-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-icon-stream:hover {
|
||||||
|
color: var(--purple-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-icon-stream svg {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
.frigate-output-section {
|
.frigate-output-section {
|
||||||
margin-top: var(--space-6);
|
margin-top: var(--space-6);
|
||||||
padding-top: var(--space-6);
|
padding-top: var(--space-6);
|
||||||
|
|||||||
@@ -53,14 +53,14 @@ export class MockStreamAPI {
|
|||||||
has_audio: false
|
has_audio: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
url: "rtsp://192.168.1.100:554/Streaming/Channels/102",
|
url: "bubble://192.168.1.100:34567/bubble/live?ch=0&stream=0",
|
||||||
path: "/Streaming/Channels/102",
|
path: "/bubble/live?ch=0&stream=0",
|
||||||
type: "FFMPEG",
|
type: "BUBBLE",
|
||||||
resolution: "640x480",
|
resolution: "1920x1080",
|
||||||
codec: "H.264",
|
codec: "H.264",
|
||||||
fps: 15,
|
fps: 25,
|
||||||
bitrate: 512000,
|
bitrate: 3072000,
|
||||||
has_audio: false
|
has_audio: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
url: "rtsp://192.168.1.100:554/cam/realmonitor?channel=1&subtype=0",
|
url: "rtsp://192.168.1.100:554/cam/realmonitor?channel=1&subtype=0",
|
||||||
@@ -71,36 +71,6 @@ export class MockStreamAPI {
|
|||||||
fps: 30,
|
fps: 30,
|
||||||
bitrate: 6144000,
|
bitrate: 6144000,
|
||||||
has_audio: true
|
has_audio: true
|
||||||
},
|
|
||||||
{
|
|
||||||
url: "rtsp://192.168.1.100:554/h264Preview_01_main",
|
|
||||||
path: "/h264Preview_01_main",
|
|
||||||
type: "FFMPEG",
|
|
||||||
resolution: "1920x1080",
|
|
||||||
codec: "H.264",
|
|
||||||
fps: 20,
|
|
||||||
bitrate: 3072000,
|
|
||||||
has_audio: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: "rtsp://192.168.1.100:554/live/ch0",
|
|
||||||
path: "/live/ch0",
|
|
||||||
type: "ONVIF",
|
|
||||||
resolution: "2688x1520",
|
|
||||||
codec: "H.265",
|
|
||||||
fps: 25,
|
|
||||||
bitrate: 5120000,
|
|
||||||
has_audio: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
url: "rtsp://192.168.1.100:554/stream1",
|
|
||||||
path: "/stream1",
|
|
||||||
type: "FFMPEG",
|
|
||||||
resolution: "3840x2160",
|
|
||||||
codec: "H.265",
|
|
||||||
fps: 30,
|
|
||||||
bitrate: 8192000,
|
|
||||||
has_audio: true
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ export class StreamList {
|
|||||||
<div class="stream-type-badge">
|
<div class="stream-type-badge">
|
||||||
${icon}
|
${icon}
|
||||||
<span>${stream.type}</span>
|
<span>${stream.type}</span>
|
||||||
|
${this.getStreamTypeTooltip(stream.type)}
|
||||||
</div>
|
</div>
|
||||||
<div class="stream-url-preview">${truncatedUrl}</div>
|
<div class="stream-url-preview">${truncatedUrl}</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -65,11 +66,164 @@ export class StreamList {
|
|||||||
'JPEG': '<svg width="20" height="20" viewBox="0 0 20 20" fill="none"><rect x="3" y="4" width="14" height="12" rx="1" stroke="currentColor" stroke-width="1.5"/><circle cx="7" cy="8" r="1" fill="currentColor"/><path d="M3 13l4-4 3 3 5-5" stroke="currentColor" stroke-width="1.5"/></svg>',
|
'JPEG': '<svg width="20" height="20" viewBox="0 0 20 20" fill="none"><rect x="3" y="4" width="14" height="12" rx="1" stroke="currentColor" stroke-width="1.5"/><circle cx="7" cy="8" r="1" fill="currentColor"/><path d="M3 13l4-4 3 3 5-5" stroke="currentColor" stroke-width="1.5"/></svg>',
|
||||||
'MJPEG': '<svg width="20" height="20" viewBox="0 0 20 20" fill="none"><rect x="2" y="4" width="7" height="12" rx="1" stroke="currentColor" stroke-width="1.5"/><rect x="11" y="4" width="7" height="12" rx="1" stroke="currentColor" stroke-width="1.5"/><path d="M5 8l2 2-2 2M14 8l2 2-2 2" stroke="currentColor" stroke-width="1.5"/></svg>',
|
'MJPEG': '<svg width="20" height="20" viewBox="0 0 20 20" fill="none"><rect x="2" y="4" width="7" height="12" rx="1" stroke="currentColor" stroke-width="1.5"/><rect x="11" y="4" width="7" height="12" rx="1" stroke="currentColor" stroke-width="1.5"/><path d="M5 8l2 2-2 2M14 8l2 2-2 2" stroke="currentColor" stroke-width="1.5"/></svg>',
|
||||||
'HLS': '<svg width="20" height="20" viewBox="0 0 20 20" fill="none"><circle cx="10" cy="10" r="7" stroke="currentColor" stroke-width="1.5"/><path d="M10 6v8M6 10h8" stroke="currentColor" stroke-width="1.5"/></svg>',
|
'HLS': '<svg width="20" height="20" viewBox="0 0 20 20" fill="none"><circle cx="10" cy="10" r="7" stroke="currentColor" stroke-width="1.5"/><path d="M10 6v8M6 10h8" stroke="currentColor" stroke-width="1.5"/></svg>',
|
||||||
'HTTP_VIDEO': '<svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M7 6l6 4-6 4V6z" fill="currentColor"/><circle cx="10" cy="10" r="8" stroke="currentColor" stroke-width="1.5"/></svg>'
|
'HTTP_VIDEO': '<svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M7 6l6 4-6 4V6z" fill="currentColor"/><circle cx="10" cy="10" r="8" stroke="currentColor" stroke-width="1.5"/></svg>',
|
||||||
|
'BUBBLE': '<svg width="20" height="20" viewBox="0 0 20 20" fill="none"><circle cx="10" cy="10" r="7" stroke="currentColor" stroke-width="1.5"/><circle cx="7" cy="9" r="1.5" fill="currentColor"/><circle cx="10" cy="9" r="1.5" fill="currentColor"/><circle cx="13" cy="9" r="1.5" fill="currentColor"/><path d="M6 13q2 2 4 2t4-2" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>'
|
||||||
};
|
};
|
||||||
return icons[type] || icons['FFMPEG'];
|
return icons[type] || icons['FFMPEG'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getStreamTypeTooltip(type) {
|
||||||
|
const tooltips = {
|
||||||
|
'FFMPEG': `
|
||||||
|
<span class="info-icon info-icon-stream">
|
||||||
|
<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">FFMPEG Stream</div>
|
||||||
|
<p class="tooltip-text">Standard video stream decoded by FFmpeg. Most compatible and widely supported format for RTSP, HTTP, and other protocols.</p>
|
||||||
|
<div class="tooltip-examples">
|
||||||
|
<div class="tooltip-examples-title">Features:</div>
|
||||||
|
<code class="tooltip-example">✓ Universal compatibility</code>
|
||||||
|
<code class="tooltip-example">✓ Supports H.264, H.265, MJPEG</code>
|
||||||
|
<code class="tooltip-example">✓ Works with most cameras</code>
|
||||||
|
<code class="tooltip-example">✓ Best for recording</code>
|
||||||
|
</div>
|
||||||
|
<p class="tooltip-text"><strong>Best for:</strong> Main streams, recording, high-quality playback. Default choice for most use cases.</p>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
`,
|
||||||
|
'ONVIF': `
|
||||||
|
<span class="info-icon info-icon-stream">
|
||||||
|
<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">ONVIF Stream</div>
|
||||||
|
<p class="tooltip-text">Industry standard protocol for IP cameras. Discovered via ONVIF specification, ensuring maximum compatibility with camera features.</p>
|
||||||
|
<div class="tooltip-examples">
|
||||||
|
<div class="tooltip-examples-title">Features:</div>
|
||||||
|
<code class="tooltip-example">✓ Standardized protocol</code>
|
||||||
|
<code class="tooltip-example">✓ Auto-discovery support</code>
|
||||||
|
<code class="tooltip-example">✓ PTZ control capable</code>
|
||||||
|
<code class="tooltip-example">✓ Vendor-independent</code>
|
||||||
|
</div>
|
||||||
|
<p class="tooltip-text"><strong>Best for:</strong> Enterprise cameras, systems requiring standardization, cameras with PTZ controls.</p>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
`,
|
||||||
|
'JPEG': `
|
||||||
|
<span class="info-icon info-icon-stream">
|
||||||
|
<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">JPEG Snapshot</div>
|
||||||
|
<p class="tooltip-text">Single static image endpoint. Can be converted to video stream by repeatedly fetching images.</p>
|
||||||
|
<div class="tooltip-examples">
|
||||||
|
<div class="tooltip-examples-title">Features:</div>
|
||||||
|
<code class="tooltip-example">✓ Low bandwidth</code>
|
||||||
|
<code class="tooltip-example">✓ Simple HTTP request</code>
|
||||||
|
<code class="tooltip-example">✓ No streaming protocol needed</code>
|
||||||
|
<code class="tooltip-example">⚠ Limited framerate (1-10 fps)</code>
|
||||||
|
</div>
|
||||||
|
<p class="tooltip-text"><strong>Best for:</strong> Thumbnails, snapshots, very low bandwidth scenarios. Not recommended for recording.</p>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
`,
|
||||||
|
'MJPEG': `
|
||||||
|
<span class="info-icon info-icon-stream">
|
||||||
|
<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">MJPEG Stream</div>
|
||||||
|
<p class="tooltip-text">Motion JPEG - sequence of JPEG images transmitted continuously. Simple but bandwidth-intensive.</p>
|
||||||
|
<div class="tooltip-examples">
|
||||||
|
<div class="tooltip-examples-title">Features:</div>
|
||||||
|
<code class="tooltip-example">✓ Simple HTTP streaming</code>
|
||||||
|
<code class="tooltip-example">✓ No complex codecs</code>
|
||||||
|
<code class="tooltip-example">✓ Frame-by-frame</code>
|
||||||
|
<code class="tooltip-example">⚠ High bandwidth usage</code>
|
||||||
|
</div>
|
||||||
|
<p class="tooltip-text"><strong>Best for:</strong> Sub streams, low-latency monitoring, simple camera integration. Higher bandwidth than H.264.</p>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
`,
|
||||||
|
'HLS': `
|
||||||
|
<span class="info-icon info-icon-stream">
|
||||||
|
<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">HLS Stream</div>
|
||||||
|
<p class="tooltip-text">HTTP Live Streaming - Apple's adaptive bitrate streaming protocol. Delivers video in small chunks over HTTP.</p>
|
||||||
|
<div class="tooltip-examples">
|
||||||
|
<div class="tooltip-examples-title">Features:</div>
|
||||||
|
<code class="tooltip-example">✓ Adaptive bitrate</code>
|
||||||
|
<code class="tooltip-example">✓ Wide browser support</code>
|
||||||
|
<code class="tooltip-example">✓ Firewall-friendly (HTTP)</code>
|
||||||
|
<code class="tooltip-example">⚠ Higher latency (5-30s)</code>
|
||||||
|
</div>
|
||||||
|
<p class="tooltip-text"><strong>Best for:</strong> Web playback, public streaming, CDN delivery. Not ideal for real-time monitoring.</p>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
`,
|
||||||
|
'HTTP_VIDEO': `
|
||||||
|
<span class="info-icon info-icon-stream">
|
||||||
|
<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">HTTP Video Stream</div>
|
||||||
|
<p class="tooltip-text">Generic HTTP-based video stream. Simple protocol that works over standard web connections.</p>
|
||||||
|
<div class="tooltip-examples">
|
||||||
|
<div class="tooltip-examples-title">Features:</div>
|
||||||
|
<code class="tooltip-example">✓ Simple HTTP protocol</code>
|
||||||
|
<code class="tooltip-example">✓ No special ports</code>
|
||||||
|
<code class="tooltip-example">✓ Firewall-friendly</code>
|
||||||
|
<code class="tooltip-example">✓ Direct browser playback</code>
|
||||||
|
</div>
|
||||||
|
<p class="tooltip-text"><strong>Best for:</strong> Quick viewing, simple setups, scenarios where RTSP ports are blocked.</p>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
`,
|
||||||
|
'BUBBLE': `
|
||||||
|
<span class="info-icon info-icon-stream">
|
||||||
|
<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">BUBBLE / DVRIP Protocol</div>
|
||||||
|
<p class="tooltip-text">Proprietary protocol for Chinese DVR/NVR cameras. Also known as: ESeeCloud, dvr163, DVR-IP, NetSurveillance, Sofia protocol, XMeye SDK.</p>
|
||||||
|
<div class="tooltip-examples">
|
||||||
|
<div class="tooltip-examples-title">Compatible brands:</div>
|
||||||
|
<code class="tooltip-example">XMEye, Floureon, ZOSI</code>
|
||||||
|
<code class="tooltip-example">Sannce, Annke, DVR163</code>
|
||||||
|
<code class="tooltip-example">ESeeCloud, NetSurveillance</code>
|
||||||
|
</div>
|
||||||
|
<div class="tooltip-examples">
|
||||||
|
<div class="tooltip-examples-title">Features:</div>
|
||||||
|
<code class="tooltip-example">⚠ Proprietary protocol</code>
|
||||||
|
<code class="tooltip-example">✓ Go2RTC converts to standard</code>
|
||||||
|
<code class="tooltip-example">✓ Two-way audio support</code>
|
||||||
|
<code class="tooltip-example">⚠ TCP only (port 34567)</code>
|
||||||
|
</div>
|
||||||
|
<p class="tooltip-text"><strong>Note:</strong> Automatically converted to standard RTSP format by Go2RTC. Works seamlessly with Frigate without additional configuration.</p>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
`
|
||||||
|
};
|
||||||
|
return tooltips[type] || '';
|
||||||
|
}
|
||||||
|
|
||||||
attachEventListeners() {
|
attachEventListeners() {
|
||||||
// Click on header to toggle
|
// Click on header to toggle
|
||||||
this.listContainer.querySelectorAll('.stream-item-header').forEach(header => {
|
this.listContainer.querySelectorAll('.stream-item-header').forEach(header => {
|
||||||
|
|||||||
Reference in New Issue
Block a user