Orosz nyílt beszéd szöveggé

Különböző audioforrásokból származó beszédminták gyűjteménye. Az adathalmaz rövid, orosz nyelvű hangklipeket tartalmaz.

Megjegyzés:

A Microsoft az Azure Open Datasets szolgáltatást "adott módon" biztosítja. A Microsoft nem vállal kifejezett vagy vélelmezett garanciát vagy feltételeket az adathalmazok Ön általi használatára vonatkozóan. A microsoft a helyi jogszabályok által megengedett mértékben kizár minden felelősséget az adathalmazok használatából eredő károkért vagy veszteségekért, beleértve a közvetlen, következményi, különleges, közvetett, incidenses vagy büntető jellegű károkat is.

Az adatkészletet a Microsoft forrásadataihoz tartozó eredeti feltételek szerint szolgáltatjuk. A készlet tartalmazhat Microsofttól származó adatokat.

Ez az orosz szövegfelolvasási (STT) adatkészlet a következőket tartalmazza:

  • ~16 millió kimondott szöveg
  • ~20 000 óra
  • 2,3 TB (.wav formátumban tömörítetlen az int16-ban), 356G opusban
  • Az összes fájl opusra lett átalakítva, kivéve az érvényesítési adatkészleteket

Az adatkészlet fő célja a beszédátírási modellek betanítása.

Az adatkészlet összetétele

Az adathalmaz mérete .wav fájlok esetén van megadva.

ADATKÉSZLET KIMONDOTT SZÖVEGEK ÓRA GB Standard kiadás CS/CHARS MEGJEGYZÉST MEGJEGYZÉS MINŐSÉG/NOI Standard kiadás
radio_v4 (*) 7 603 192 10,430 1,195 5s / 68 Választógomb Igazítás 95% / tiszta
public_speech (*) 1,700,060 2,709 301 6s / 79 Nyilvános beszéd Igazítás 95% / tiszta
audiobook_2 1,149,404 1,511 162 5s / 56 Könyvek Igazítás 95% / tiszta
radio_2 651,645 1,439 154 8s / 110 Választógomb Igazítás 95% / tiszta
public_youtube1120 1,410,979 1,104 237 3s / 34 YouTube Feliratok 95% / ~tiszta
public_youtube700 759,483 701 75 3s / 43 YouTube Feliratok 95% / ~tiszta
tts_russian_addresses 1,741,838 754 81 2s / 20 Címek TTS 4-hangok 100% / tiszta
asr_public_phone_calls_2 603,797 601 66 4s / 37 Telefonbeszélgetések ASR 70% / zajos
public_youtube1120_hq 369,245 291 31 3s / 37 YouTube HQ Feliratok 95% / ~tiszta
asr_public_phone_calls_1 233,868 211 23 3s / 29 Telefonbeszélgetések ASR 70% / zajos
radio_v4_add (*) 92,679 157 18 6s / 80 Választógomb Igazítás 95% / tiszta
asr_public_stories_2 78,186 78 9 4s / 43 Könyvek ASR 80% / tiszta
asr_public_stories_1 46,142 38 4 3s / 30 Könyvek ASR 80% / tiszta
public_series_1 20,243 17 2 3s / 38 YouTube Feliratok 95% / ~tiszta
asr_calls_2_val 12,950 7,7 2 2s / 34 Telefonbeszélgetések Manuális jegyzetek 99% / tiszta
public_lecture_1 6,803 6 1 3s / 47 Előadások Feliratok 95% / tiszta
buriy_audiobooks_2_val 7,850 4,9 1 2s / 31 Könyvek Manuális jegyzetek 99% / tiszta
public_youtube700_val 7,311 4,5 1 2s / 35 YouTube Manuális jegyzetek 99% / tiszta

(*) A txt-fájlokban csak egy mintaadat található.

Jegyzetkészítési módszertan

Az adathalmaz nyílt forrásokból áll össze. A hosszú szekvenciákat hangdarabokra osztottuk fel a hangtevékenység észlelésének és az igazítás használatával. Egyes hangtípusokat a rendszer automatikusan jegyzetel, és heurisztika használatával statisztikailag ellenőrzi.

Adatkötetek és frissítés gyakorisága

Az adathalmaz teljes mérete 350 GB. A nyilvánosan megosztott címkékkel rendelkező adathalmaz teljes mérete 130 GB.

Maga az adathalmaz valószínűleg nem frissül a visszamenőleges kompatibilitás érdekében. Kövesse az eredeti adattárat a teljesítménytesztekhez, és zárja ki a fájlokat.

Elképzelhető, hogy a jövőben új tartományokat és nyelveket is felveszünk majd.

Hangnormalizáció

Minden fájl normalizálva van a egyszerűbb és gyorsabb futtatókörnyezeti bővítés érdekében. A feldolgozás a következő:

  • Szükség szerint monóra konvertálva;
  • Szükség esetén 16 kHz-es mintavételi sebességre konvertálva;
  • 16 bites egész számokban tárolva;
  • OPUS-ra konvertálva;

Lemezes DB-módszer

Minden hangfájl (wav, bináris) kivonatolva van. A kivonat egy mappahierarchiát hoz létre az optimálisabb fs művelet érdekében.

target_format = 'wav'
wavb = wav.tobytes()

f_hash = hashlib.sha1(wavb).hexdigest()

store_path = Path(root_folder,
                  f_hash[0],
                  f_hash[1:3],
                  f_hash[3:15] + '.' + target_format)

Letöltések

Az adatkészlet két formában érhető el:

  • Az Azure Blob Storage-on és/vagy közvetlen hivatkozásokon keresztül elérhető archívumok;
  • Az Azure Blob Storage-on keresztül elérhető eredeti fájlok; Minden a következő helyen van tárolva: "https://azureopendatastorage.blob.core.windows.net/openstt/"

Mappaszerkezet:

└── ru_open_stt_opus                                            <= archived folders
│   │
│   ├── archives
│   │    ├── asr_calls_2_val.tar.gz                             <= tar.gz archives with opus and wav files
│   │    │   ...                                                <= see the below table for enumeration
│   │    └── tts_russian_addresses_rhvoice_4voices.tar.gz
│   │
│   └── manifests
│        ├── asr_calls_2_val.csv                                <= csv files with wav_path, text_path, duration (see notebooks)
│        │   ...
│        └── tts_russian_addresses_rhvoice_4voices.csv
│
└── ru_open_stt_opus_unpacked                                   <= a separate folder for each uploaded domain
    ├── public_youtube1120
    │    ├── 0                                                  <= see "On disk DB methodology" for details
    │    ├── 1
    │    │   ├── 00
    │    │   │  ...
    │    │   └── ff
    │    │        ├── *.opus                                   <= actual files
    │    │        └── *.txt
    │    │   ...
    │    └── f
    │
    ├── public_youtube1120_hq
    ├── public_youtube700_val
    ├── asr_calls_2_val
    ├── radio_2
    ├── private_buriy_audiobooks_2
    ├── asr_public_phone_calls_2
    ├── asr_public_stories_2
    ├── asr_public_stories_1
    ├── public_lecture_1
    ├── asr_public_phone_calls_1
    ├── public_series_1
    └── public_youtube700
ADATKÉSZLET GB, WAV GB, ARCHÍV ARCHÍVUM FORRÁS JEGYZÉK
Betanítás
Rádiós és nyilvános beszédek minta - 11.4 opus+txt - jegyzékfájl
audiobook_2 162 25.8 opus+txt Internet + igazítás jegyzékfájl
radio_2 154 24.6 opus+txt Választógomb jegyzékfájl
public_youtube1120 237 19.0 opus+txt YouTube-videók jegyzékfájl
asr_public_phone_calls_2 66 9,4 opus+txt Internet + ASR jegyzékfájl
public_youtube1120_hq 31 4.9 opus+txt YouTube-videók jegyzékfájl
asr_public_stories_2 9 1.4 opus+txt Internet + igazítás jegyzékfájl
tts_russian_addresses_rhvoice_4voices 80.9 12.9 opus+txt TTS jegyzékfájl
public_youtube700 75,0 12.2 opus+txt YouTube-videók jegyzékfájl
asr_public_phone_calls_1 22,7 3.2 opus+txt Internet + ASR jegyzékfájl
asr_public_stories_1 4.1 0,7 opus+txt Nyilvános történetek jegyzékfájl
public_series_1 1,9 0.3 opus+txt Nyilvános sorozatok jegyzékfájl
public_lecture_1 0,7 0,1 opus+txt Internet + kézi jegyzékfájl
Val
asr_calls_2_val 2 0,8 wav+txt Internet jegyzékfájl
buriy_audiobooks_2_val 1 0,5 wav+txt Könyvek + manuális jegyzékfájl
public_youtube700_val 2 0,13 wav+txt YouTube videos + kézi jegyzékfájl

Letöltési útmutató

Közvetlen letöltés

Az adatkészlet közvetlen letöltésével kapcsolatos utasításokért tekintse meg a GitHub letöltési útmutatójának oldalát.

További információk

Az adatokkal kapcsolatos segítségért vagy kérdésekért forduljon az adatszerző(k)hez a következő címen: aveysov@gmail.com

Ez a licenc lehetővé teszi, hogy a felhasználók bármilyen adathordozón vagy formában terjesztsék, remixelhetik, adaptálhassák és felhasználhassák az anyagot, csak akkor, ha az alkotónak meg van adva a hozzárendelés. A következő összetevőket tartalmazza:

  • BY – Kreditet kell adni a létrehozónak
  • NC – Csak a munka nem kereskedelmi célú felhasználása engedélyezett

CC-BY-NC, a kereskedelmi felhasználáshoz az adatkészlet szerzőivel kötött megállapodás szükséges.

Az adatok elérése

Azure Notebooks

Segédfüggvények /függőségek

Libsndfile létrehozása

A pysoundfile (a libsoundfile körüli Python CFFI-burkoló) használatával hatékonyan olvashatja el az opus-fájlokat a Pythonban, amely nem jár jelentős többletterheléssel.

Az Opus támogatása a felsőbb rétegben lett implementálva, de nem lett megfelelően kiadva. Ezért az egyéni build + majom javítást választottuk.

Ezt általában sudo-hozzáféréssel kell futtatnia a rendszerhéjban:

apt-get update
apt-get install cmake autoconf autogen automake build-essential libasound2-dev \
libflac-dev libogg-dev libtool libvorbis-dev libopus-dev pkg-config -y

cd /usr/local/lib
git clone https://github.com/erikd/libsndfile.git
cd libsndfile
git reset --hard 49b7d61
mkdir -p build && cd build

cmake .. -DBUILD_SHARED_LIBS=ON
make && make install
cmake --build .

Segédfüggvények /függőségek

Telepítse az alábbi kódtárakat:

pandas
numpy
scipy
tqdm
soundfile
librosa

A jegyzékfájlok a következő oszlopokkal rendelkező CSV-fájlok:

  • A hang elérési útja
  • Szövegfájl elérési útja
  • Duration

Ezek bizonyultak az adatok elérésének legegyszerűbb formátumának.

A könnyű használat érdekében az összes jegyzék már újra van űzve. A bennük lévő összes elérési út relatív, gyökérmappát kell megadnia.

# manifest utils
import os
import numpy as np
import pandas as pd
from tqdm import tqdm
from urllib.request import urlopen


def reroot_manifest(manifest_df,
                    source_path,
                    target_path):
    if source_path != '':
        manifest_df.wav_path = manifest_df.wav_path.apply(lambda x: x.replace(source_path,
                                                                              target_path))
        manifest_df.text_path = manifest_df.text_path.apply(lambda x: x.replace(source_path,
                                                                                target_path))
    else:
        manifest_df.wav_path = manifest_df.wav_path.apply(lambda x: os.path.join(target_path, x))
        manifest_df.text_path = manifest_df.text_path.apply(lambda x: os.path.join(target_path, x))    
    return manifest_df


def save_manifest(manifest_df,
                  path,
                  domain=False):
    if domain:
        assert list(manifest_df.columns) == ['wav_path', 'text_path', 'duration', 'domain']
    else:
        assert list(manifest_df.columns) == ['wav_path', 'text_path', 'duration']

    manifest_df.reset_index(drop=True).sort_values(by='duration',
                                                   ascending=True).to_csv(path,
                                                                          sep=',',
                                                                          header=False,
                                                                          index=False)
    return True


def read_manifest(manifest_path,
                  domain=False):
    if domain:
        return pd.read_csv(manifest_path,
                        names=['wav_path',
                               'text_path',
                               'duration',
                               'domain'])
    else:
        return pd.read_csv(manifest_path,
                        names=['wav_path',
                               'text_path',
                               'duration'])


def check_files(manifest_df,
                domain=False):
    orig_len = len(manifest_df)
    if domain:
        assert list(manifest_df.columns) == ['wav_path', 'text_path', 'duration']
    else:
        assert list(manifest_df.columns) == ['wav_path', 'text_path', 'duration', 'domain']
    wav_paths = list(manifest_df.wav_path.values)
    text_path = list(manifest_df.text_path.values)

    omitted_wavs = []
    omitted_txts = []

    for wav_path, text_path in zip(wav_paths, text_path):
        if not os.path.exists(wav_path):
            print('Dropping {}'.format(wav_path))
            omitted_wavs.append(wav_path)
        if not os.path.exists(text_path):
            print('Dropping {}'.format(text_path))
            omitted_txts.append(text_path)

    manifest_df = manifest_df[~manifest_df.wav_path.isin(omitted_wavs)]
    manifest_df = manifest_df[~manifest_df.text_path.isin(omitted_txts)]
    final_len = len(manifest_df)

    if final_len != orig_len:
        print('Removed {} lines'.format(orig_len-final_len))
    return manifest_df


def plain_merge_manifests(manifest_paths,
                          MIN_DURATION=0.1,
                          MAX_DURATION=100):

    manifest_df = pd.concat([read_manifest(_)
                             for _ in manifest_paths])
    manifest_df = check_files(manifest_df)

    manifest_df_fit = manifest_df[(manifest_df.duration>=MIN_DURATION) &
                                  (manifest_df.duration<=MAX_DURATION)]

    manifest_df_non_fit = manifest_df[(manifest_df.duration<MIN_DURATION) |
                                      (manifest_df.duration>MAX_DURATION)]

    print(f'Good hours: {manifest_df_fit.duration.sum() / 3600:.2f}')
    print(f'Bad hours: {manifest_df_non_fit.duration.sum() / 3600:.2f}')

    return manifest_df_fit


def save_txt_file(wav_path, text):
    txt_path = wav_path.replace('.wav','.txt')
    with open(txt_path, "w") as text_file:
        print(text, file=text_file)
    return txt_path


def read_txt_file(text_path):
    #with open(text_path, 'r') as file:
    response = urlopen(text_path)
    file = response.readlines()
    for i in range(len(file)):
        file[i] = file[i].decode('utf8')
    return file 

def create_manifest_from_df(df, domain=False):
    if domain:
        columns = ['wav_path', 'text_path', 'duration', 'domain']
    else:
        columns = ['wav_path', 'text_path', 'duration']
    manifest = df[columns]
    return manifest


def create_txt_files(manifest_df):
    assert 'text' in manifest_df.columns
    assert 'wav_path' in manifest_df.columns
    wav_paths, texts = list(manifest_df['wav_path'].values), list(manifest_df['text'].values)
    # not using multiprocessing for simplicity
    txt_paths = [save_txt_file(*_) for _ in tqdm(zip(wav_paths, texts), total=len(wav_paths))]
    manifest_df['text_path'] = txt_paths
    return manifest_df


def replace_encoded(text):
    text = text.lower()
    if '2' in text:
        text = list(text)
        _text = []
        for i,char in enumerate(text):
            if char=='2':
                try:
                    _text.extend([_text[-1]])
                except:
                    print(''.join(text))
            else:
                _text.extend([char])
        text = ''.join(_text)
    return text
# reading opus files
import os
import soundfile as sf



# Fx for soundfile read/write functions
def fx_seek(self, frames, whence=os.SEEK_SET):
    self._check_if_closed()
    position = sf._snd.sf_seek(self._file, frames, whence)
    return position


def fx_get_format_from_filename(file, mode):
    format = ''
    file = getattr(file, 'name', file)
    try:
        format = os.path.splitext(file)[-1][1:]
        format = format.decode('utf-8', 'replace')
    except Exception:
        pass
    if format == 'opus':
        return 'OGG'
    if format.upper() not in sf._formats and 'r' not in mode:
        raise TypeError("No format specified and unable to get format from "
                        "file extension: {0!r}".format(file))
    return format


#sf._snd = sf._ffi.dlopen('/usr/local/lib/libsndfile/build/libsndfile.so.1.0.29')
sf._subtypes['OPUS'] = 0x0064
sf.SoundFile.seek = fx_seek
sf._get_format_from_filename = fx_get_format_from_filename


def read(file, **kwargs):
    return sf.read(file, **kwargs)


def write(file, data, samplerate, **kwargs):
    return sf.write(file, data, samplerate, **kwargs)
# display utils
import gc
from IPython.display import HTML, Audio, display_html
pd.set_option('display.max_colwidth', 3000)
#Prepend_path is set to read directly from Azure. To read from local replace below string with path to the downloaded dataset files
prepend_path = 'https://azureopendatastorage.blob.core.windows.net/openstt/ru_open_stt_opus_unpacked/'


def audio_player(audio_path):
    return '<audio preload="none" controls="controls"><source src="{}" type="audio/wav"></audio>'.format(audio_path)

def display_manifest(manifest_df):
    display_df = manifest_df
    display_df['wav'] = [audio_player(prepend_path+path) for path in display_df.wav_path]
    display_df['txt'] = [read_txt_file(prepend_path+path) for path in tqdm(display_df.text_path)]
    audio_style = '<style>audio {height:44px;border:0;padding:0 20px 0px;margin:-10px -20px -20px;}</style>'
    display_df = display_df[['wav','txt', 'duration']]
    display(HTML(audio_style + display_df.to_html(escape=False)))
    del display_df
    gc.collect()

Lejátszás adatkészlettel

Fájlminta lejátszása

A legtöbb platformböngésző támogatja a natív hanglejátszást. Így HTML5-hang lejátszók használatával tekinthetjük meg az adatokat.

manifest_df = read_manifest(prepend_path +'/manifests/public_series_1.csv')
#manifest_df = reroot_manifest(manifest_df,
                              #source_path='',
                              #target_path='../../../../../nvme/stt/data/ru_open_stt/')

sample = manifest_df.sample(n=20)
display_manifest(sample)

Fájl beolvasása

!ls ru_open_stt_opus/manifests/*.csv

Néhány példa a wav- és opusfájlok legjobb olvasására.

Scipy a leggyorsabb hullámos. A Pysoundfile a legjobb az opushoz.

%matplotlib inline

import librosa
from scipy.io import wavfile
from librosa import display as ldisplay
from matplotlib import pyplot as plt

Hullám olvasása

manifest_df = read_manifest(prepend_path +'manifests/asr_calls_2_val.csv')
#manifest_df = reroot_manifest(manifest_df,
                              #source_path='',
                              #target_path='../../../../../nvme/stt/data/ru_open_stt/')
sample = manifest_df.sample(n=5)
display_manifest(sample)
from io import BytesIO

wav_path = sample.iloc[0].wav_path
response = urlopen(prepend_path+wav_path)
data = response.read()
sr, wav = wavfile.read(BytesIO(data))
wav.astype('float32')
absmax = np.max(np.abs(wav))
wav =  wav / absmax
# shortest way to plot a spectrogram
D = librosa.amplitude_to_db(np.abs(librosa.stft(wav)), ref=np.max)
plt.figure(figsize=(12, 6))
ldisplay.specshow(D, y_axis='log')
plt.colorbar(format='%+2.0f dB')
plt.title('Log-frequency power spectrogram')
# shortest way to plot an envelope
plt.figure(figsize=(12, 6))
ldisplay.waveplot(wav, sr=sr, max_points=50000.0, x_axis='time', offset=0.0, max_sr=1000, ax=None)

Opus olvasása

manifest_df = read_manifest(prepend_path +'manifests/asr_public_phone_calls_2.csv')
#manifest_df = reroot_manifest(manifest_df,
                              #source_path='',
                              #target_path='../../../../../nvme/stt/data/ru_open_stt/')
sample = manifest_df.sample(n=5)
display_manifest(sample)
opus_path = sample.iloc[0].wav_path
response = urlopen(prepend_path+opus_path)
data = response.read()
wav, sr = sf.read(BytesIO(data))
wav.astype('float32')
absmax = np.max(np.abs(wav))
wav =  wav / absmax
# shortest way to plot a spectrogram
D = librosa.amplitude_to_db(np.abs(librosa.stft(wav)), ref=np.max)
plt.figure(figsize=(12, 6))
ldisplay.specshow(D, y_axis='log')
plt.colorbar(format='%+2.0f dB')
plt.title('Log-frequency power spectrogram')
# shortest way to plot an envelope
plt.figure(figsize=(12, 6))
ldisplay.waveplot(wav, sr=sr, max_points=50000.0, x_axis='time', offset=0.0, max_sr=1000, ax=None)

További lépések

Tekintse meg a többi adathalmazt az Open Datasets katalógusban.