GOESB

Create a pack

A pack is metadata + a hash-verified manifest describing a dataset — never the audio itself. Prefer the in-browser builder to hash your audio folder and generate pack.yaml + manifest.jsonl automatically — this page is the field reference and, most importantly, the answer to “where does the audio actually come from?”

Fields

Validated against schemas/benchmark-pack.schema.json in the runner repo.

FieldRequiredNotes
idYesLowercase, hyphenated, unique, permanent.
versionYesSemver. A pack is immutable after publication — a content change is a new version.
sha256YesHash over the pack's own canonical content (everything except this field). The builder computes it; verify it locally before opening a PR.
profile_idYesWhich profile this pack is scored against.
visibilityYesopen (identical data for everyone), community (may be free or commercial), or private (never leaves your machine, never submitted).
licenseYesSPDX id (CC-BY-4.0, CC0-1.0, ...) or explicit terms. Required for open/community.
audio.count / total_duration_s / sample_rate_hzNoSummary stats — filled in from your actual audio files.
audio.manifest_sha256NoHash of manifest.jsonl (the file listing every clip + its transcript).
audio.source.url / fetch_instructionsNoWhere a consumer gets the audio — see “Sourcing audio” below. Required in spirit for open/community packs, even though the schema doesn't enforce it.
audio.source.type / paramsNoSet type to fleurs or librispeech (with the matching params) and goesb run auto-fetches the audio for anyone — no fetch_instructions needed by hand. Omit (or use manual) for anything else.
metadata.language / recording_environment / speech_styleYesspeech_style is spontaneous, read, or mixed.
metadata.dialect / age_group / microphone / background_noise / num_speakers / transcription_style / tagsNoThe more of these you fill in, the more useful the pack is for filtering.

Sourcing audio

This is the part that trips people up, so it's worth being explicit: GOESB never hosts audio. A pack is text — metadata, transcripts, hashes — and it stays that way even after you've added your own dataset. Where the actual audio bytes live depends on which kind of pack you're contributing:

  • Using an existing open corpus (FLEURS, VoxPopuli, LibriSpeech, Common Voice). The corpus is already hosted by its publisher — your job is to write fetch_instructions precise enough that anyone can reproduce your exact subset. For a new language, reach for scripts/fetch_fleurs_subset.py first — it's generic across all 102 FLEURS languages and, like LibriSpeech, needs no account or consent screen. Common Voice covers more languages still, but its own download flow can't be scripted the same way — worth knowing before you commit to it for a new pack.
  • Contributing your own recordings. You host them — your own object storage bucket, a Hugging Face Hub dataset, Zenodo, an institutional server, anything with a stable URL and a license you actually hold the rights to grant. audio.source.url points at it, fetch_instructions says exactly how to turn that URL into the filesmanifest.jsonl describes.
  • Private packs. No sourcing needed — audio stays on your own machine and is never submitted at all; only metadata and results are.

Known open corpora

CorpusCoverageLicenseGetting the audio
FLEURS102 languages, read speechCC-BY-4.0Ungated — scripts/fetch_fleurs_subset.py handles any of its languages; set source.type: fleurs and goesb run auto-fetches it for anyone
VoxPopuli23 European languages, parliamentary speechCC0-1.0Ungated, no script yet — write fetch_instructions by hand
LibriSpeechEnglish, read audiobooksCC-BY-4.0Ungated — scripts/fetch_librispeech_subset.py; set source.type: librispeech for auto-fetch
Common Voice100+ languages, crowd-sourcedCC0-1.0Requires visiting their site and accepting terms per language — can't be scripted

Worked fetch_instructions examples

A new language pack, using FLEURS — create pack.yaml first (id, profile_id, license, visibility, metadata), then let the script fill in the audio fields:

audio:
  source:
    type: fleurs
    params: { language: nl_nl, split: dev }
    url: "https://huggingface.co/datasets/google/fleurs"
    fetch_instructions: >
      Run `python scripts/fetch_fleurs_subset.py --language nl_nl
      --pack-dir packs/<this-pack>` from the repo root. It downloads
      dev.tsv, streams dev.tar.gz for just those clips, writes
      manifest.jsonl, and fills in this file's audio.* fields + sha256.
      Verify against audio.manifest_sha256 before running a benchmark.

The English/LibriSpeech pattern — one script per corpus, since LibriSpeech predates the generic FLEURS one:

audio:
  source:
    type: librispeech
    params: { speaker: "1272", chapter: "128104", split: dev-clean }
    url: "https://www.openslr.org/resources/12/dev-clean.tar.gz"
    fetch_instructions: >
      Run `python scripts/fetch_librispeech_subset.py --speaker 1272
      --chapter 128104` from the repo root. It streams dev-clean.tar.gz,
      extracts only that speaker/chapter, writes manifest.jsonl, and saves
      the FLAC files to packs/<this-pack>/audio/. Verify against
      audio.manifest_sha256 before running a benchmark.

source.type/params is what lets goesb run fetch the audio itself instead of a contributor running the script by hand for every consumer — set it whenever the pack's corpus is one of the built-in providers (currently fleurs, librispeech). fetch_instructions stays as the human-readable fallback either way — for anything else, it's the only path. Good fetch_instructions are a runnable recipe, not prose describing where you personally found the files.

Worked example: a full pack.yaml

id: librispeech-en-batch
version: 1.0.0
sha256: d51fad1961713996f72a43bcd6fa91d5b08b17665152ecc66f47595c0c36c67c
profile_id: whisper-medium-en-batch
visibility: open
license: CC-BY-4.0
audio:
  count: 15
  total_duration_s: 145.195
  sample_rate_hz: 16000
  manifest_sha256: 6b9cdcf81a565496b7d4ef4881b035d98593eb941e61d87780591f0aba5852d9
  source:
    type: librispeech
    params: { speaker: "1272", chapter: "128104", split: dev-clean }
    fetch_instructions: >
      python scripts/fetch_librispeech_subset.py --speaker 1272 --chapter 128104
metadata:
  language: en-US
  dialect: general-american
  age_group: mixed
  recording_environment: quiet
  microphone: consumer usb
  sample_rate_hz: 16000
  background_noise: none
  num_speakers: 100
  speech_style: read
  transcription_style: verbatim
  tags: [librispeech, english, clean]

manifest.jsonl sits next to it, one line per clip:

{"duration_s": 5.855, "reference_text": "MISTER QUILTER IS THE APOSTLE OF THE MIDDLE CLASSES...", "relative_path": "1272-128104-0000.flac", "utterance_id": "1272-128104-0000"}

Submit it

A pack is at least two files (pack.yaml, manifest.jsonl), so the command line is easier than the GitHub web editor here. Clone the repo (see the how-to guide), then:

mkdir -p packs/<your-id>
# add pack.yaml and manifest.jsonl to packs/<your-id>/

python scripts/validate_assets.py   # schema AND hash check — must pass clean

git checkout -b add-<your-id>-pack
git add packs/<your-id>/pack.yaml packs/<your-id>/manifest.jsonl
git commit -m "Add <your-id> pack"
git push -u origin add-<your-id>-pack
# then open a PR from your fork on GitHub

validate_assets.py recomputes every pack's hash and fails on mismatch — the same check CI runs, so if it passes locally it won't fail there either. A reviewer then checks the same criteria as any contribution — security, neutrality, correctness, reproducibility — see the Contribute page.