Rosyjska otwarta mowa do tekstu
Kolekcja próbek mowy z różnych źródeł dźwięku. Ten zestaw danych zawiera krótkie klipy audio w języku rosyjskim.
Uwaga
Firma Microsoft udostępnia zestawy danych Platformy Azure open na zasadzie "tak, jak to jest". Firma Microsoft nie udziela żadnych gwarancji, wyraźnych lub domniemanych, gwarancji ani warunków w odniesieniu do korzystania z zestawów danych. W zakresie dozwolonym zgodnie z prawem lokalnym firma Microsoft nie ponosi odpowiedzialności za wszelkie szkody lub straty, w tym bezpośrednie, wtórne, specjalne, pośrednie, przypadkowe lub karne wynikające z korzystania z zestawów danych.
Zestaw danych jest udostępniany zgodnie z pierwotnymi warunkami, na jakich firma Microsoft otrzymała dane źródłowe. Zestaw danych może zawierać dane pozyskane z firmy Microsoft.
Ten rosyjski zestaw danych zamiany mowy na tekst (STT) obejmuje:
- Ok. 16 milionów wypowiedzi
- ~20 000 godzin
- 2,3 TB (nieskompresowane w formacie .wav w int16), 356G w opus
- Wszystkie pliki zostały przekształcone w wartość opus, z wyjątkiem zestawów danych weryfikacji
Głównym przeznaczeniem zestawu danych jest trenowanie modeli przekształcających mowę na tekst.
Budowa zestawu danych
Rozmiar zestawu danych jest podawany dla plików .wav.
ZESTAW DANYCH | WYPOWIEDZI | GODZIN | GB | SECS/CHARS | KOMENTARZ | ADNOTACJA | JAKOŚĆ/SZUM |
---|---|---|---|---|---|---|---|
radio_v4 (*) | 7 603 192 | 10 430 | 1195 | 5 s / 68 | Przycisk radiowy | Align | 95% / wyraźne |
public_speech (*) | 1 700 060 | 2 709 | 301 | 6 s / 79 | Przemówienia publiczne | Align | 95% / wyraźne |
audiobook_2 | 1 149 404 | 1511 | 162 | 5 s / 56 | Księgi | Align | 95% / wyraźne |
radio_2 | 651 645 | 1 439 | 154 | 8 s / 110 | Przycisk radiowy | Align | 95% / wyraźne |
public_youtube1120 | 1 410 979 | 1104 | 237 | 3 s / 34 | YouTube | Podtytuły | 95% / ~wyraźne |
public_youtube700 | 759 483 | 701 | 75 | 3 s / 43 | YouTube | Podtytuły | 95% / ~wyraźne |
tts_russian_addresses | 1 741 838 | 754 | 81 | 2 s / 20 | Adresy | Głosy TTS 4 | 100% / wyraźne |
asr_public_phone_calls_2 | 603 797 | 601 | 66 | 4 s / 37 | Rozmowy telefoniczne | ASR | 70% / zaszumione |
public_youtube1120_hq | 369 245 | 291 | 31 | 3 s / 37 | YouTube HQ | Podtytuły | 95% / ~wyraźne |
asr_public_phone_calls_1 | 233 868 / 2000 | 211 | 23 | 3 s / 29 | Rozmowy telefoniczne | ASR | 70% / zaszumione |
radio_v4_add (*) | 92 679 | 157 | 18 | 6 s / 80 | Przycisk radiowy | Align | 95% / wyraźne |
asr_public_stories_2 | 78 186 | 78 | 9 | 4 s / 43 | Księgi | ASR | 80% / wyraźne |
asr_public_stories_1 | 46 142 | 38 | 100 | 3 s / 30 | Księgi | ASR | 80% / wyraźne |
public_series_1 | 20 243 | 17 | 2 | 3 s / 38 | YouTube | Podtytuły | 95% / ~wyraźne |
asr_calls_2_val | 12 950 | 7,7 | 2 | 2 s / 34 | Rozmowy telefoniczne | Ręczne adnotacje | 99% / wyraźne |
public_lecture_1 | 6 803 | 6 | 1 | 3 s / 47 | Wykłady | Podtytuły | 95% / wyraźne |
buriy_audiobooks_2_val | 7850 | 4,9 | 1 | 2 s / 31 | Księgi | Ręczne adnotacje | 99% / wyraźne |
public_youtube700_val | 7311 | 4,5 | 1 | 2 s / 35 | YouTube | Ręczne adnotacje | 99% / wyraźne |
(*) Za pomocą plików txt udostępniana jest tylko próbka danych.
Metodologia adnotacji
Zestaw danych został przygotowany za pomocą otwartych źródeł. Długie zdania są dzielone na fragmenty audio za pomocą funkcji wykrywania aktywności głosowej i wyrównywania. Niektóre typy audio są automatycznie oznaczone adnotacjami i weryfikowane statystycznie przy użyciu heurystyki.
Woluminy danych i częstotliwość aktualizacji
Całkowity rozmiar zestawu danych to 350 GB. Łączny rozmiar zestawu danych z etykietami udostępnionymi publicznie wynosi 130 GB.
Sam zestaw danych prawdopodobnie nie zostanie zaktualizowany pod kątem zgodności z poprzednimi wersjami. Postępuj zgodnie z oryginalnym repozytorium testów porównawczych i wyklucz pliki.
W przyszłości mogą zostać dodane nowe domeny i języki.
Normalizacja audio
Wszystkie pliki są znormalizowane w celu łatwiejszego i szybszego rozszerzania środowiska uruchomieniowego. Przetwarzanie jest następujące:
- Przekonwertowane do formatu mono, jeśli to konieczne
- W razie potrzeby przekonwertowana na częstotliwość próbkowania 16 kHz;
- Zapisane jako 16-bitowe wartości całkowite
- Przekonwertowane do formatu OPUS
Metodologia bazy danych na dysku
Każdy plik audio (wav, binarny) ma skrót. Skrót służy do tworzenia hierarchii folderów w celu uzyskania bardziej optymalnej operacji fs.
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)
Pobieranie
Zestaw danych jest udostępniany w dwóch formularzach:
- Archiwa dostępne za pośrednictwem usługi Azure Blob Storage i/lub linków bezpośrednich;
- Oryginalne pliki dostępne za pośrednictwem usługi Azure Blob Storage; Wszystko jest przechowywane w 'https://azureopendatastorage.blob.core.windows.net/openstt/'
Struktura folderów:
└── 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
ZESTAW DANYCH | GB, WAV | GB, ARCHIWUM | ARCHIWUM | ŹRÓDŁO | MANIFEST |
---|---|---|---|---|---|
Szkolenie | |||||
Przykłady z radia i przemówień publicznych | - | 11,4 | opus i txt | - | manifest |
audiobook_2 | 162 | 25,8 | opus i txt | Internet i wyrównanie | manifest |
radio_2 | 154 | 24,6 | opus i txt | Przycisk radiowy | manifest |
public_youtube1120 | 237 | 19,0 | opus i txt | Filmy z serwisu YouTube | manifest |
asr_public_phone_calls_2 | 66 | 9,4 | opus i txt | Internet i ASR | manifest |
public_youtube1120_hq | 31 | 4.9 | opus i txt | Filmy z serwisu YouTube | manifest |
asr_public_stories_2 | 9 | 1.4 | opus i txt | Internet i wyrównanie | manifest |
tts_russian_addresses_rhvoice_4voices | 80,9 | 12,9 | opus i txt | TTS | manifest |
public_youtube700 | 75,0 | 12,2 | opus i txt | Filmy z serwisu YouTube | manifest |
asr_public_phone_calls_1 | 22,7 | 3.2 | opus i txt | Internet i ASR | manifest |
asr_public_stories_1 | 4.1 | 0,7 | opus i txt | Historie publiczne | manifest |
public_series_1 | 1,9 | 0.3 | opus i txt | Serie publiczne | manifest |
public_lecture_1 | 0,7 | 0.1 | opus i txt | Internet i ręcznie | manifest |
Val | |||||
asr_calls_2_val | 2 | 0,8 | wav i txt | Internet | manifest |
buriy_audiobooks_2_val | 1 | 0.5 | wav i txt | Książki i ręcznie | manifest |
public_youtube700_val | 2 | 0,13 | wav i txt | Wideo z usługi YouTube i ręcznie | manifest |
Instrukcje pobierania
Pobieranie bezpośrednie
Aby uzyskać instrukcje dotyczące bezpośredniego pobierania zestawu danych, zobacz stronę instrukcji pobierania w usłudze GitHub.
Dodatkowe informacje
Aby uzyskać pomoc lub pytania dotyczące danych, skontaktuj się z autorami danych pod adresem aveysov@gmail.com
Licencja ta pozwala użytkownikom rozpowszechniać, remix, dostosowywać i opierać się na materiale w dowolnym nośniku lub formacie tylko w celach niekomercyjnych i tylko tak długo, jak przypisanie jest podane twórcy. Obejmuje następujące elementy:
- BY — kredyt musi zostać przyznany twórcy
- NC — dozwolone są tylko niekomercyjne zastosowania pracy
Licencja CC-BY-NC i użytek komercyjny jest możliwy po zawarciu umowy z autorami zestawu danych.
Dostęp do danych
Azure Notebooks
Funkcje/zależności pomocnika
Kompilowanie pliku libsndfile
Wydajnym sposobem odczytywania plików opus w języku Python, który nie wiąże się ze znaczącym obciążeniem, jest użycie pliku pysoundfile (otoki CFFI języka Python wokół libsoundfile).
Obsługa Firmy Opus została wdrożona w górę, ale nie została prawidłowo wydana. W związku z tym wybraliśmy niestandardową kompilację i stosowanie poprawek małp.
Zazwyczaj należy to uruchomić w powłoce przy użyciu dostępu sudo:
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 .
Funkcje/zależności pomocnika
Zainstaluj następujące biblioteki:
pandas
numpy
scipy
tqdm
soundfile
librosa
Manifesty to pliki CSV z następującymi kolumnami:
- Ścieżka do dźwięku
- Ścieżka do pliku tekstowego
- Czas trwania
Okazało się, że jest to najprostszy format uzyskiwania dostępu do danych.
Aby ułatwić korzystanie, wszystkie manifesty są już ponownie wyrootowane. Wszystkie ścieżki w nich są względne. Musisz podać folder główny.
# 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()
Odtwarzanie za pomocą zestawu danych
Odtwarzanie próbki plików
Większość przeglądarek platform obsługuje natywne odtwarzanie dźwięku. Aby wyświetlić nasze dane, możemy użyć odtwarzaczy audio HTML5.
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)
Odczytywanie pliku
!ls ru_open_stt_opus/manifests/*.csv
Niektóre przykłady pokazujące, jak najlepiej odczytywać pliki wav i opus.
Scipy jest najszybszy dla fal. Pysoundfile jest najlepszym w klasyfikacji generalnej dla opus.
%matplotlib inline
import librosa
from scipy.io import wavfile
from librosa import display as ldisplay
from matplotlib import pyplot as plt
Odczytywanie fali
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)
Odczytywanie parametru opus
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)
Następne kroki
Wyświetl pozostałe zestawy danych w katalogu Open Datasets (Otwieranie zestawów danych).