CorentinJ/Real-Time-Voice-Cloning · error · Exception

Can't create RandomCycler from an empty collection

Error message

Can't create RandomCycler from an empty collection

What it means

Raised by RandomCycler.__init__ (encoder/data_objects/random_cycler.py) when the source sequence is empty. RandomCycler guarantees each item is returned between m//n and ((m-1)//n)+1 times; with n == 0 those guarantees are undefined and sample() would loop forever, so construction is rejected. The class is instantiated from exactly two places: SpeakerVerificationDataset (speaker_verification_dataset.py:18, with the list of speaker directories) and Speaker._load_utterances (speaker.py:18, with utterances parsed from the speaker's _sources.txt).

Source

Thrown at encoder/data_objects/random_cycler.py:14

import random

class RandomCycler:
    """
    Creates an internal copy of a sequence and allows access to its items in a constrained random 
    order. For a source sequence of n items and one or several consecutive queries of a total 
    of m items, the following guarantees hold (one implies the other):
        - Each item will be returned between m // n and ((m - 1) // n) + 1 times.
        - Between two appearances of the same item, there may be at most 2 * (n - 1) other items.
    """
    
    def __init__(self, source):
        if len(source) == 0:
            raise Exception("Can't create RandomCycler from an empty collection")
        self.all_items = list(source)
        self.next_items = []
    
    def sample(self, count: int):
        shuffle = lambda l: random.sample(l, len(l))
        
        out = []
        while count > 0:
            if count >= len(self.all_items):
                out.extend(shuffle(list(self.all_items)))
                count -= len(self.all_items)
                continue
            n = min(count, len(self.next_items))
            out.extend(self.next_items[:n])
            count -= n
            self.next_items = self.next_items[n:]
            if len(self.next_items) == 0:
                self.next_items = shuffle(list(self.all_items))

View on GitHub (pinned to 890f3a0318)

Solutions

  1. Re-run preprocessing for the offending speaker: python encoder_preprocess.py -d <dataset> -i <datasets_root> (drop --skip_existing so empty outputs are regenerated).
  2. Inspect each speaker dir: find <datasets_root>/SV2TTS/encoder -name _sources.txt -empty to locate the culprit, then delete or re-preprocess that directory.
  3. If the speaker's source audio is genuinely unusable (all silence / <0.1s), remove that speaker directory before training.
  4. As a library user, validate that a speaker dir has at least one *.npy frames file before constructing Speaker/RandomCycler.

Example fix

# before (fails when _sources.txt is empty)
speaker = Speaker(speaker_dir)
utterances, frames, ranges = speaker.random_partial(count, n_frames)

# after (guard before use)
speaker = Speaker(speaker_dir)
speaker._load_utterances()
assert speaker.utterances, f"{speaker.name} has no preprocessed utterances"
utterances, frames, ranges = speaker.random_partial(count, n_frames)
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def valid_speaker_dir(speaker_dir: Path) -> bool:
    src = speaker_dir / "_sources.txt"
    if not src.is_file():
        return False
    return any(line.strip() for line in src.read_text().splitlines())

Try / catch

try:
    dataset = SpeakerVerificationDataset(root)
except Exception as e:
    if "RandomCycler" in str(e):
        bad = [d for d in root.glob("*") if d.is_dir() and not valid_speaker_dir(d)]
        raise RuntimeError(f"Empty speaker dirs: {bad}") from e
    raise

Prevention

When it happens

Trigger: The speaker.py path: a preprocessed speaker directory whose _sources.txt exists but is empty (encoder_preprocess.py wrote no utterances, e.g. all wav files failed VAD trimming), so `self.utterances` is [] and RandomCycler([]) raises during random_partial(). The dataset path requires zero speaker dirs, but that case is usually intercepted first by the 'No speakers found' exception in speaker_verification_dataset.py:15.

Common situations: Running encoder_train.py against a datasets_root where one speaker's audio was entirely too short/silent for preprocessing, leaving an empty _sources.txt; interrupted encoder_preprocess.py runs; a manually created speaker directory with no preprocessing output.

Related errors


AI-assisted analysis of CorentinJ/Real-Time-Voice-Cloning@890f3a0318 (2026-08-15). Data as JSON: /api/errors/99e88ac2f126306d. Report an issue: GitHub.