# How to Detect and Handle Speaker Diarization Errors in Video Transcriptions

> Master speaker diarization errors in video transcriptions with the browser-use/video-use repository. Learn to implement try/except blocks and validate responses for robust pipelines.

- Repository: [Browser Use/video-use](https://github.com/browser-use/video-use)
- Tags: how-to-guide
- Published: 2026-07-08

---

**The `video-use` repository enables speaker diarization by default via ElevenLabs Scribe, but you must wrap API calls in `try/except` blocks, validate that the `"words"` key exists in the response payload, and handle potential `OSError` exceptions during file writes to build a resilient transcription pipeline.**

The `browser-use/video-use` repository automates video transcription using the ElevenLabs Scribe API, which identifies individual speakers through diarization. While this feature is enabled by default in the request payload, errors can surface at the API request level, during payload validation, or when writing results to disk. Understanding how to detect and handle speaker diarization errors ensures your transcription workflow remains robust even when the service returns invalid speaker counts or missing diarization data.

## Understanding Speaker Diarization Configuration

### Default Diarization Settings

In [`helpers/transcribe.py`](https://github.com/browser-use/video-use/blob/main/helpers/transcribe.py), the transcription request automatically includes `"diarize": "true"` in the JSON payload sent to ElevenLabs Scribe. This enables speaker identification without requiring additional configuration. You can optionally tune the diarization behavior using the `--num-speakers` CLI flag, which maps to the `num_speakers` parameter in the `call_scribe` function.

### The Three Stages of Potential Failure

Errors related to speaker diarization surface at three distinct stages:

1. **API request failures** – The ElevenLabs endpoint returns a non-200 HTTP status (e.g., 400 Bad Request for invalid speaker counts)
2. **Payload validation gaps** – The JSON response arrives successfully but lacks diarization-specific keys like `"words"` or `"segments"`
3. **File-system write errors** – The transcript directory is unwritable or the JSON serialization fails when persisting results

## Detecting API Request Errors

The `call_scribe` function in [`helpers/transcribe.py`](https://github.com/browser-use/video-use/blob/main/helpers/transcribe.py) validates HTTP responses by checking `resp.status_code != 200`. When the API rejects a request—such as when an invalid `num_speakers` value is supplied—the function raises a `RuntimeError` containing the full response body.

To detect these errors, wrap the API call in a `try/except RuntimeError` block:

```python
try:
    payload = call_scribe(audio_path, api_key, language, num_speakers)
except RuntimeError as e:
    # Log the full response for debugging

    print(f"Scribe API request failed: {e}", file=sys.stderr)
    # Optionally retry with a reduced or removed num_speakers value

```

## Validating Diarization Data in the Response

The current implementation does not validate the payload beyond HTTP status. You must add explicit checks to verify that diarization actually occurred. After `call_scribe` returns, inspect the payload for the `"words"` key, which contains the speaker-attributed segments.

If the service could not perform diarization on the audio (due to poor quality or incorrect speaker hints), the response will lack these fields. Detect this condition and raise a descriptive error:

```python
def call_scribe_with_checks(
    audio_path: Path,
    api_key: str,
    language: str | None = None,
    num_speakers: int | None = None,
) -> dict:
    """
    Calls the ElevenLabs Scribe API and validates that diarization data
    is present. Raises a clear exception if not.
    """
    try:
        payload = call_scribe(audio_path, api_key, language, num_speakers)
    except RuntimeError as e:
        raise RuntimeError(f"Scribe API request failed: {e}") from e

    # Validate diarization data exists

    if "words" not in payload:
        raise ValueError(
            "Diarization data missing in Scribe response – "
            "verify that the audio quality is sufficient and that "
            "the '--num-speakers' argument is correct."
        )
    
    return payload

```

## Handling File-System Write Errors

When writing the transcription JSON to disk, the code uses `out_path.write_text(json.dumps(payload, indent=2))`. Any `OSError` (such as permission denied or disk full) bubbles up uncaught. Wrap this operation to surface clear messages about the output path:

```python
try:
    out_path.write_text(json.dumps(payload, indent=2))
except OSError as e:
    raise OSError(f"Failed to write transcript to {out_path}: {e}")

```

## Implementing a Robust Error-Handling Workflow

Combine all three detection strategies into a single `transcribe_one` function that gracefully recovers from diarization failures. If the error relates to an invalid speaker count, retry without the hint; otherwise, surface the error to the user:

```python
def transcribe_one(
    video: Path,
    edit_dir: Path,
    api_key: str,
    language: str | None = None,
    num_speakers: int | None = None,
    verbose: bool = True,
) -> Path:
    # Setup logic...

    audio = extract_audio(video)  # hypothetical preprocessing

    
    try:
        payload = call_scribe_with_checks(audio, api_key, language, num_speakers)
    except (RuntimeError, ValueError) as exc:
        print(f"❌ transcription failed for {video.name}: {exc}", file=sys.stderr)
        
        # Retry without explicit speaker count if num_speakers caused the failure

        if isinstance(exc, RuntimeError) and "num_speakers" in str(exc):
            print("   retrying without explicit speaker count...", flush=True)
            payload = call_scribe_with_checks(audio, api_key, language, None)
        else:
            raise  # Re-raise if we cannot recover

    # Write with error handling

    out_path = edit_dir / f"{video.stem}.json"
    try:
        out_path.write_text(json.dumps(payload, indent=2))
    except OSError as e:
        raise OSError(f"Cannot write to {out_path}: {e}")
    
    return out_path

```

### CLI Usage Example

When running from the command line, the script automatically handles speaker count errors:

```bash
$ python helpers/transcribe.py my_video.mp4 --num-speakers 3

# If the speaker count is invalid, the script outputs:

#   ❌ transcription failed for my_video.mp4: RuntimeError(...)

#   retrying without explicit speaker count...

#   saved: my_video.json …

```

## Summary

- **Diarization is enabled by default** in `video-use` via `"diarize": "true"` in the ElevenLabs Scribe request payload.
- **Catch `RuntimeError`** to detect API request failures (invalid HTTP status codes) in `call_scribe`.
- **Validate the `"words"` key** exists in the response payload to confirm diarization succeeded; raise `ValueError` if missing.
- **Handle `OSError`** during file writes to prevent silent failures when saving JSON transcripts.
- **Implement retry logic** that removes the `num_speakers` hint when the API rejects the initial request, allowing fallback to automatic speaker detection.

## Frequently Asked Questions

### What causes speaker diarization to fail in video-use?

Diarization fails when the ElevenLabs Scribe service cannot identify distinct speakers in the audio, often due to poor audio quality, overlapping speech, or an incorrect `--num-speakers` hint that contradicts the actual speaker count. The API may return a successful HTTP response but omit the `"words"` and `"segments"` keys that contain speaker attribution data.

### How do I retry failed diarization requests automatically?

Wrap the `call_scribe` invocation in a `try/except` block that catches `RuntimeError` (for API failures) and `ValueError` (for missing diarization data). If the error message indicates an invalid speaker count, retry the call with `num_speakers=None` to let the service auto-detect speakers, as implemented in the `transcribe_one` function in [`helpers/transcribe.py`](https://github.com/browser-use/video-use/blob/main/helpers/transcribe.py).

### Which file contains the core transcription logic?

The core transcription logic resides in [`helpers/transcribe.py`](https://github.com/browser-use/video-use/blob/main/helpers/transcribe.py), which defines the `call_scribe` function for API communication, the CLI interface with `--num-speakers` support, and the `transcribe_one` workflow. Batch processing is handled by [`helpers/transcribe_batch.py`](https://github.com/browser-use/video-use/blob/main/helpers/transcribe_batch.py), which forwards parameters to the same underlying functions.

### Is speaker diarization enabled by default?

Yes. According to the source code in `browser-use/video-use`, the transcription request automatically includes `"diarize": "true"` in the JSON payload sent to ElevenLabs Scribe. You do not need to enable it manually, though you can adjust behavior using the optional `--num-speakers` CLI argument.