Add BUBBLE protocol support for XMeye/HiSilicon NVR/DVR cameras

Implemented comprehensive BUBBLE protocol support for Chinese NVR/DVR cameras (ZOSI, SANNCE, ANNKE, FLOUREON, XMeye). This proprietary protocol requires HTTP with embedded credentials and special handling.

Changes:
- Added BUBBLE entries to brand databases with main/sub stream support
- Extended URL placeholder system to support {channel} syntax
- Implemented BUBBLE-specific stream generation with credential embedding
- Added BUBBLE stream detection via Content-Type: video/bubble
- Updated Frigate/Go2RTC generators to convert BUBBLE URLs to bubble:// format
- Added BUBBLE patterns to popular stream database

Technical details:
- BUBBLE uses HTTP protocol with credentials in URL (bubble://user:pass@host:port/path)
- Supports dual streams: stream=0 (main) and stream=1 (sub)
- Requires video=copy parameter for optimal performance in go2rtc
- Detection prioritized before generic HTTP checks to ensure correct identification
This commit is contained in:
eduard256
2025-11-09 18:09:04 +03:00
parent 75afc987f4
commit 35293dec83
10 changed files with 266 additions and 10 deletions
@@ -144,6 +144,21 @@ export class FrigateGenerator {
}
}
// Handle BUBBLE protocol - convert to bubble:// format for go2rtc
if (stream.type === 'BUBBLE') {
try {
const urlObj = new URL(stream.url);
const username = urlObj.username || 'admin';
const password = urlObj.password || '';
const host = urlObj.hostname;
const port = urlObj.port || '80';
const path = urlObj.pathname + urlObj.search;
return `bubble://${username}:${password}@${host}:${port}${path}#video=copy`;
} catch (e) {
return stream.url;
}
}
// For all other types (RTSP, MJPEG, HLS, HTTP-FLV, RTMP, etc.): use direct URL
// Go2RTC handles these formats natively
return stream.url;
@@ -60,6 +60,11 @@ export class Go2RTCGenerator {
return this.generateONVIFSource(stream);
}
// Handle BUBBLE protocol
if (stream.type === 'BUBBLE') {
return this.generateBubbleSource(stream);
}
// For all other types: use direct URL
return stream.url;
}
@@ -100,4 +105,23 @@ export class Go2RTCGenerator {
return stream.url;
}
}
/**
* Generate BUBBLE source
* Converts HTTP BUBBLE endpoint to bubble:// format for go2rtc
* Format: bubble://user:pass@host:port/bubble/live?ch=X&stream=Y#video=copy
*/
static generateBubbleSource(stream) {
try {
const urlObj = new URL(stream.url);
const username = urlObj.username || 'admin';
const password = urlObj.password || '';
const host = urlObj.hostname;
const port = urlObj.port || '80';
const path = urlObj.pathname + urlObj.search;
return `bubble://${username}:${password}@${host}:${port}${path}#video=copy`;
} catch (e) {
return stream.url;
}
}
}