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.
| Field | Required | Notes |
|---|---|---|
| id | Yes | Lowercase, hyphenated, unique, permanent. |
| version | Yes | Semver. A pack is immutable after publication — a content change is a new version. |
| sha256 | Yes | Hash over the pack's own canonical content (everything except this field). The builder computes it; verify it locally before opening a PR. |
| profile_id | Yes | Which profile this pack is scored against. |
| visibility | Yes | open (identical data for everyone), community (may be free or commercial), or private (never leaves your machine, never submitted). |
| license | Yes | SPDX id (CC-BY-4.0, CC0-1.0, ...) or explicit terms. Required for open/community. |
| audio.count / total_duration_s / sample_rate_hz | No | Summary stats — filled in from your actual audio files. |
| audio.manifest_sha256 | No | Hash of manifest.jsonl (the file listing every clip + its transcript). |
| audio.source.url / fetch_instructions | No | Where 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 / params | No | Set 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_style | Yes | speech_style is spontaneous, read, or mixed. |
| metadata.dialect / age_group / microphone / background_noise / num_speakers / transcription_style / tags | No | The 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_instructionsprecise enough that anyone can reproduce your exact subset. For a new language, reach forscripts/fetch_fleurs_subset.pyfirst — 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.urlpoints at it,fetch_instructionssays exactly how to turn that URL into the filesmanifest.jsonldescribes. - 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
| Corpus | Coverage | License | Getting the audio |
|---|---|---|---|
| FLEURS | 102 languages, read speech | CC-BY-4.0 | Ungated — scripts/fetch_fleurs_subset.py handles any of its languages; set source.type: fleurs and goesb run auto-fetches it for anyone |
| VoxPopuli | 23 European languages, parliamentary speech | CC0-1.0 | Ungated, no script yet — write fetch_instructions by hand |
| LibriSpeech | English, read audiobooks | CC-BY-4.0 | Ungated — scripts/fetch_librispeech_subset.py; set source.type: librispeech for auto-fetch |
| Common Voice | 100+ languages, crowd-sourced | CC0-1.0 | Requires 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 GitHubvalidate_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.