Rusça açık konuşmayı metne dönüştürme

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

Dekont

Microsoft, Azure Open Datasets'i "olduğu gibi" sağlar. Microsoft, veri kümelerini kullanımınızla ilgili olarak açık veya zımni hiçbir garanti veya koşul sağlamaz. Yerel yasalarınız kapsamında izin verilen ölçüde, Microsoft veri kümelerini kullanımınızdan kaynaklanan doğrudan, sonuçsal, özel, dolaylı, arızi veya cezai dahil olmak üzere tüm zarar veya kayıplar için tüm sorumluluğu kabul etmez.

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şmayı metne dönüştürme (STT) veri kümesi şunları içerir:

  • Yaklaşık 16 milyon konuşma
  • Yaklaşık 20.000 saat
  • 2.3 TB (int16'da .wav biçiminde sıkıştırılmamış), opus'ta 356G
  • Doğrulama veri kümeleri dışında tüm dosyalar opus'a 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

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

VERİ KÜMESİ KONUŞMALAR SAAT GB SECS/CHARS YORUM EK AÇIKLAMA KALITE/GÜRÜLTÜ
radio_v4 (*) 7.603.192 10.430 1.195 5 sn / 68 Radyo Align %95 / net
public_speech (*) 1.700.060 2.709 301 6 sn / 79 Genel konuşma Align %95 / net
audiobook_2 1.149.404 1.511 162 5 sn / 56 Defterler Align %95 / net
radio_2 651.645 1.439 154 8 sn / 110 Radyo Align %95 / net
public_youtube1120 1.410.979 1.104 237 3 sn / 34 YouTube Alt başlıklar %95 / ~net
public_youtube700 759.483 701 75 3 sn / 43 YouTube Alt başlıklar %95 / ~net
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 görüşmeleri ASR %70 / gürültülü
public_youtube1120_hq 369.245 291 31 3 sn / 37 YouTube HQ Alt başlıklar %95 / ~net
asr_public_phone_calls_1 233.868 211 23 3 sn / 29 Telefon görüşmeleri ASR %70 / gürültülü
radio_v4_add (*) 92.679 157 18 6 sn / 80 Radyo Align %95 / net
asr_public_stories_2 78.186 Kategori 78 9 4 sn / 43 Defterler ASR %80 / net
asr_public_stories_1 46.142 38 4 3 sn / 30 Defterler ASR %80 / net
public_series_1 20.243 17 2 3 sn / 38 YouTube Alt başlıklar %95 / ~net
asr_calls_2_val 12.950 7,7 2 2 sn / 34 Telefon görüşmeleri El ile ek açıklama %99 / net
public_lecture_1 6.803 6 1 3 sn / 47 Konuşmalar Alt başlıklar %95 / net
buriy_audiobooks_2_val 7.850 4,9 1 2 sn / 31 Defterler El ile ek açıklama %99 / net
public_youtube700_val 7.311 4,5 1 2 sn / 35 YouTube El ile ek açıklama %99 / net

(*) 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ürlerine otomatik olarak açıklama eklenir ve buluşsal yöntemler kullanılarak istatistiksel olarak doğrulanır.

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

Veri kümesinin toplam boyutu 350 GB'tır. Genel olarak paylaşılan etiketler içeren veri kümesinin toplam boyutu 130 GB'tır.

Geriye dönük uyumluluk için veri kümesinin güncelleştirilmesi olası değildir. Karşılaştırmalar için özgün depoyu izleyin ve dosyaları hariç tutun.

Gelecekte yeni etki alanları ve diller eklenebilir.

Ses normalleştirme

Tüm dosyalar daha kolay ve daha hızlı çalışma zamanı geliştirmeleri için normalleştirilir. İşleme aşağıdaki gibidir:

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

Karşıdan Yüklemeler

Veri kümesi iki biçimde sağlanır:

  • Azure blob depolama ve/veya doğrudan bağlantılar aracılığıyla kullanılabilen arşivler;
  • Azure blob depolama aracılığıyla kullanılabilen özgün dosyalar; Her şey 'https://azureopendatastorage.blob.core.windows.net/openstt/' içinde depolanı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
VERİ KÜMESİ GB, WAV GB, ARŞİV ARŞİV KAYNAK BİLDİRİM
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ümesini doğrudan indirme yönergeleri için GitHub indirme yönergeleri sayfasına bakın.

Ek bilgi

Veriler hakkında yardım veya sorular için adresinden veri yazarları ile iletişime geçin aveysov@gmail.com

Bu lisans, kullanıcıların malzemeyi yalnızca ticari olmayan amaçlarla ve yalnızca içerik oluşturucuya verildiği sürece herhangi bir ortamda veya biçimde dağıtmasına, karıştırmasına, uyarlamasına ve üzerine inşa etmesine olanak tanır. Bu, aşağıdaki öğeleri içerir:

  • BY – Krediyi oluşturana verilmelidir
  • NC – Yalnızca çalışmanın ticari olmayan kullanımlarına 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 oluşturma

Python'da önemli bir yük doğurmayan opus dosyalarını okumanın verimli bir yolu, pysoundfile (libsoundfile çevresinde python CFFI sarmalayıcı) kullanmaktır.

Opus desteği yukarı akışa uygulandı, ancak düzgün bir şekilde yayımlanmadı. Bu nedenle, özel derleme + maymun düzeltme eki uygulamayı seçtik.

Genellikle bunu sudo erişimiyle kabuğunuzda ç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

Bildirimler, 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ğunu kanıtladılar.

Kullanım kolaylığı için tüm bildirimler zaten yeniden köklenmiştir. İçlerindeki 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 yürütme

Dosya örneğini yürütme

Çoğu platform tarayıcısı yerel ses kayıttan yürütmeyi destekler. Böylece verilerimizi görüntülemek için HTML5 ses oynatıcıları 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 okumayı gösteren bazı örnekler.

Scipy, wav için en hızlı olandır. Pysoundfile, opus 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

Dalgalı 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)

Oku 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ğundaki diğer veri kümelerini görüntüleyin.