Part 1Marc de Batlle
0%
Part 1Marc de Batlle
All work02 / 11
Three

Donants de VeuA Common Voice instance rebuilt to collect non-normative Catalan speech for the BSC.

Chapter concepts
  1. 1Federació ACAPPS runs veus.acapps.org, a self-hosted Mozilla Common Voice, to collect Catalan speech from people with hearing loss, accents, dialects and learners for the Barcelona Supercomputing Center. I replaced the corpus, customised the frontend and wrote the anonymised export.
  2. 2Role: Freelance: sole developer. Status: Deployed.
  3. 3Stack: Docker Compose, MySQL 8, React, Fluent, Python, ffmpeg, Auth0.
  4. 4Key figure: 80 speakers in 8 groups, phase by phase.
02
PeriodJul to Sep 2026
RoleFreelance: sole developer
StatusDeployed

The problem

Automatic speech recognition and subtitling work badly for voices the training data never contained. The BSC wanted a corpus of non-normative Catalan speech (prelingual deafness, accents, dialects, learners) and Federació ACAPPS wanted its community to record it. The previous provider had cloned stock Common Voice onto the domain with zero customisation.

Three things had to change: the sentences people read, the site itself, and how the recordings reach the BSC. I was the sole developer, working locally; the federation's technician deploys to production and manages Auth0 users.

Infrastructure
ServerUbuntu 22.04, 6 vCPU, 11 GB, Plesk, Nginx in front of Apache
PlatformCommon Voice on Docker Compose: web, bundler, Redis, MySQL 8.0.31
AuthAuth0 single sign-on
ClipsMP3 48 kbps, 32 kHz, mono, per client and sentence

Corpus and phases

Mid-project the BSC sent ten files of 1,000 sentences organised as train and test groups: the first 146 common to everyone, the rest specific to each group, with 80 speakers in eight groups of ten and 400 to 720 sentences per speaker. Common Voice has one sentence pool per locale and serves it at random to whoever logs in. It has no idea of groups.

The fix uses two levers. One active list that gets rotated: phase 0 loads the common sentences, phase N loads group N's sentences and retires the previous pool by marking it used, inserting the new set and flushing Redis. And access control from outside: the federation blocks every Auth0 user except the ten speakers of the current group. The technician runs one command per phase from a written guide.

Common Voice has one sentence pool per locale and serves it at random to whoever logs in. It has no idea of groups.

Corpus and phases
The corpus, in sentences
1,000
sentences per file, ten files from the BSC
720
most sentences for one speaker
400
fewest sentences for one speaker
146
sentences common to every group
Exhibit 3-6
A phase change
  1. 1.Close the current phase
  2. 2.Retire the old pool (mark used)
  3. 3.Insert the group's sentences
  4. 4.Flush Redis
  5. 5.Federation unblocks the next ten speakers in Auth0
  6. 6.Recording resumes

Frontend

The client's nine-section redesign brief was implemented in Common Voice's React frontend and Fluent localisation files, then the web image was rebuilt. Listen, Write, Download and Answer tabs are gone; the home page is login and record. New copy, two calls to action, the project image, the waveform in ACAPPS brand colours, three cards for registered users, four project sections in place of the community block, funders limited to the BSC, Drets Socials and Política Lingüística, and a footer with the federation's details.

Anonymised export

Clips delivered to the BSC must carry an anonymous name, group_speaker_sentence such as train06_08_0452.wav, with the mapping between speakers, sentences and codes kept privately by ACAPPS for GDPR. Sentence ids in Common Voice are salted hashes, so the link between a database sentence and a BSC file is made on exact text, not by recomputing hashes.

The export is a Python tool with a TOML config. It reads clips, sentences and users from the MySQL container, assigns sequential codes, transcodes each MP3 to 16-bit PCM mono WAV at 32 kHz with ffmpeg, writes a manifest and the private mapping as separate files, and verifies every output against its source with sha256. Validated end to end locally with a real recording session: reset, phase 0, phase change, phase 1, export, nine clips correct by both resolution paths, integrity nine of nine.

Exhibit 3-9
Deliverables
ItemContent
Sentence swap toolOne run per phase, with a guide for the technician
FrontendNine-section redesign in React and Fluent, rebuilt image
Export toolPython, ffmpeg, sha256, manifest plus private mapping
DocumentationDeployment guide, client explanations in Catalan, project knowledge base
At a glance
ClientFederació ACAPPS
Third partyBarcelona Supercomputing Center
RoleSole developer, fixed price
PeriodAccepted Jul 2026, delivered Sep 2026
StackDocker Compose, MySQL 8, React, Fluent, Python, ffmpeg, Auth0
Continue
Previous chapterRenda 2025 CRM
Next chapterBuildLoud