# Diagnosing "/hls.m3u8 times out"

This proxy was updated (v1.1.0) to fix two real bugs found during a code
review that could cause exactly this symptom:

1. **`session.error` was never set** when `ffprobe` failed/timed out, so
   `/hls.m3u8` never returned the 502 it was supposed to - it just silently
   fell through and returned an empty/broken playlist (no segments, no
   `#EXT-X-ENDLIST`), which looks like an indefinite hang to a player.
2. **The ffmpeg remux process itself had zero timeout protection.** Only
   `ffprobe` had a kill-timer. If ffmpeg connected fine for probing but
   then stalled mid-remux (network drop, blocked sustained transfer,
   dead connection, etc.), the request would hang indefinitely with no
   way to ever return a response.

Both are now fixed with Node-level watchdog timers (reliable regardless
of ffmpeg version/build - see "Why not ffmpeg's own -timeout flag" below).
As of this version, `/hls.m3u8` will **always** return within
`PLAYLIST_WAIT_MS` (default 20s) with either a working playlist or a
clear JSON error explaining what happened.

If you're still seeing a hang/timeout after updating, work through this
list **on your actual cPanel server** (I cannot reach your specific
domain or an arbitrary external test URL from where I run - my
environment's network is restricted to prevent arbitrary internet
access, so all of this needs to be run by you via cPanel Terminal / SSH).

## 1. Confirm the new code is actually deployed and restarted

- Re-upload `app.js`, `lib/session.js`, `lib/ffprobe.js`, `lib/playlist.js`.
- In **Setup Node.js App**, click **Restart** (file changes are not
  auto-reloaded by Passenger).
- Check the app's log (linked from Setup Node.js App) for the startup
  line `stremio-remux-proxy listening on :XXXX`.

## 2. Reproduce directly with ffprobe/ffmpeg via SSH/Terminal - bypass Node entirely

This isolates whether the problem is ffmpeg/network related, or
something in the Node layer:

```bash
# Does ffprobe even see the file?
time /path/to/ffprobe -v error -print_format json \
  -show_entries format=duration:stream=index,codec_type,codec_name \
  "https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/1080/Big_Buck_Bunny_1080_10s_30MB.mp4"
```

- **Hangs or takes a long time?** -> network/TLS issue from this server
  (see #3, #4 below).
- **Fails immediately with a certificate error?** -> see #4 (CA certs).
- **Returns JSON quickly** -> ffprobe/network is fine; the issue is more
  likely Passenger/Apache's own timeout (see #5) or the app not actually
  running the updated code.

## 3. Check outbound network access from the CageFS/LVE jail

Shared hosting sometimes restricts outbound connections (only allowing
specific ports, or blocking certain destinations entirely):

```bash
curl -v --max-time 15 -I "https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/1080/Big_Buck_Bunny_1080_10s_30MB.mp4"
```

If this itself hangs or fails, it's a server/network-level restriction,
not something fixable in the Node app - contact your host about outbound
HTTPS access for your account/LVE.

## 4. Check TLS/CA certificate trust

A very common shared-hosting gotcha: the CageFS-jailed environment can
have an outdated or missing CA bundle, causing HTTPS connections to hang
or fail differently than a normal system `curl`:

```bash
curl -v "https://test-videos.co.uk" 2>&1 | grep -i -E "certificate|SSL|TLS"
openssl s_client -connect test-videos.co.uk:443 -servername test-videos.co.uk </dev/null 2>&1 | grep -i "verify"
```

If you see certificate verification errors, ffmpeg will typically fail
fast (not hang) - but it's worth ruling out since ffmpeg's TLS error
handling varies by build.

## 5. Check Apache/Passenger's own request timeout

Even with our app now failing fast (max ~20s), if Apache's `Timeout`
directive or Passenger's request queue timeout is set lower than that,
**Apache itself** may return a 504/502 to the client before our app gets
a chance to respond - which looks identical from the browser/player's
perspective. Ask your host, or check (if you have access):

```bash
grep -ri timeout /etc/apache2/conf.d/*.conf /usr/local/apache/conf/*.conf 2>/dev/null
```

If this is the constraint, you can lower `PLAYLIST_WAIT_MS` (env var) to
comfortably fit under Apache's own timeout, so our app always answers
first with a clear error rather than letting Apache's generic timeout
page win the race.

## 6. Increase log verbosity temporarily

Set `FFMPEG_STALL_TIMEOUT_MS=8000` (or lower) via the Node app's
environment variables and restart, then hit `/hls.m3u8` again - a faster
timeout gets you a diagnostic answer sooner while you iterate.

## Why not just use ffmpeg's own `-timeout`/`-rw_timeout` flag?

Verified directly against this project's ffmpeg/ffprobe build: neither
`http`, `https`, nor `tls` protocol contexts expose a timeout AVOption at
all (only the raw `tcp` layer does, via `-timeout`, and whether/how it's
forwarded through TLS/HTTP wrapping isn't guaranteed across ffmpeg
versions/builds). Relying on it risked either silently doing nothing, or
in some cases a hard "Option not found" failure. This proxy now enforces
all timeouts at the Node.js process level (`SIGKILL` after N ms of no
progress), which works identically regardless of ffmpeg version, build,
or protocol - zero guessing required.
