Pidato Terbuka Bahasa Rusia ke Teks
Kumpulan sampel ucapan berasal dari berbagai penyedia sumber audio. Kumpulan himpunan data berisi klip audio pendek dalam bahasa Rusia.
Catatan
Microsoft menyediakan Azure Open Datasets berdasarkan "apa adanya". Microsoft tidak memberikan jaminan, tersurat maupun tersirat, jaminan atau ketentuan sehubungan dengan penggunaan Anda atas himpunan data. Sejauh diizinkan menurut undang-undang setempat Anda, Microsoft melepaskan semua tanggung jawab atas segala kerusakan atau kerugian, termasuk langsung, konsekuensial, khusus, tidak langsung, insidental, atau hukuman, yang diakibatkan oleh penggunaan Anda atas kumpulan data.
Kumpulan data ini disediakan di bawah ketentuan asli yang diterima Microsoft data sumbernya. Himpunan data mungkin menyertakan data yang bersumber dari Microsoft.
Kumpulan himpunan data ucapan ke teks (STT) Rusia ini meliputi:
- ~16 juta ucapan
- ~20,000 jam
- 2,3 TB (tidak dikompresi dalam format .wav dalam int16), 356G di opus
- Semua file diubah ke opus, kecuali untuk validasi himpunan data
Tujuan utama dari himpunan data adalah untuk melatih model ucapan ke teks.
Komposisi himpunan data
Ukuran himpunan data diberikan untuk .wav anda.
HIMPUNAN DATA | UCAPAN | JAM | GB | SECS/CHARS | KOMENTAR | ANOTASI | KUALITAS/KEBISINGAN |
---|---|---|---|---|---|---|---|
radio_v4 (*) | 7.603.192 | 10.430 | 1.195 | 5det / 68 | Radio | Meratakan | 95% / crisp |
pidato_publik (*) | 1.700.060 | 2.709 | 301 | 6det / 79 | Pidato publik | Meratakan | 95% / crisp |
audiobook_2 | 1.149.404 | 1.511 | 162 | 5det / 56 | Buku | Meratakan | 95% / crisp |
radio_2 | 651.645 | 1.439 | 154 | 8det / 110 | Radio | Meratakan | 95% / crisp |
public_youtube1120 | 1.410.979 | 1,104 | 237 | 3det / 34 | YouTube | Subtitel | 95% / ~crisp |
public_youtube700 | 759.483 | 701 | 75 | 3det / 43 | YouTube | Subtitel | 95% / ~crisp |
tts_russian_addresses | 1.741.838 | 754 | 81 | 2det / 20 | Alamat | TTS 4 suara | 100% / crisp |
asr_public_phone_calls_2 | 603.797 | 601 | 66 | 4det / 37 | Panggilan telepon | ASR | 70% / Kebisingan |
public_youtube1120_hq | 369.245 | 291 | 31 | 3det / 37 | YouTube HQ | Subtitel | 95% / ~crisp |
asr_public_phone_calls_1 | 233.868 | 211 | 23 | 3det / 29 | Panggilan telepon | ASR | 70% / Kebisingan |
radio_v4_add (*) | 92.679 | 157 | 18 | 6det / 80 | Radio | Meratakan | 95% / crisp |
asr_public_stories_2 | 78.186 | 78 | 9 | 4det / 43 | Buku | ASR | 80% / crisp |
asr_public_stories_1 | 46.142 | 38 | 4 | 3det / 30 | Buku | ASR | 80% / crisp |
public_series_1 | 20.243 | 17 | 2 | 3det / 38 | YouTube | Subtitel | 95% / ~crisp |
asr_calls_2_val | 12.950 | 7.7 | 2 | 2det / 34 | Panggilan telepon | Anotasi manual | 99% / crisp |
public_lecture_1 | 6.803 | 6 | 1 | 3det / 47 | Pelajaran | Subtitel | 95% / crisp |
buriy_audiobooks_2_val | 7.850 | 4.9 | 1 | 2det / 31 | Buku | Anotasi manual | 99% / crisp |
public_youtube700_val | 7.311 | 4.5 | 1 | 2det / 35 | YouTube | Anotasi manual | 99% / crisp |
(*) Hanya sampel data yang disediakan dengan file txt.
Metodologi anotasi
Himpunan data dikompilasi menggunakan open source. Urutan panjang dibagi menjadi beberapa potongan audio menggunakan deteksi dan penyelarasan aktivitas suara. Beberapa jenis audio dianotasikan secara otomatis dan diverifikasi secara statistik dengan heuristik.
Volume data dan frekuensi pembaruan
Ukuran total himpunan data adalah 350 GB. Ukuran total himpunan data dengan label yang dibagikan secara publik adalah 130 GB.
Himpunan data itu sendiri tidak mungkin diperbarui untuk kompatibilitas mundur. Ikuti repositori asli untuk tolok ukur dan pisahkan file.
Domain dan bahasa baru mungkin ditambahkan di masa mendatang.
Normalisasi audio
Semua file dinormalisasi untuk augmentasi runtime bahasa umum yang lebih mudah dan lebih cepat. Pemrosesan adalah sebagai berikut:
- Dikonversi ke mono, jika perlu;
- Dikonversi ke tingkat pengambilan sampel 16 kHz, jika perlu;
- Disimpan sebagai bilangan bulat 16-bit;
- Dikonversi ke OPUS;
Pada metodologi DB disk
Setiap file audio (wav, biner) di-hash (potong). Hash digunakan untuk membuat hierarki folder untuk operasi fs yang lebih optimal.
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)
Unduhan
Himpunan data disediakan dalam dua bentuk:
- Arsip tersedia melalui penyimpanan objek besar biner Azure dan/atau tautan langsung;
- File asli tersedia melalui penyimpanan blob Azure; Semuanya disimpan di ‘https://azureopendatastorage.blob.core.windows.net/openstt/’
Struktur folder:
└── 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
HIMPUNAN DATA | GB, WAV | GB, ARSIP | ARCHIVE | SUMBER | MANIFES |
---|---|---|---|---|---|
Berlatih | |||||
Sampel radio dan ucapan publik | - | 11,4 | opus+txt | - | manifest |
audiobook_2 | 162 | 25,8 | opus+txt | Internet + perataan | manifest |
radio_2 | 154 | 24,6 | opus+txt | Radio | manifest |
public_youtube1120 | 237 | 19,0 | opus+txt | Video YouTube | manifest |
asr_public_phone_calls_2 | 66 | 9,4 | opus+txt | Internet + ASR | manifest |
public_youtube1120_hq | 31 | 4.9 | opus+txt | Video YouTube | manifest |
asr_public_stories_2 | 9 | 1.4 | opus+txt | Internet + perataan | manifest |
tts_russian_addresses_rhvoice_4voices | 80,9 | 12,9 | opus+txt | TTS | manifest |
public_youtube700 | 75,0 | 12,2 | opus+txt | Video YouTube | manifest |
asr_public_phone_calls_1 | 22,7 | 3.2 | opus+txt | Internet + ASR | manifest |
asr_public_stories_1 | 4.1 | 0,7 | opus+txt | Cerita publik | manifest |
public_series_1 | 1.9 | 0,3 | opus+txt | Seri publik | manifest |
public_lecture_1 | 0,7 | 0.1 | opus+txt | Internet + manual | manifest |
Val | |||||
asr_calls_2_val | 2 | 0,8 | wav+txt | Internet | manifest |
buriy_audiobooks_2_val | 1 | 0,5 | wav+txt | Buku + manual | manifest |
public_youtube700_val | 2 | 0,13 | wav+txt | Video YouTube + manual | manifest |
Lihat instruksi pengunduhan
Unduhan langsung
Untuk petunjuk tentang cara mengunduh himpunan data secara langsung, lihat halaman instruksi unduhan GitHub.
Informasi Tambahan
Untuk bantuan atau pertanyaan tentang data, hubungi penulis data di aveysov@gmail.com
Lisensi ini mengizinkan pengguna untuk mendistribusikan, me-remix, mengadaptasi, dan membangun materi pada media atau format apa pun untuk tujuan nonkomersial saja, dan hanya selama atribusi diberikan ke pembuat. Semua itu termasuk elemen berikut:
- BY – Kredit harus diberikan kepada pembuat
- NC - Hanya penggunaan nonkomersial dari karya yang diizinkan
CC-BY-NC dan penggunaan komersial tersedia setelah perjanjian dengan penulis himpunan data.
Akses data
Azure Notebooks
Fungsi pembantu / dependensi
Membangun libsndfile
Cara cepat membaca file opus di Python agar tidak menimbulkan overhead signifikan yaitu dengan menggunakan pysoundfile (pembungkus CFFI Python di sekeliling libsoundfile).
Dukungan Opus telah dijalankan di upstram, namun belum dirilis dengan baik. Oleh karena itu, kami memilih untuk membangun kustom + monkey patch.
Biasanya, Anda perlu menjalankan ini di shell Anda dengan akses 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 .
Fungsi pembantu / dependensi
Instal pustaka berikut ini:
pandas
numpy
scipy
tqdm
soundfile
librosa
Manifes adalah file csv dengan kolom berikut:
- Jalur ke audio
- Jalur ke file teks
- Durasi
Mereka terbukti menjadi format paling sederhana dalam mengakses data.
Untuk kemudahan penggunaan, semua manifes sudah dicabut. Semua jalur relatif, Anda perlu menyediakan direktori akar.
# 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()
Coba putar dengan himpunan data
Memutar sampel file
Kebanyakan browser platform mendukung pemutaran audio asli. Jadi kita dapat menggunakan pemutar audio HTML5 untuk menampilkan data kita.
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)
Membaca file
!ls ru_open_stt_opus/manifests/*.csv
Beberapa contoh menampilkan cara terbaik membaca file wav dan opus.
Scipy merupakan yang tercepat untuk wav. Pysoundfile menjadi yang terbaik untuk opus.
%matplotlib inline
import librosa
from scipy.io import wavfile
from librosa import display as ldisplay
from matplotlib import pyplot as plt
Membaca wav
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)
Membaca 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)
Langkah berikutnya
Lihat himpunan data lainnya di katalog Open Datasets.