# Streambert Download Manager: Handling M3U8 Streams with External Tools

> Learn how the Streambert download manager uses m3u8 external tools like vid-dl-cli-only and ffmpeg to efficiently download and merge HLS streams. Streambert simplifies complex video downloads.

- Repository: [true_lock/streambert](https://github.com/truelockmc/streambert)
- Tags: how-to-guide
- Published: 2026-05-21

---

**Streambert captures HLS playlist URLs through a custom Electron session, then delegates the actual downloading to an external binary (vid-dl-cli-only) that fetches fragments, merges them with ffmpeg, and reports progress back via IPC.**

Streambert is an Electron-based streaming application that automates the detection and downloading of HLS (HTTP Live Streaming) content. The **Streambert download manager** leverages a sophisticated IPC architecture to bridge the renderer process UI with a standalone command-line downloader, enabling robust handling of `.m3u8` playlists and external tool integration.

## Intercepting M3U8 URLs in the Player Session

When a video page loads, Streambert creates a custom `playerSession` with specific `webRequest` filters to intercept media resources before they reach the player.

In [`src/index.js`](https://github.com/truelockmc/streambert/blob/main/src/index.js), the main process registers `onBeforeRequest` listeners for both blocked hosts and media URLs:

```javascript
const MEDIA_URLS = [
  "*://*/*.m3u8*",
  "*://*/*.m3u8",
  "*://*/*.vtt*",
  "*://*/*.vtt",
];
playerSession.webRequest.onBeforeRequest(
  { urls: [...BLOCKED_HOSTS, ...MEDIA_URLS] },
  (details, callback) => {
    const { url } = details;
    if (url.includes('.m3u8')) {
      mw.webContents.send('m3u8-found', url);
    } else if (url.includes('.vtt')) {
      const { extractSubtitleLang } = require('./src/ipc/subtitles');
      mw.webContents.send('subtitle-found', {
        url,
        lang: extractSubtitleLang(url),
      });
    }
    callback({});
  },
);

```

- **`.m3u8` detection**: Triggers the `m3u8-found` event sent to the renderer, enabling the download UI.
- **`.vtt` detection**: Extracts language tags via `extractSubtitleLang()` from [`src/utils/subtitles.js`](https://github.com/truelockmc/streambert/blob/main/src/utils/subtitles.js) and emits `subtitle-found`.

This interception happens transparently to the user, allowing the app to present download options immediately when HLS content is detected.

## Validating the External Downloader Binary

Before executing any download, Streambert verifies that the user has configured a valid external tool. The `check-downloader` IPC handler in [`src/ipc/downloads.js`](https://github.com/truelockmc/streambert/blob/main/src/ipc/downloads.js) scans the specified directory for an executable binary:

```javascript
ipcMain.handle('check-downloader', (_, folderPath) => {
  if (!folderPath) return { exists: false, reason: 'no_folder' };
  const binary = entries.find(e => {
    if (e === '_internal' || e.startsWith('.')) return false;
    const stat = fs.statSync(path.join(folderPath, e));
    return process.platform === 'win32' ? e.endsWith('.exe')
         : !!(stat.mode & 0o111);
  });
  if (!binary) return { exists: false, reason: 'no_executable' };
  return { exists: true, binaryPath: path.join(folderPath, binary) };
});

```

The validation checks for platform-appropriate executables (`.exe` on Windows, files with execute permissions on Unix systems) and excludes internal folders like `_internal`.

## Spawning Downloads via IPC

The `run-download` handler orchestrates the actual download by spawning the external **vid-dl-cli-only** binary as a child process. Located in [`src/ipc/downloads.js`](https://github.com/truelockmc/streambert/blob/main/src/ipc/downloads.js), this handler manages process state, logging, and progress tracking:

```javascript
ipcMain.handle('run-download', (_, {
  binaryPath,
  m3u8Url,
  name,
  downloadPath,
}) => {
  const id = crypto.randomUUID();
  const logPath = path.join(os.tmpdir(), `streambert_dl_${id}.log`);

  const entry = { id, name, m3u8Url, downloadPath };
  downloads.push(entry);

  const args = [
    '--cli',
    m3u8Url,
    '-f', 'mp4 (with Audio)',
    '-r', 'best',
    '-b', '320',
    '-n', name,
    '-d', downloadPath,
  ];
  const proc = spawn(binaryPath, args, { 
    stdio: ['ignore','pipe','pipe'] 
  });
  activeProcs.set(id, proc);
  // ... progress handling
});

```

Each download receives a unique UUID, creates a temporary log file in `os.tmpdir()`, and stores process references in `activeProcs` for lifecycle management.

## Real-Time Progress Parsing

The download manager parses stdout from the external tool to provide granular progress updates. The parser in [`src/ipc/downloads.js`](https://github.com/truelockmc/streambert/blob/main/src/ipc/downloads.js) handles multiple output formats:

**Fragment-based HLS progress**:

```javascript
const fragMatch = trimmed.match(/\(frag\s+(\d+)\/(\d+)\)/);
if (fragMatch) {
  const current = parseInt(fragMatch[1]);
  const total = parseInt(fragMatch[2]);
  update.progress = Math.min(99,
    Math.round((current / total) * 100));
  update.lastMessage = `Fragment ${current} / ${total}`;
}

```

**Direct download statistics**:
When encountering `[download]` prefixed lines, the parser extracts percentage, total size, and download speed using regex patterns.

**FFmpeg integration**:
The parser also monitors for `Duration:` and `size=` lines during the final muxing phase to accurately track the merge progress.

All updates are emitted to the renderer via `download-progress` events containing the download ID, percentage, speed, and status messages.

## Post-Processing and Cleanup

Upon successful completion (exit code `0`), the download manager performs several cleanup operations:

1. **Log removal**: Deletes the temporary log file created in `os.tmpdir()`.
2. **File discovery**: If the binary doesn't explicitly report the output path, Streambert scans the download directory for the most recently modified video file matching known extensions.
3. **Safe renaming**: Sanitizes the media title and renames the file appropriately.
4. **Subtitle fetching**: Processes any subtitle URLs passed from the UI via `downloadSubtitleFile`, supporting HTTP(S) and local `file:` schemes, saving `.srt`, `.vtt`, or `.ass` files alongside the video.

If the external tool fails, the manager captures the last meaningful line from `stderr` and surfaces it to the user through the UI.

## Session Persistence and Safety

Streambert maintains download state across sessions through [`downloads.json`](https://github.com/truelockmc/streambert/blob/main/downloads.json), which persists completed entries while filtering out active or error states. The `killAllDownloads()` function ensures graceful shutdown by terminating child processes and removing temporary artifacts (`.part`, `.tmp` files) when the application exits or when the user triggers a `reset-app` command.

## Summary

- **Streambert download manager** uses a custom Electron `playerSession` to intercept `.m3u8` and `.vtt` URLs before they reach the video player.
- The `check-downloader` IPC handler validates the presence of the **vid-dl-cli-only** binary before allowing downloads to start.
- Downloads run in isolated child processes spawned via `spawn()` in [`src/ipc/downloads.js`](https://github.com/truelockmc/streambert/blob/main/src/ipc/downloads.js), with real-time stdout parsing for fragment-level progress updates.
- Post-processing includes automatic file discovery, safe renaming, subtitle downloads, and cleanup of temporary log files.
- State persistence and emergency cleanup ensure system hygiene even during unexpected shutdowns.

## Frequently Asked Questions

### How does Streambert detect M3U8 streams without browser extensions?

Streambert creates a custom Electron session (`playerSession`) with `webRequest.onBeforeRequest` filters targeting `*.m3u8*` and `*.vtt*` patterns. When the player loads a page, this API intercepts network requests before they complete, allowing the main process to emit `m3u8-found` events to the renderer without requiring external browser extensions or user scripts.

### What external tool does Streambert require for downloading?

Streambert requires the **vid-dl-cli-only** binary, a standalone command-line downloader capable of processing HLS playlists, downloading fragments, and merging them with ffmpeg. The application validates this binary through the `check-downloader` IPC handler, which checks for executable permissions (or `.exe` extension on Windows) in the user-specified directory.

### Can Streambert download subtitles separately from video?

Yes. When the player session detects `.vtt` URLs, it extracts language codes using `extractSubtitleLang()` from [`src/utils/subtitles.js`](https://github.com/truelockmc/streambert/blob/main/src/utils/subtitles.js) and emits `subtitle-found` events. During download initiation, users can pass subtitle arrays to the `run-download` handler, which fetches them via `downloadSubtitleFile` and saves them with appropriate extensions alongside the video file.

### How does the download manager handle partial failures or cancellations?

The download manager tracks active processes in an `activeProcs` Map using UUIDs. When a user cancels a download or the app shuts down, `killAllDownloads()` terminates the associated child process and removes temporary files including log files and partial downloads (`.part` files). Failed downloads capture the last stderr line for error reporting while preserving the attempt in the downloads store until explicitly cleared.