Rusça konuşmayı metne açma

Çeşitli ses kaynaklarından toplanan konuşma örnekleri koleksiyonu. Veri kümesi Rusça kısa ses klipleri içerir.

Not

Microsoft, Azure Açık Veri Kümeleri "olduğu gibi" temel alan bir hizmet sağlar. Microsoft, veri kümelerini kullanımınıza yönelik açık veya zımni garantiler veya koşullar vermez. Microsoft, yerel yasalarınız kapsamında izin verilen ölçüde, veri kümelerini kullanımınız sonucunda ortaya çıkan doğrudan, sonuçsal, özel, dolaylı, arızi veya ceza da dahil olmak üzere tüm zararlar veya kayıplar için tüm sorumluluğu kabulmektedir.

Bu veri kümesi Microsoft’un kaynak verileri aldığı orijinal hükümler kapsamında sağlanır. Veri kümesi Microsoft’tan alınan verileri içerebilir.

Bu Rusça konuşmadan metin (STT) veri kümesi şunları içerir:

  • ~ 16.000.000 uttersları
  • ~ 20.000 saat
  • 2,3 TB (Int16 içinde. wav biçiminde sıkıştırılmamış), Opus 'de 356G
  • Tüm dosyalar, doğrulama veri kümeleri hariç Opus olarak dönüştürüldü

Veri kümesinin temel amacı konuşmayı metne dönüştürme modellerini eğitmektir.

Veri kümesi bileşimi

Veri kümesi boyutu. wav dosyaları için verilir.

VERI KÜMESI En konuşma SAATLERININ GB SANIYE/KARAKTER COMMENT EK açıklama KALITE/GÜRÜLTÜ
radio_v4 (*) 7.603.192 10.430 1.195 5 sn / 68 Radyo Hizala %95/canlı
public_speech (*) 1.700.060 2.709 301 6 sn / 79 Genel konuşma Hizala %95/canlı
audiobook_2 1.149.404 1.511 162 5 sn / 56 Kitaplar Hizala %95/canlı
radio_2 651.645 1.439 154 8 sn / 110 Radyo Hizala %95/canlı
public_youtube1120 1.410.979 1.104 237 3 sn / 34 YouTube Alt yazılar %95/~ canlı
public_youtube700 759.483 701 75 3 sn / 43 YouTube Alt yazılar %95/~ canlı
tts_russian_addresses 1.741.838 754 81 2 sn / 20 Adresler TTS 4 sesleri %100 / net
asr_public_phone_calls_2 603.797 601 66 4 sn / 37 Telefon aramaları ASR %70/gürültülü
public_youtube1120_hq 369.245 291 31 3 sn / 37 YouTube HQ Alt yazılar %95/~ canlı
asr_public_phone_calls_1 233.868 211 23 3 sn / 29 Telefon aramaları ASR %70/gürültülü
radio_v4_add (*) 92.679 157 18 6 sn / 80 Radyo Hizala %95 /sn
asr_public_stories_2 78.186 78 9 4 sn / 43 Kitaplar ASR %80/sn
asr_public_stories_1 46.142 38 4 3 sn / 30 Kitaplar ASR %80/sn
public_series_1 20.243 17 2 3 sn / 38 YouTube Alt yazılar %95 / ~~~~
asr_calls_2_val 12.950 7,7 2 2 sn / 34 Telefon aramaları El ile ek açıklama %99 /sn
public_lecture_1 6.803 6 1 3 sn / 47 Konuşmalar Alt yazılar %95 /sn
buriy_audiobooks_2_val 7.850 4,9 1 2 sn / 31 Kitaplar El ile ek açıklama %99 /sn
public_youtube700_val 7.311 4,5 1 2 sn / 35 YouTube El ile ek açıklama %99 /sn

(*) Txt dosyalarıyla yalnızca örnek veriler sağlanır.

Ek açıklama metodolojisi

Veri kümesi açık kaynaklar kullanılarak derlenmiştir. Uzun diziler ses etkinliği algılama ve hizalama kullanılarak ses öbeklerine ayrılır. Bazı ses türleri, heuristics kullanılarak otomatik olarak ek açıklama eklenir ve istatistiksel olarak doğrulanır.

Veri birimleri ve güncelleştirme sıklığı

Veri kümesi toplam boyutu 350 GB'tır. Genel olarak paylaşılan etiketlere sahip veri kümesi toplam boyutu 130 GB'tır.

Veri kümesi büyük olasılıkla geriye dönük uyumluluk için güncelleştirilmez. Karşılaştırmalar ve dışlama dosyaları için özgün depoyu izleyin.

Gelecekte yeni etki alanları ve diller eklenebilir.

Ses normalleştirme

Tüm dosyalar daha kolay ve daha hızlı çalışma zamanı büyütmeleri için normalleştirilmiştir. İşleme şu şekildedir:

  • Gerekirse monoya dönüştürülür;
  • Gerekirse 16 kHz örnekleme hızına dönüştürülür;
  • 16 bit tamsayılar olarak depolanır;
  • OPUS’a dönüştürülür;

Disk üzerinde veritabanı metodolojisi

Her ses dosyasına (wav, ikili) karma işlemi uygulanır. Karma, daha iyi fs işlemi için bir klasör hiyerarşisi oluşturmak için kullanılır.

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)

İndirmeler

Veri kümesi iki şekilde sağlanır:

Klasör yapısı:

└── 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
Dataset GB, WAV GB, ARŞİV Arşiv KAYNAK Bildirim
Eğitim
Radyo ve genel konuşma örneği - 11,4 opus+txt - bildirim
audiobook_2 162 25,8 opus+txt İnternet + hizalama bildirim
radio_2 154 24,6 opus+txt Radyo bildirim
public_youtube1120 237 19,0 opus+txt YouTube videoları bildirim
asr_public_phone_calls_2 66 9.4 opus+txt İnternet + ASR bildirim
public_youtube1120_hq 31 4,9 opus+txt YouTube videoları bildirim
asr_public_stories_2 9 1.4 opus+txt İnternet + hizalama bildirim
tts_russian_addresses_rhvoice_4voices 80,9 12,9 opus+txt TTS bildirim
public_youtube700 75.0 12,2 opus+txt YouTube videoları bildirim
asr_public_phone_calls_1 22.7 3.2 opus+txt İnternet + ASR bildirim
asr_public_stories_1 4.1 0.7 opus+txt Genel hikayeler bildirim
public_series_1 1.9 0.3 opus+txt Genel seriler bildirim
public_lecture_1 0.7 0.1 opus+txt İnternet + el kitabı bildirim
Val
asr_calls_2_val 2 0.8 wav+txt İnternet bildirim
buriy_audiobooks_2_val 1 0,5 wav+txt Kitaplar + el kitabı bildirim
public_youtube700_val 2 0.13 wav+txt YouTube videoları + el kitabı bildirim

İndirme yönergeleri

Doğrudan indirme

Veri kümesinin doğrudan nasıl indirileceği hakkında yönergeler için bkz. GitHub indirme yönergeleri sayfası.

Ek bilgiler

Veriler hakkındaki yardım veya sorular için, şu adreste bulunan veri yazarlarıyla iletişim kurun: aveysov@gmail.com

Bu lisans, kullanıcıların yalnızca ticari olmayan amaçlar için herhangi bir ortamda ya da biçimde her türlü ortama veya formata dağıtım yapmasına, yeniden karışmasını, uyarlanmasını ve oluşturmasını sağlar. Bu, aşağıdaki öğeleri içerir:

  • BY – Oluşturucuya kredi ver gerekir
  • NC – Yalnızca iş ticari olmayan kullanımlara izin verilir

CC-BY-NC ve ticari kullanım, veri kümesi yazarlarıyla anlaşma yapıldıktan sonra gerçekleştirilebilir.

Veri erişimi

Azure Notebooks

Yardımcı işlevler/bağımlılıklar

Libsndfile bina

Python'da önemli bir ek yüke neden olmayan opus dosyalarını okumanın verimli bir yolu, pyfile (libfile çevresindeki bir Python CFFI sarmalayıcı) kullanmaktır.

Yukarı akışta opus desteği uygulanmıştır ancak düzgün bir şekilde yayımlanmaz. Bu nedenle özel derleme + maymun düzeltme eki uygulama tercihini kullandık.

Genellikle bunu sudo erişimiyle kabuğunda çalıştırmanız gerekir:

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 .

Yardımcı işlevler/bağımlılıklar

Aşağıdaki kitaplıkları yükleyin:

pandas
numpy
scipy
tqdm
soundfile
librosa

Bildirim, aşağıdaki sütunlara sahip csv dosyalarıdır:

  • Ses yolu
  • Metin dosyasının yolu
  • Süre

Verilere erişmenin en basit biçimi olduğu kanıtlandı.

Kullanım kolaylığı için tüm bildirimlerin kökü zaten yeniden köke alındı. Bunlarda yer alan tüm yollar görelidir, bir kök klasör sağlamanız gerekir.

# 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()

Veri kümesiyle oynatma

Dosya örneği oynatma

Çoğu platform tarayıcısı yerel ses kayıttan yürütmeyi destekler. Bu nedenle verilerimizi görüntülemek için HTML5 ses oyuncularını kullanabiliriz.

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)

Dosya okuma

!ls ru_open_stt_opus/manifests/*.csv

Wav ve opus dosyalarını en iyi şekilde nasıl okuyabilirsiniz? gösteren bazı örnekler.

Scipy, wav için en hızlıdır. Pyfile, operasyon için en iyi geneldir.

%matplotlib inline

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

Wav okuma

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)

Okuma 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)

Sonraki adımlar

Açık Veri Kümeleri kataloğunda veri kümelerinin geri kalanını görüntüleme.