File size: 4,422 Bytes
6eed659
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#!/usr/bin/env python3
"""FLEURS lingala (ln_cd) + shona (sn_zw) : de la parole EXTERNE, avec des
LOCUTEURS NOUVEAUX.

Hypothese : on a mesure TROIS FOIS que reentrainer sur WAXAL degrade le test
(pseudo-labels lin -0.0062, tour 2 sna -0.00018, SWA -0.0010) alors que la
validation s'ameliorait a chaque fois. Mecanisme identifie : l'ajout de donnees
des MEMES locuteurs colle le modele a eux, or le test est fait de locuteurs
INEDITS. Corollaire jamais teste : des donnees EXTERNES apportent des locuteurs
nouveaux, donc l'effet inverse -- plus de diversite locuteur, meilleure
generalisation.

Conformite : FLEURS (google/fleurs) est public, non restreint, CC-BY-4.0, et
l'organisateur autorise explicitement les corpus externes publics et licencies
s'ils sont DECLARES (fil Zindi 33616). A ajouter a COMPLIANCE.md s'il finit dans
le systeme soumis.

Reserve connue : FLEURS est de la parole LUE (phrases Wikipedia), alors que WAXAL
est de la description d'images spontanee. Decalage de domaine reel -- c'est
precisement ce que la soumission tranchera.
"""
import glob, os, tarfile, csv as _csv, json, sys

os.environ.setdefault("HF_HUB_DISABLE_XET", "1")
os.environ.setdefault("HF_HOME", "/scratch/hf_home")
from huggingface_hub import snapshot_download

tok = open(os.path.expanduser("~/.cache/huggingface/token")).read().strip()
DEST = "/scratch/fleurs"
LANGS = {"ln_cd": "lin", "sn_zw": "sna"}

pats = []
for lg in LANGS:
    pats += ["data/%s/audio/train.tar.gz" % lg, "data/%s/train.tsv" % lg,
             "data/%s/audio/dev.tar.gz" % lg, "data/%s/dev.tsv" % lg]
print("telechargement FLEURS %s ..." % ", ".join(LANGS), flush=True)
snapshot_download("google/fleurs", repo_type="dataset", allow_patterns=pats,
                  local_dir=DEST, max_workers=8, token=tok)
got = glob.glob(DEST + "/data/*/audio/*.tar.gz")
print("archives : %d (%.2f Go)" % (len(got), sum(os.path.getsize(f) for f in got) / 1e9), flush=True)

import soundfile as sf
import numpy as np

OUTD = "/scratch/prep/audio/fleurs"
os.makedirs(OUTD, exist_ok=True)
M = "/scratch/prep/manifests"
os.makedirs(M, exist_ok=True)

for lg, ourlang in LANGS.items():
    rows = []
    for split in ("train", "dev"):
        tsv = "%s/data/%s/%s.tsv" % (DEST, lg, split)
        tgz = "%s/data/%s/audio/%s.tar.gz" % (DEST, lg, split)
        if not (os.path.exists(tsv) and os.path.exists(tgz)):
            print("  %s/%s absent, saute" % (lg, split), flush=True); continue
        meta = {}
        with open(tsv, encoding="utf-8") as f:
            for line in f:
                p = line.rstrip("\n").split("\t")
                if len(p) >= 4:
                    meta[p[1]] = p[3]          # nom de fichier -> transcription normalisee
        d = os.path.join(OUTD, lg, split)
        os.makedirs(d, exist_ok=True)
        with tarfile.open(tgz) as t:
            t.extractall(d)
        wavs = glob.glob(d + "/**/*.wav", recursive=True)
        n_ok = 0
        for w in wavs:
            b = os.path.basename(w)
            txt = meta.get(b)
            if not txt or not txt.strip():
                continue
            try:
                info = sf.info(w)
            except Exception:
                continue
            dur = info.frames / float(info.samplerate)
            if not (1.5 <= dur <= 30.0):
                continue
            if info.samplerate != 16000:
                x, sr = sf.read(w, dtype="float32")
                if x.ndim > 1:
                    x = x.mean(1)
                idx = np.linspace(0, len(x) - 1, int(len(x) * 16000 / sr))
                x = np.interp(idx, np.arange(len(x)), x).astype("float32")
                sf.write(w, x, 16000)
                dur = len(x) / 16000.0
            rows.append({"id": "fleurs_%s_%s" % (lg, b.replace(".wav", "")),
                         "audio": w, "duration": dur, "text": txt.strip(),
                         "speaker": "fleurs_%s_unk" % lg, "source": "fleurs_%s" % lg,
                         "lang": ourlang})
            n_ok += 1
        print("  %s/%s : %d clips retenus sur %d" % (lg, split, n_ok, len(wavs)), flush=True)
    out = "%s/fleurs_%s.jsonl" % (M, ourlang)
    with open(out, "w", encoding="utf-8") as f:
        for r in rows:
            f.write(json.dumps(r, ensure_ascii=False) + "\n")
    print("  -> %s : %d clips / %.1f h" % (out, len(rows), sum(r["duration"] for r in rows) / 3600), flush=True)

print("FLEURS_DONE", flush=True)