# Limitations of FadCam's Remote Streaming Capabilities: 9 Critical Constraints Explained

> Discover FadCam's remote streaming limitations including H.264 only, 2-sec buffer, 15-sec circular limit, and local Wi-Fi default. Learn the 9 critical constraints.

- Repository: [Faded/FadCam](https://github.com/anonfaded/FadCam)
- Tags: deep-dive
- Published: 2026-05-13

---

**FadCam's remote streaming only supports H.264 video, requires a minimum 2-second buffer before playback starts, maintains a hard 15-second circular buffer limit, and operates on local Wi-Fi networks by default.**

FadCam is a privacy-first Android dashcam application that delivers video via HTTP Live Streaming (HLS). The implementation in `anonfaded/FadCam` prioritizes lightweight operation and minimal resource consumption, which creates specific technical boundaries. Understanding these limitations of FadCam's remote streaming capabilities ensures developers configure appropriate expectations for real-time video delivery.

## Codec and Format Limitations

### H.264 Only: No HEVC/H.265 Browser Support

FadCam exclusively supports **H.264** video encoding for remote streaming. The codebase explicitly warns users when High Efficiency Video Coding (HEVC/H.265) is selected, as browsers cannot decode these streams.

In [`app/src/main/res/values/strings.xml`](https://github.com/anonfaded/FadCam/blob/main/app/src/main/res/values/strings.xml) at line 1971, the warning string `codec_hevc_incompatible_message` alerts users that "Live streaming via HLS requires H.264 codec." The streaming implementation never emits H.265 initialization segments, and the HLS playlist builder assumes H.264 formatting. Users must manually switch codecs before initiating a stream, or playback will fail to load in any browser.

### Single Track Output: No Independent Audio Streams

The HLS stream contains only a single video track with embedded audio. The `FragmentedMp4MuxerWrapper` class forwards video fragments exclusively, mixing audio directly into the fMP4 container without exposing separate tracks.

This architecture prevents clients from independently muting audio or selecting alternative audio tracks. All audio remains embedded within the video fragments, limiting flexibility for viewers who might want audio-only streams or subtitle overlays.

## Buffer and Timing Constraints

### Two-Second Minimum Buffer Requirement

Playback cannot begin until at least **two media fragments** are buffered. In [`RemoteStreamManager.java`](https://github.com/anonfaded/FadCam/blob/main/RemoteStreamManager.java) at lines 78-82, the `getStatusJson()` method checks if `bufferedCount < 2` and reports a "buffering" state to connected clients.

The playlist generator returns `null` when fewer than two fragments exist (lines 74-77). This creates an unavoidable startup delay of approximately 2 seconds, during which the stream URL is active but video remains unavailable. The constraint ensures clients receive complete initialization data before rendering begins.

### 15-Second Circular Buffer Limit

The streaming buffer maintains a **maximum of 15 one-second fragments** defined by `BUFFER_SIZE = 15` in [`RemoteStreamManager.java`](https://github.com/anonfaded/FadCam/blob/main/RemoteStreamManager.java) at lines 42-45. When the buffer reaches capacity, older fragments are automatically evicted to bound memory usage.

This limitation means viewers joining a live stream can only access approximately 15 seconds of recent video history. Older data is permanently discarded, making FadCam unsuitable for applications requiring extended DVR-style playback buffers or time-shifted viewing.

## Connectivity and Session Requirements

### Recording-Dependent Streaming Lifecycle

Remote streaming requires an **active recording session**. The `setStreamingEnabled(true)` method starts the HTTP server, but the stream only enters "ready" state when `isRecording()` returns true and an initialization segment exists, as implemented at lines 66-78 in [`RemoteStreamManager.java`](https://github.com/anonfaded/FadCam/blob/main/RemoteStreamManager.java).

If the user stops recording or the application enters the background, the stream immediately shuts down and the HLS URL ceases serving data. This coupling ensures streaming only occurs when privacy consent is explicitly granted through the recording interface, but prevents "camera-only" monitoring modes without file storage.

### Local Network Restriction Without Cloud Relay

By default, streaming operates **exclusively on local Wi-Fi subnets**. The HLS endpoint construction in [`WatchRemoteFragment.java`](https://github.com/anonfaded/FadCam/blob/main/WatchRemoteFragment.java) at line 116 uses the device's Wi-Fi IP address to build URLs like `http://192.168.x.x:8080/live.m3u8`.

Cloud relay functionality exists but remains disabled unless explicitly activated in settings. Without this relay, remote viewers attempting access from outside the local network will fail to connect, as the server binds to local interfaces only. This design prioritizes privacy by minimizing external exposure but limits flexibility for remote monitoring.

## Quality and Scalability Limitations

### Static Bitrate: No Adaptive Streaming

FadCam streams use a **single static quality configuration** stored in [`StreamQuality.java`](https://github.com/anonfaded/FadCam/blob/main/StreamQuality.java). The implementation lacks adaptive bitrate (ABR) algorithms or multi-resolution ladder support found in enterprise streaming platforms.

All connected clients receive identical bitrate and frame rate settings regardless of their available bandwidth or device capabilities. Network fluctuations may cause buffering or quality degradation without automatic adjustment, and mobile clients on constrained connections cannot request lower-quality variants.

### Device-Dependent Concurrent Client Limits

While `clientMetricsMap` tracks connected clients, the codebase imposes **no explicit hard limit** on concurrent viewers. Practical capacity depends entirely on the host device's CPU, RAM, and network stack performance.

In real-world usage, most Android devices support only a handful of simultaneous connections before experiencing thermal throttling or network congestion. This makes FadCam suitable for personal monitoring or small-scale sharing but unsuitable for broadcast scenarios requiring dozens of concurrent viewers.

### Staleness Detection and Frozen Streams

The server pushes status updates every 2 seconds, but `lastRelayUploadMs` only updates when segment uploads succeed in cloud mode (lines 1000-1005 in [`RemoteStreamManager.java`](https://github.com/anonfaded/FadCam/blob/main/RemoteStreamManager.java)). If the device freezes, stalls, or loses network connectivity, the playlist stops updating while the HTTP server remains responsive.

Viewers may encounter frozen video without immediate error messages, and the dashboard uses the stale timestamp to indicate stream death only after extended delays. This creates a "zombie stream" condition where connections appear active but deliver no new data.

## Practical Implementation Examples

### Enabling Remote Streaming in Your Application

```kotlin
// Initialize the stream manager singleton
val manager = RemoteStreamManager.getInstance()
manager.setContext(requireContext())
manager.setStreamingEnabled(true)
manager.setStreamingMode(RemoteStreamManager.StreamingMode.STREAM_AND_SAVE)

// Start the foreground service to maintain recording
startService(Intent(requireContext(), RemoteStreamService::class.java))

```

The singleton construction resides at lines 40-68, with server enabling logic at lines 60-73 in [`RemoteStreamManager.java`](https://github.com/anonfaded/FadCam/blob/main/RemoteStreamManager.java).

### Constructing the Local HLS Playback URL

```java
// Retrieve the device's Wi-Fi IP address
String localIp = RemoteStreamService.getLocalIpAddress();
String hlsUrl = "http://" + localIp + ":8080/live.m3u8";

```

This URL construction pattern appears in [`WatchRemoteFragment.java`](https://github.com/anonfaded/FadCam/blob/main/WatchRemoteFragment.java) at line 116, defaulting to port 8080.

### Checking Stream Health via the Status Endpoint

```bash
curl http://<device_ip>:8080/status

```

A healthy stream returns JSON similar to:

```json
{
  "streaming": true,
  "state": "ready",
  "message": "Stream is ready for playback.",
  "fragmentsBuffered": 8,
  "hasInitSegment": true
}

```

The `getStatusJson()` method at lines 1717-1760 caches responses for 1 second to prevent excessive polling overhead.

### Handling Codec Warnings in the UI

When users select HEVC recording, the application displays the warning defined in [`strings.xml`](https://github.com/anonfaded/FadCam/blob/main/strings.xml):

```xml
<string name="codec_hevc_incompatible_message">
    📡 Live streaming via HLS requires H.264 codec.
    Please switch codecs to enable remote viewing.
</string>

```

## Summary

- **H.264 required**: HEVC/H.265 streams are incompatible with browser-based HLS playback.
- **2-second startup delay**: Streams require two buffered fragments before the playlist becomes available.
- **15-second history limit**: The circular buffer automatically discards fragments older than 15 seconds.
- **Recording dependency**: Streaming stops when recording stops or the app backgrounds.
- **Local network default**: Internet access requires explicit cloud relay configuration.
- **Static quality**: No adaptive bitrate or resolution selection for varying network conditions.
- **Limited concurrency**: Practical viewer counts depend on device hardware capabilities.
- **No separate audio tracks**: Audio is embedded in video fragments only.

## Frequently Asked Questions

### Why does the stream buffer for 2 seconds before playing?

FadCam requires **at least two one-second media fragments** before generating the HLS playlist. According to the source code in [`RemoteStreamManager.java`](https://github.com/anonfaded/FadCam/blob/main/RemoteStreamManager.java) at lines 74-82, the `getStatusJson()` method checks `bufferedCount < 2` and returns a buffering state until sufficient data exists. This ensures clients receive complete initialization segments before attempting playback.

### Can I stream FadCam video over the internet without a cloud relay?

No, **local Wi-Fi networks are required by default**. The HLS endpoint in [`WatchRemoteFragment.java`](https://github.com/anonfaded/FadCam/blob/main/WatchRemoteFragment.java) (line 116) constructs URLs using the device's local Wi-Fi IP address. Without enabling the optional cloud relay in settings, the HTTP server only binds to local network interfaces, blocking external internet access while maintaining privacy.

### Why does my stream stop when I close the application or stop recording?

FadCam's streaming architecture ties the HTTP server lifecycle to the **active recording session**. The `isRecording()` check at lines 66-78 in [`RemoteStreamManager.java`](https://github.com/anonfaded/FadCam/blob/main/RemoteStreamManager.java) controls the "ready" state, and stopping recording triggers immediate server shutdown. This design ensures streaming only occurs during explicit recording sessions with user consent.

### Does FadCam support 4K or high-bitrate streaming?

FadCam supports high resolutions only within the constraints of **H.264 encoding and static bitrate configuration**. The [`StreamQuality.java`](https://github.com/anonfaded/FadCam/blob/main/StreamQuality.java) file stores a single quality preset without adaptive variants. While 4K H.264 streams are technically possible, the 15-second buffer limit and lack of bandwidth adaptation may cause playback issues on constrained networks.