Merge pull request #1 from outis1one/clDemoe/camera-live-view-app-dlYME
ClDemoe/camera live view app dl yme
This commit is contained in:
+29
-4
@@ -52,18 +52,43 @@ sudo journalctl -u doorbell -f # live logs
|
||||
Add to home screen (Chrome menu -> Add to home screen) for an app-like
|
||||
experience.
|
||||
|
||||
## Changing the camera
|
||||
## Choosing the camera
|
||||
|
||||
Each Pi is hardcoded to one camera -- the one whose mic and speaker are
|
||||
physically co-located with this Pi. The PTT button on this page only
|
||||
talks to *this* Pi's speaker, so mixing cameras here would let a misclick
|
||||
talk into the wrong room.
|
||||
|
||||
`server.py` near the top:
|
||||
```js
|
||||
const CAMERA_NAME = "front_door";
|
||||
```python
|
||||
CAMERA_NAME = "front_door"
|
||||
```
|
||||
|
||||
After editing:
|
||||
The name must match a `go2rtc.streams` entry in
|
||||
`frigate_config/config.yml` and the camera must be `enabled: true` in
|
||||
Frigate. After editing:
|
||||
```bash
|
||||
sudo systemctl restart doorbell
|
||||
```
|
||||
|
||||
## Multiple doorbell Pis
|
||||
|
||||
Run one copy of this app per Pi, each on its own subdomain (e.g.
|
||||
`frontdoor.yourdomain.com`, `backdoor.yourdomain.com`). Add a Caddy
|
||||
block per subdomain pointing at that Pi's LAN IP -- same shape as the
|
||||
existing `doorbell.yourdomain.com` block in `../caddy/Caddyfile`.
|
||||
|
||||
To render quick-jump buttons to the other Pis at the top of the page,
|
||||
fill in `PEER_LINKS` near the top of `server.py`:
|
||||
```python
|
||||
PEER_LINKS = [
|
||||
{"label": "Back door", "url": "https://backdoor.yourdomain.com"},
|
||||
{"label": "Squirrel", "url": "https://squirrel.yourdomain.com"},
|
||||
]
|
||||
```
|
||||
Leave it as `[]` (the default) and the row is hidden. Restart with
|
||||
`sudo systemctl restart doorbell` after editing.
|
||||
|
||||
## Audio stack
|
||||
|
||||
ALSA-only -- no PipeWire/PulseAudio. Lighter on the Pi Zero. If you ever
|
||||
|
||||
+32
-4
@@ -20,6 +20,18 @@ from flask_sock import Sock
|
||||
app = Flask(__name__)
|
||||
sock = Sock(app)
|
||||
|
||||
# Camera this Pi corresponds to. Must match a go2rtc stream name in
|
||||
# frigate_config/config.yml. The PTT button talks to the speaker physically
|
||||
# attached to this Pi, so this should be the camera at the same location.
|
||||
CAMERA_NAME = "front_door"
|
||||
|
||||
# Optional jump-links to sibling doorbell Pis (each running its own copy of
|
||||
# this app, hardcoded to its own camera). Rendered as a row of buttons above
|
||||
# the PTT button when non-empty. Leave empty if there are no other Pis.
|
||||
PEER_LINKS = [
|
||||
# {"label": "Back door", "url": "https://backdoor.yourdomain.com"},
|
||||
]
|
||||
|
||||
PAGE = """<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
@@ -46,6 +58,9 @@ PAGE = """<!doctype html>
|
||||
.row{display:flex;gap:8px}
|
||||
.row button{flex:1;padding:10px;background:#333;color:#fff;border:none;
|
||||
border-radius:8px;font-size:13px}
|
||||
.row a{flex:1;padding:10px;background:#333;color:#fff;border-radius:8px;
|
||||
font-size:13px;text-decoration:none;text-align:center;
|
||||
display:flex;align-items:center;justify-content:center}
|
||||
#status{font-size:12px;color:#888;text-align:center;min-height:1em}
|
||||
</style>
|
||||
</head>
|
||||
@@ -55,6 +70,7 @@ PAGE = """<!doctype html>
|
||||
<video id="cam" autoplay playsinline muted></video>
|
||||
</div>
|
||||
<div id="controls">
|
||||
<div class="row" id="peers" style="display:none"></div>
|
||||
<button id="ptt" disabled>Connecting...</button>
|
||||
<div class="row">
|
||||
<button id="unmute">Unmute camera</button>
|
||||
@@ -67,18 +83,30 @@ PAGE = """<!doctype html>
|
||||
|
||||
<script>
|
||||
// ---- CONFIG ---------------------------------------------------------
|
||||
const CAMERA_NAME = "front_door";
|
||||
const FRIGATE_WEBRTC_URL = "/frigate/api/go2rtc/api/webrtc?src=" + CAMERA_NAME;
|
||||
const CAMERA_NAME = {{ camera_name|tojson }};
|
||||
const PEERS = {{ peers|tojson }};
|
||||
const FRIGATE_WEBRTC_URL = "/frigate/api/go2rtc/api/webrtc?src=" + encodeURIComponent(CAMERA_NAME);
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
const $ = id => document.getElementById(id);
|
||||
const ptt = $('ptt'), status = $('status'), video = $('cam'),
|
||||
unmute = $('unmute'), reload = $('reload'), wake = $('wake');
|
||||
unmute = $('unmute'), reload = $('reload'), wake = $('wake'),
|
||||
peersRow = $('peers');
|
||||
|
||||
let ws, mediaRecorder, micStream, wakeLock = null;
|
||||
|
||||
const log = m => { status.textContent = m; console.log('[doorbell]', m); };
|
||||
|
||||
if (PEERS.length) {
|
||||
for (const p of PEERS) {
|
||||
const a = document.createElement('a');
|
||||
a.href = p.url;
|
||||
a.textContent = p.label;
|
||||
peersRow.appendChild(a);
|
||||
}
|
||||
peersRow.style.display = 'flex';
|
||||
}
|
||||
|
||||
async function startVideo(){
|
||||
try {
|
||||
const pc = new RTCPeerConnection();
|
||||
@@ -192,7 +220,7 @@ setupPTT();
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
return render_template_string(PAGE)
|
||||
return render_template_string(PAGE, camera_name=CAMERA_NAME, peers=PEER_LINKS)
|
||||
|
||||
|
||||
@app.route('/healthz')
|
||||
|
||||
Reference in New Issue
Block a user