You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/operations-guide.md
+52Lines changed: 52 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -218,6 +218,21 @@ invocation, not the JSON file or an already-running service.
218
218
219
219
## Run unattended with systemd
220
220
221
+
For a portable Pi with a UVC camera, use a stable `/dev/v4l/by-id/` capture
222
+
path and validate its advertised formats before installing the service. Start
223
+
with 640x360 at 15 fps and 500 kbps, then tune against the actual uplink and
224
+
encoder load. Audio and transport overhead also need upload capacity.
225
+
If a selected `by-id` or `by-path` camera disappears, startup fails and the
226
+
service retries that selection. It does not substitute another camera.
227
+
228
+
The asyncio runtime services GLib events so media bus errors and queued decoder
229
+
fallbacks are delivered. Unhandled terminal media errors log the failing element and GStreamer
230
+
details, then exit with status 1. Shutdown has an independent eight-second
231
+
deadline in case a camera driver blocks during cleanup. Existing Jetson decoder
232
+
and display fallback handlers still run first. A direct CLI invocation exits;
233
+
automatic process recovery requires a supervisor such as the service below.
234
+
This detects reported media errors, not every possible silent camera freeze.
235
+
221
236
First prove the exact command interactively. Then use `tools/install_unattended.py` to create a validated receiver or sender unit whose user and working directory match the installed clone. Complete examples are in the [Pi Zero 2 W guide](pi-zero-2-w-unattended-webrtc.md#8-make-the-receiver-start-on-boot).
The helper uses `Restart=always`, a small `RestartSec`, unbuffered Python output, and `network-online.target`. It stores credentials in a restricted JSON config instead of the unit command. Running the installer again validates the replacement unit and restarts the existing service so new settings take effect.
233
248
249
+
Newly generated units retry every five seconds without a start-rate limit, so
250
+
a camera missing for several minutes does not permanently disable the service.
251
+
Reinstall an existing unit to apply this policy. Retries also continue for
252
+
configuration errors; inspect the journal and stop the service while correcting
253
+
them. Ordinary signaling reconnection continues inside the running application.
254
+
255
+
For USB camera/microphone recovery, select the camera under `/dev/v4l/by-id/`
256
+
and pass the microphone's `/dev/snd/by-id/` symlink to `--audio-device` (installer)
257
+
or `--alsa` (publisher). `/dev/v4l/by-path/` and `/dev/snd/by-path/` select a port
258
+
instead. The publisher resolves the sound-card symlink on every launch and new capture pipeline, opening
259
+
PCM device zero of that card even if its numeric card index has changed. A missing
260
+
explicit microphone is a startup error; the service retries instead of disabling
261
+
audio or selecting another microphone. Existing ALSA names remain supported;
262
+
use one when the required PCM device is not zero. Automatic audio discovery can
263
+
still disable audio when no mic is present, so use an explicit device unattended.
264
+
265
+
The WebRTC publisher monitors buffers from `v4l2src`, `alsasrc`, and `pulsesrc`.
266
+
If an active capture source produces no buffers for 30 seconds, it exits for
267
+
supervised recovery. `--capture-timeout SECONDS` adjusts the timeout (`0` disables
268
+
it). This also covers a source that never produces its first buffer. Paused/idle
269
+
pipelines do not expire, and quiet audio still counts as healthy capture when
270
+
buffers continue. Other camera backends retain their existing behavior. Capture
271
+
failure restarts the whole publisher, so removing the mic can also interrupt video.
272
+
This requires a service supervisor; the standalone script does not relaunch itself.
273
+
234
274
`--service-name` accepts up to 247 letters, digits, underscores, dots, hyphens,
235
275
or `@` characters before the generated `.service` suffix. It must not start with
236
276
`-` or `@`. Use a concrete instance such as `camera@front`, rather than `camera@`.
@@ -302,6 +342,18 @@ Increase one dimension at a time: resolution, then frame rate, then bitrate, the
302
342
303
343
## Stability checks
304
344
345
+
For mobile connections, peer negotiation is limited to 60 seconds by default.
346
+
A stalled attempt is released so the viewer's existing reconnect schedule can
347
+
request a fresh connection. Use `--peer-connect-timeout SECONDS` to adjust this
348
+
window (`0` disables it). Established connections are not expired by this timer.
349
+
350
+
To exercise relay-only operation, configure `--ice-transport-policy relay` and
351
+
`--turn-server` (or the equivalent configuration-file keys). Startup rejects
352
+
missing or invalid TURN configuration, and applying the relay policy must succeed
353
+
before ICE servers are configured. TURN credentials are hidden in setup logs.
354
+
Test both signaling reconnection and actual TURN transport outages: a working
355
+
WebSocket alone does not demonstrate that video has recovered.
356
+
305
357
Run at least a short sender-off/sender-on recovery test and a longer steady-state soak before unattended deployment:
0 commit comments