Bagikan melalui


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.