Yehor Smoliakov commited on
Commit
8cd0fcd
1 Parent(s): 7c981ca
Files changed (13) hide show
  1. .gitattributes +5 -27
  2. .gitignore +2 -0
  3. README.md +178 -7
  4. app.py +90 -0
  5. inference.py +68 -0
  6. inference_gpu.py +69 -0
  7. inference_timestamps.py +86 -0
  8. long_1.wav +3 -0
  9. mer_lviv_interview.wav +3 -0
  10. requirements.txt +12 -0
  11. short_1.wav +3 -0
  12. tsn.wav +3 -0
  13. tsn_2.wav +3 -0
.gitattributes CHANGED
@@ -1,27 +1,5 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ftz filter=lfs diff=lfs merge=lfs -text
6
- *.gz filter=lfs diff=lfs merge=lfs -text
7
- *.h5 filter=lfs diff=lfs merge=lfs -text
8
- *.joblib filter=lfs diff=lfs merge=lfs -text
9
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
10
- *.model filter=lfs diff=lfs merge=lfs -text
11
- *.msgpack filter=lfs diff=lfs merge=lfs -text
12
- *.onnx filter=lfs diff=lfs merge=lfs -text
13
- *.ot filter=lfs diff=lfs merge=lfs -text
14
- *.parquet filter=lfs diff=lfs merge=lfs -text
15
- *.pb filter=lfs diff=lfs merge=lfs -text
16
- *.pt filter=lfs diff=lfs merge=lfs -text
17
- *.pth filter=lfs diff=lfs merge=lfs -text
18
- *.rar filter=lfs diff=lfs merge=lfs -text
19
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
20
- *.tar.* filter=lfs diff=lfs merge=lfs -text
21
- *.tflite filter=lfs diff=lfs merge=lfs -text
22
- *.tgz filter=lfs diff=lfs merge=lfs -text
23
- *.wasm filter=lfs diff=lfs merge=lfs -text
24
- *.xz filter=lfs diff=lfs merge=lfs -text
25
- *.zip filter=lfs diff=lfs merge=lfs -text
26
- *.zstandard filter=lfs diff=lfs merge=lfs -text
27
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
1
+ tsn.wav filter=lfs diff=lfs merge=lfs -text
2
+ long_1.wav filter=lfs diff=lfs merge=lfs -text
3
+ mer_lviv_interview.wav filter=lfs diff=lfs merge=lfs -text
4
+ short_1.wav filter=lfs diff=lfs merge=lfs -text
5
+ tsn_2.wav filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ .idea/
2
+ .venv
README.md CHANGED
@@ -1,13 +1,184 @@
1
  ---
2
- title: Wav2vec2 Demo
3
- emoji: 🏢
4
- colorFrom: yellow
5
- colorTo: indigo
6
  sdk: gradio
7
- sdk_version: 2.9.4
8
  app_file: app.py
9
  pinned: false
10
- license: mit
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces#reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: Wav2vec2 Ukrainian with Timestamps
3
+ emoji: 🔥
4
+ colorFrom: blue
5
+ colorTo: yellow
6
  sdk: gradio
 
7
  app_file: app.py
8
  pinned: false
 
9
  ---
10
 
11
+
12
+ # Demo of Ukrainian wav2vec2 model
13
+
14
+ - The base model is hosted here: https://huggingface.co/Yehor/wav2vec2-xls-r-1b-uk-with-lm
15
+ - The model with better News LM: https://huggingface.co/Yehor/wav2vec2-xls-r-1b-uk-with-news-lm
16
+
17
+ Follow our community in Telegram: https://t.me/speech_recognition_uk
18
+
19
+ ---
20
+
21
+ Create a virtualenv:
22
+
23
+ ```bash
24
+ pipenv install
25
+ pipenv shell
26
+ ```
27
+
28
+ Install deps:
29
+
30
+ ```bash
31
+ pip install https://github.com/huggingface/transformers/archive/refs/tags/v4.16.2.zip
32
+ pip install https://github.com/kpu/kenlm/archive/master.zip
33
+
34
+ pip install torch==1.9.1 torchaudio==0.9.1 pyctcdecode==0.3.0
35
+ ```
36
+
37
+ Run inference:
38
+
39
+ ```bash
40
+ python inference.py --model_id Yehor/wav2vec2-xls-r-1b-uk-with-lm --path_files short_1.wav
41
+
42
+ # with chunking
43
+ python inference.py --model_id Yehor/wav2vec2-xls-r-1b-uk-with-lm --path_files short_1.wav --chunk_length_s 10 --stride_length_s_l 4 --stride_length_s_r 2
44
+ python inference.py --model_id Yehor/wav2vec2-xls-r-1b-uk-with-lm --path_files long_1.wav --chunk_length_s 10 --stride_length_s_l 4 --stride_length_s_r 2
45
+
46
+ # with chunking on GPU
47
+ python inference_gpu.py --model_id Yehor/wav2vec2-xls-r-1b-uk-with-lm --path_files short_1.wav --chunk_length_s 10 --stride_length_s_l 4 --stride_length_s_r 2
48
+ python inference_gpu.py --model_id Yehor/wav2vec2-xls-r-1b-uk-with-lm --path_files long_1.wav --chunk_length_s 10 --stride_length_s_l 4 --stride_length_s_r 2
49
+
50
+ python inference.py --model_id Yehor/wav2vec2-xls-r-1b-uk-with-news-lm --path_files mer_lviv_interview.wav --chunk_length_s 10 --stride_length_s_l 4 --stride_length_s_r 2
51
+ python inference_gpu.py --model_id Yehor/wav2vec2-xls-r-1b-uk-with-news-lm --path_files mer_lviv_interview.wav --chunk_length_s 10 --stride_length_s_l 4 --stride_length_s_r 2
52
+
53
+ python inference.py --model_id Yehor/wav2vec2-xls-r-1b-uk-with-lm --path_files tsn.wav,tsn_2.wav --chunk_length_s 10 --stride_length_s_l 4 --stride_length_s_r 2
54
+ ```
55
+
56
+ NOTE: Do the inference process for long files with chunking.
57
+
58
+ ---
59
+
60
+ short_1.wav:
61
+
62
+ ```
63
+ пана сполучені штати над важливий стратегічний партнер однак є різницяштати мають спеціальний закон який передбачає якщо китай напади на тайвань американський військові мають його захищати у гри
64
+ ```
65
+
66
+ short_1.wav (with better News LM):
67
+
68
+ ```
69
+ аня сполучені штати над важливий стратегічний партнер однак є різниця штати мають спеціальний закон який передбачає якщо китай нападе на тайвань американський військові мають його захищати угери
70
+ ```
71
+
72
+ long_1.wav:
73
+
74
+ ```
75
+ серце чи дивовижни порятунок мільйони людей фактично в прямому ефірі вже три доби спостерігають за спробамиамероканських рятувальникив дісттисколодя за пятирічне хлопя досі не зрозуміло чи вдастядістати його з тридцяти метрового провал живим про надзвичайно складну операцію що триває в цю мить я на есарчуккулояз який провалився пятирічнийраян ледь помітна діра в землі менше тридцяти сантиметріву діаметрі але в глиб вона тягнеться на тридцять два метро батьки шукали сина кілька один перед тим як зрозуміле він під землею коли він зник я молилися богупросила аби алагзбиріг мосина і його дістали з колодязь живим господихай йому та менше болить в тій ділі я так сподіваючиь що у рятувальники все вийде його неможливо витягти просто так розуміють рятувальники занадто вуськоа розширяти діру не можна вона просто завалитья тому вони три до бою розкопують амундалік і поки працює техніки
76
+ ```
77
+
78
+ long_1.wav (with News LM):
79
+
80
+ ```
81
+ серце чи дивовижних порятунок мільйони людей фактично в прямому ефірі вже три доби спостерігають за спробами мероканських рят��вальників дісттисколодя за пятирічне хлопя досі незрозуміло чи вдастся дістати його з тридцятиметрового провалля живим про надзвичайно складну операцію що триває в цю мить я не слісарчукодязв який провалився пятирічний раян ледь помітна діра в землі менше тридцяти сантиметрів у діаметрі але в глиб вона тягнеться на тридцять два метри батьки шукали сина кілька годин перед тим як зрозуміли він під землею а коли він зник я молилася богу просила аби алагбирігмо сина і його дістали сколотізяживим господи хай йому там менше болить в тій дірі і так сподіваючись що у рятувальники все вийде його неможливо витягти просто так розуміють рятувальників занадто вузько а розширяти діру не можна вона просто завалиться тому вони три добою розкопують амну далікі поки працює технік
82
+ ```
83
+
84
+ long_1.wav (with better News LM):
85
+
86
+ ```
87
+ серце чи дивовижний порятунок мільйони людей фактично в прямому ефірі вже три доби спостерігають за спробами мароканських рятувальників дісттисколодя за пятирічне хлопя досі незрозуміло чи вдастся дістати його з тридцятиметрового провалля живим про надзвичайно складну операцію що триває в цю мить я не слесарчукодязв який провалився пятирічний раян ледь помітна діра в землі менше тридцяти сантиметрів у діаметрі але в глиб вона тягнеться на тридцять два метри батьки шукали сина кілька годин перед тим як зрозуміли він під землею а коли він зник я молилася богу просила аби алаксбирігмо сина і його дістали сководізяживим господи хай йому там менше болить в тій тіріятак сподіваючись що у рятувальники все вийде його неможливо витягти просто так розуміють рятувальників занадто вузько а розширяти діру не можна вона просто завалиться тому вони три добою розкопують амнокдалік і поки працює технік
88
+ ```
89
+
90
+ tsn.wav (with better News LM):
91
+
92
+ ```
93
+ інформаційний вечір на один плюс один в студії та сем лідія таран а платонова королева з чого починалося і чим ще зовсім не закінчиться правління єлизавети другої сімдесят років на троні окмовівіполовні рішення щодо спадкоємців корони більше зараз усе
94
+ ```
95
+
96
+ tsn_2.wav (with better News LM):
97
+
98
+ ```
99
+ до осло зіли під час стрілянини на південмаші в жану влучили три кулі одна з них розірвала кишківник та хребет животі катастрофу розуміти три літри крові яку неможливо повернути тому що вона забруднена кишківник кинувши доз розірваний освітунавіть не котичекапо ужилася дуже активна проти дістала кулі просто на варті контрактниця відповідала за оповіщення частини про надзвичайні ситуації він був в двох кроках від вельми мовчки розстріляли що на посту була радіостанція і я запраз та могла доповісти частину військові ну я не змогла доповісти зробив постріли я вже не змогла підвестися стрілянина на південмаші сталася вночі двадцять сьомого січня пятеро людей загинули серед них одна цивільна ще пятро поранені підозрюваний двадцятирічний рокових артемірявчух у сі��о спочатку провину визнавав тепер і знову м адвокатами від показів відмовився ані конфліктних ситуації ані бо чого підозрілого жанна каже до стрілянини із підозрюваним навіть не розмовляла а тільки за памятала і оце а так я навіть його імені й фамілії не знав я дуже рідко заступала ці кару там де срочного служба я не можу знати чому він так зробив навпроти жани реанімації контрактник ігор самененко під час стрлянини відпочивав за графіком повороже забігаю тикрчишотамячу ксюш сумною наше
100
+ ```
101
+
102
+ mer_lviv_interview.wav:
103
+
104
+ ```
105
+ ми отримали нового керівника територіальної оборони області а це є фахова людина і з дурне міста ми переформотуваи наш управлінні звичайних ситуаії сьогодні воно має функцію назвичйнх ситуацівільного захист територіальної оборони і в нас достатньо якісна співпрая якісна координації тому що заначаміста допомогти державному фактично кірунку щоб він якісно за працював стосовно ремонти стосовно обладнання і стосовно рекрутенгу людей які зараз голошулися що би бути по контрактах в територіальної обороні на території міста любова на стврюються двбатаьони і наразі все йде чітко за тимланам які визначено державою натомість місто взяла на себе додатково функцію ми очали великий навчальний процес для працівників комунальних підприємсособливо мов для про стратегічне підприємства працівники виконавчий хоронні влади банально відновити навики володіння зброю в наших працівників люсважливи чиникце уміння надавати першу до медичну допомогу і за така велика хвиля яка після закінчення карантивно де включати і старшокласників ми на при великий жаль багато в остнніх років таке враження що перебували лютриному сні розуміючи що росія поруч і за ви буде центр можливо агресії нам треба вишколювати себе і бути готовими до того щоб захищати рідну державу якщо кожен українець буде добре володіти навиками стрилецької зброї буде вміти надавати мдичну допомогу в бимене це потужна сила яку неможливо здолати тому в координації з державу і рухаємося вперед ще таке питання оту нас багато кажуть що поруч і бригада ми сил тертральо оборони можуть стврюватися і формуватися доровольчі обєднання чи у вслвові це передбачено і як ваше ставлення до такого віце ми працюємо в чуткійкоординації з державними інституціями і на сьогоднішній день я не бачу потреби в інших формування х тому що принципі має бути жорстка вертикально має бути один центр правління сла обогощо є новий командувач територіальної оборони рамках держави керівник штабоновий принципі пан у то який в нас у чули територіальну орону області на це дуже фахова компетентна людина з ним просто рємно сів працювати в не розуміє все співслов законом передбачена можливість прикидання в разі такої нагальної потреби перекидання бригада сил територіальної оборони в зонобоєвихді вічі області яке ваше ставл��нндоцього і можливо вам відомо яке можливо ставлення у самих сів територіальної оборони віці на сьогоднішній день ми розуміємо що він форційному плані треба зробити титанічниобєм праці людям треба пояснити що ти не можеш сховатисяу власному помешкані коли прийде ворог ворога треба не пустити на території нашої країни і я думаю що всі громадяни повинні мати готовнізахи щати свої рідну крїну на сьогоднішній день йде нормальний процес люди записується дуже багато відомелюдей записуся в територіальну оборону я вважаю це правильно тому що треба мати таки висів а стосовно всіх інших речей ще раз наголошую коли мова йде про безпеку про оборону держави має бути субординація і є чітка державна вертикальтреба захищати будемо сі разом захищати нема наторадиа ще одне питання багато хто впеонийщо законіне достатньо влади про писано для місцеве адміністрації влдимається на увазі повноважень і можливості при формуванні розгортанні сил тоеитрально оборони ви на практиці зіткнулися вже цим і як ви оцінюють ся це ну по перше добре що закон є звичайно що од жоден закон не є та обтальний чи ідеальний він мав би процесі реально життя за знати певних крягувань у наприклад керівником териріальной оборони в часі на звичайної ситуації є голова обласної адміністрації так а по місто любово наприклад керівником є керівник районної адміністрації це є не великий офісі є декілька працівників і вони мали би стояти над громади міста льоа я не думаю що це буде мати достатню якісний ефект тому що принцип є крівникобласті я керівник мста але ці речі напевно коли писали закон не до кінця прраховували але ми маємо час щоб це поправити але на сьогодні ми чітко викониозакни який є інших варіантів не може бути пане андріюбуквально остання запитнняваша бригада тлвівськану два батальйон як викрити як вони зараз озброєні повністю чи ніч це тільки стрилецьке збрїчице й більш важке озброєнн і як в ставитиь до того щоб міськдністрація мала можливістькажімо щось купувати для забзпечення саме си тртріальоорон у на приклад ті ж самі виспілотники для розвідки або засоби звязку а або ось щось таке ну що ви розуміли ми достатньо багато помагаємо всім нашим військовим частинам батальоам це робили вчорастобупі татом у кожного року якщо говорити про сили територіальну оборони області ми допоможе мо усім чим буде потрібно мова про гроші не йде ми не профінансуємо ремонту чи іншої вулиці а нашим хлопцям до поможемо і це має робити кона громада і кожен лідер гмади в нашій країні
106
+ ```
107
+
108
+ mer_lviv_interview.wav (with better News LM):
109
+
110
+ ```
111
+ ми отримали нового керівника територіальної оборони області а це є фахова людина і з турне міста ми переформатували наше управління звичайних ситуаії сьогодні воно має функцію надзвичйних ситуацї цівільного захист територіальної оборони і в нас достатньо якісна співпраця якісна ко��рдинація тому що задача міста допомогти державному фактично керунку щоб він якісно запрацював стосовно ремонті стосовно обладнання і стосовно рекрутингу людей які зараз зголошувалися щоби бути по контрактах в територіальній обороні на території міста любова на стврюються батальони і наразі все йде чітко за тим ланом які визначеної державою натомість місто взяло на себе додаткову функцію ми очали великий навчальний процес для працівників комунальних підприємстособливо мов для про стратегічні підприємства працівники виконавчий хорані влади банально відновити навики володіння зброєю в наших працівників плюс важливий чинник це уміння надавати першу домедичну допомогу і за така велика хвиля яка після закінчення карантивно буде включати і старшокласників ми напривеликий жаль багато в останніх років таке враження що перебували літориномусні розуміючи що росія поруч і за вибуде центр можливо агресії нам треба вишколювати себе і бути готовими до того щоб захищати рідну державу якщо кожен українець буде добре володіти навиками стрілецької зброї буде вміти надавати м дичну допомогу в имени це потужна сила яку неможливо здолати тому в координації з державу і рухаємося вперед ще таке питання от у нас багато кажуть що поруч із бригадами сил тертральооборони можуть стврюватися і формуватися добровольчі обєднання чи уволвові це передбачено як ваше ставлення до такого віце ми працюємо в чіткийкординації з державними інституціями і на сьогоднішній день я не бачу потреби в інших формуваннях тому що в принципі має бути жорстка вертикаль має бути один центр управління сла обо що є новий командувач територіальної оборони в рамках держави керівник шабанови принципі пану то які в нас учули територіальну орон області на це дуже фахова компетентна людина з ним просто приємно співпрацювати не розуміє все співслова законом передбачена можливість перекидання в разі такої нагальної потреби перекидання бригад сил територіальної оборони в зону бойових дій віншіобласті яке ваше ставленн до цього і можливо вам відомо яке можливо ставлення рсу самих бійців територіальної оборони від це на сьогоднішній день ми розуміємо що вінформаційному плані треба зробити титанічний обєм праці людям треба пояснити що ти не можеш сховатися у власному помешканні коли прийде ворог ворога треба не пустити на територію нашої країни і я думаю що всі громадяни повинні мати готовні захищати свою рідну крїну на сьогоднішній день йде нормальний процес люди записується дуже багато відоме людей записується в територіальну оборону я вважаю це правильно тому що треба мати такі вишкіл а стосовно всіх інших речей ще раз наголошую коли мова йде про безпеку про оборону держави має бути субординація і є чітка державна вертикаль треба захищати будемо сі разом захищати нема на то ради а ��е одне питання багато хто впевнений що в законі недостатньо влади прописано для місцевих д міністрації влди мається на увазі повноважень і можлвостпри формуванні розгортанні сил ториторіально оборони ви на практиці зіткнулися вже цим і як ви оцінюютьсяцену поперше добре що закон є звичайно що жододенззаон не є та обтальний чи ідеальний він мав би процесі реально життя зазнати певних коригувань ну наприклад керівником териріальной оборони в часі на звичайної ситуації є голова обласної адміністрації так а по місту любовонаприклад керівником є керівник районної адміністрації це є невеликий офіс нехедекілька працівників і вони мали би стояти над громадою міста львова я не думаю що це буде мати достатню якісний ефект тому що принцип є керівникобласті керівни мста але ці речі напевно коли писали закон не до кінця раховували але ми маємо час щоб це поправити але на сьогодні ми чітко викониозакни який є іншхварянтів не може буде пане андрію буквально остання запитння ваша бригада львівська ну два батальйони як викрита як вони зараз озброєні повністю чи ніч це тільки стрілецьке збря чи це й більш важке озброєння і як в ставитись до того щоб міськдістрація мала можливістькажімо щось купувати для забзпечення саме си тртіальоорони ну наприклад ті ж самі беспілотники для розвідки або засоби звязку а або ось щось таке ну щоб ви розуміли ми достатньо багато помагаємо всім нашим військовим частинам батальонам це робили читерастобу питатиму кожного року якщо говорити про сили територіально оборони області ми допоможемо усім чим буде потрібно мова про гроші не йде ми не профінансуємо ремонтуючи іншої вулиці а нашим хлопцям допоможемо і це має робити кона громада і кожен лідер гомади в нашій країні
112
+ ```
113
+
114
+ ### Inference of `mer_lviv_interview.wav` (time is 06:38)
115
+
116
+ #### CPU
117
+
118
+ - Memory peaks to 60GB
119
+ - Memory peaks to 65GB (on News LM)
120
+
121
+ Inference duration:
122
+
123
+ ```
124
+ real 7m39.461s
125
+ user 59m19.065s
126
+ sys 24m1.254s
127
+ ```
128
+
129
+ Inference duration (on News LM):
130
+
131
+ ```
132
+ real 12m36.888s
133
+ user 63m19.396s
134
+ sys 24m24.823s
135
+ ```
136
+
137
+ Duration tracked with loading the LM.
138
+
139
+ ## Using timestamps
140
+
141
+ The `inference_timestamps.py` script can be used to do inference with timestamps for chars and words.
142
+
143
+ ### `output_char_offsets=True`
144
+
145
+ ```
146
+ Wav2Vec2CTCTokenizerOutput(text='паня сполучені штати надважливий стратегічний партнер однак є різниця штати мають спеціальни закон який передбачає якщо китай нападе на тайвань американський військові мають його захищати евуйвгере', char_offsets=[{'char': 'п', 'start_offset': 0, 'end_offset': 1}, {'char': 'а', 'start_offset': 1, 'end_offset': 2}, {'char': 'н', 'start_offset': 9, 'end_offset': 10}, {'char': 'я', 'start_offset': 11, 'end_offset': 12}, {'char': ' ', 'start_offset': 14, 'end_offset': 15}, {'char': 'с', 'start_offset': 16, 'end_offset': 17}, {'char': 'п', 'start_offset': 19, 'end_offset': 20}, {'char': 'о', 'start_offset': 21, 'end_offset': 22}, {'char': 'л', 'start_offset': 23, 'end_offset': 24}, {'char': 'у', 'start_offset': 25, 'end_offset': 26}, {'char': 'ч', 'start_offset': 30, 'end_offset': 31}, {'char': 'е', 'start_offset': 32, 'end_offset': 33}, {'char': 'н', 'start_offset': 37, 'end_offset': 38}, {'char': 'і', 'start_offset': 38, 'end_offset': 39}, {'char': ' ', 'start_offset': 40, 'end_offset': 42}, {'char': 'ш', 'start_offset': 43, 'end_offset': 44}, {'char': 'т', 'start_offset': 46, 'end_offset': 47}, {'char': 'а', 'start_offset': 48, 'end_offset': 49}, {'char': 'т', 'start_offset': 57, 'end_offset': 58}, {'char': 'и', 'start_offset': 58, 'end_offset': 59}, {'char': ' ', 'start_offset': 76, 'end_offset': 79}, {'char': 'н', 'start_offset': 85, 'end_offset': 86}, {'char': 'а', 'start_offset': 87, 'end_offset': 88}, {'char': 'д', 'start_offset': 93, 'end_offset': 94}, {'char': 'в', 'start_offset': 97, 'end_offset': 98}, {'char': 'а', 'start_offset': 99, 'end_offset': 100}, {'char': 'ж', 'start_offset': 105, 'end_offset': 106}, {'char': 'л', 'start_offset': 113, 'end_offset': 114}, {'char': 'и', 'start_offset': 114, 'end_offset': 115}, {'char': 'в', 'start_offset': 121, 'end_offset': 122}, {'char': 'и', 'start_offset': 123, 'end_offset': 124}, {'char': 'й', 'start_offset': 125, 'end_offset': 126}, {'char': ' ', 'start_offset': 127, 'end_offset': 129}, {'char': 'с', 'start_offset': 130, 'end_offset': 131}, {'char': 'т', 'start_offset': 134, 'end_offset': 136}, {'char': 'р', 'start_offset': 138, 'end_offset': 139}, {'char': 'а', 'start_offset': 139, 'end_offset': 140}, {'char': 'т', 'start_offset': 145, 'end_offset': 146}, {'char': 'е', 'start_offset': 146, 'end_offset': 147}, {'char': 'г', 'start_offset': 152, 'end_offset': 153}, {'char': 'і', 'start_offset': 153, 'end_offset': 154}, {'char': 'ч', 'start_offset': 160, 'end_offset': 161}, {'char': 'н', 'start_offset': 167, 'end_offset': 168}, {'char': 'и', 'start_offset': 168, 'end_offset': 169}, {'char': 'й', 'start_offset': 170, 'end_offset': 171}, {'char': ' ', 'start_offset': 171, 'end_offset': 173}, {'char': 'п', 'start_offset': 174, 'end_offset': 175}, {'char': 'а', 'start_offset': 176, 'end_offset': 177}, {'char': 'р', 'start_offset': 179, 'end_offset': 180}, {'char': 'т', 'start_offset': 183, 'end_offset': 184}, {'char': 'н', 'start_offset': 188, 'end_offset': 189}, {'char': 'е', 'start_offset': 189, 'end_offset': 190}, {'char': 'р', 'start_offset': 193, 'end_offset': 194}, {'char': ' ', 'start_offset': 201, 'end_offset': 203}, {'char': 'о', 'start_offset': 204, 'end_offset': 205}, {'char': 'д', 'start_offset': 208, 'end_offset': 209}, {'char': 'н', 'start_offset': 214, 'end_offset': 216}, {'char': 'а', 'start_offset': 216, 'end_offset': 217}, {'char': 'к', 'start_offset': 224, 'end_offset': 225}, {'char': ' ', 'start_offset': 227, 'end_offset': 229}, {'char': 'є', 'start_offset': 233, 'end_offset': 234}, {'char': ' ', 'start_offset': 237, 'end_offset': 239}, {'char': 'р', 'start_offset': 240, 'end_offset': 241}, {'char': 'і', 'start_offset': 241, 'end_offset': 242}, {'char': 'з', 'start_offset': 247, 'end_offset': 248}, {'char': 'н', 'start_offset': 253, 'end_offset': 254}, {'char': 'и', 'start_offset': 254, 'end_offset': 255}, {'char': 'ц', 'start_offset': 261, 'end_offset': 262}, {'char': 'я', 'start_offset': 262, 'end_offset': 263}, {'char': ' ', 'start_offset': 281, 'end_offset': 283}, {'char': 'ш', 'start_offset': 283, 'end_offset': 284}, {'char': 'т', 'start_offset': 286, 'end_offset': 287}, {'char': 'а', 'start_offset': 288, 'end_offset': 289}, {'char': 'т', 'start_offset': 294, 'end_offset': 295}, {'char': 'и', 'start_offset': 296, 'end_offset': 297}, {'char': ' ', 'start_offset': 297, 'end_offset': 299}, {'char': 'м', 'start_offset': 300, 'end_offset': 301}, {'char': 'а', 'start_offset': 301, 'end_offset': 302}, {'char': 'ю', 'start_offset': 306, 'end_offset': 307}, {'char': 'т', 'start_offset': 308, 'end_offset': 309}, {'char': 'ь', 'start_offset': 309, 'end_offset': 311}, {'char': ' ', 'start_offset': 311, 'end_offset': 313}, {'char': 'с', 'start_offset': 313, 'end_offset': 314}, {'char': 'п', 'start_offset': 316, 'end_offset': 317}, {'char': 'е', 'start_offset': 318, 'end_offset': 319}, {'char': 'ц', 'start_offset': 324, 'end_offset': 325}, {'char': 'і', 'start_offset': 325, 'end_offset': 326}, {'char': 'а', 'start_offset': 328, 'end_offset': 329}, {'char': 'л', 'start_offset': 333, 'end_offset': 334}, {'char': 'ь', 'start_offset': 334, 'end_offset': 336}, {'char': 'н', 'start_offset': 339, 'end_offset': 340}, {'char': 'и', 'start_offset': 341, 'end_offset': 342}, {'char': ' ', 'start_offset': 345, 'end_offset': 348}, {'char': 'з', 'start_offset': 351, 'end_offset': 352}, {'char': 'а', 'start_offset': 354, 'end_offset': 355}, {'char': 'к', 'start_offset': 361, 'end_offset': 362}, {'char': 'о', 'start_offset': 365, 'end_offset': 366}, {'char': 'н', 'start_offset': 373, 'end_offset': 374}, {'char': ' ', 'start_offset': 382, 'end_offset': 384}, {'char': 'я', 'start_offset': 386, 'end_offset': 387}, {'char': 'к', 'start_offset': 390, 'end_offset': 391}, {'char': 'и', 'start_offset': 392, 'end_offset': 393}, {'char': 'й', 'start_offset': 394, 'end_offset': 395}, {'char': ' ', 'start_offset': 396, 'end_offset': 398}, {'char': 'п', 'start_offset': 399, 'end_offset': 401}, {'char': 'е', 'start_offset': 402, 'end_offset': 403}, {'char': 'р', 'start_offset': 406, 'end_offset': 407}, {'char': 'е', 'start_offset': 407, 'end_offset': 408}, {'char': 'д', 'start_offset': 411, 'end_offset': 412}, {'char': 'б', 'start_offset': 415, 'end_offset': 416}, {'char': 'а', 'start_offset': 416, 'end_offset': 417}, {'char': 'ч', 'start_offset': 424, 'end_offset': 425}, {'char': 'а', 'start_offset': 428, 'end_offset': 429}, {'char': 'є', 'start_offset': 437, 'end_offset': 438}, {'char': ' ', 'start_offset': 445, 'end_offset': 447}, {'char': 'я', 'start_offset': 448, 'end_offset': 449}, {'char': 'к', 'start_offset': 452, 'end_offset': 453}, {'char': 'щ', 'start_offset': 455, 'end_offset': 456}, {'char': 'о', 'start_offset': 457, 'end_offset': 458}, {'char': ' ', 'start_offset': 460, 'end_offset': 463}, {'char': 'к', 'start_offset': 463, 'end_offset': 464}, {'char': 'и', 'start_offset': 465, 'end_offset': 466}, {'char': 'т', 'start_offset': 470, 'end_offset': 471}, {'char': 'а', 'start_offset': 472, 'end_offset': 473}, {'char': 'й', 'start_offset': 478, 'end_offset': 480}, {'char': ' ', 'start_offset': 484, 'end_offset': 486}, {'char': 'н', 'start_offset': 487, 'end_offset': 488}, {'char': 'а', 'start_offset': 488, 'end_offset': 489}, {'char': 'п', 'start_offset': 493, 'end_offset': 494}, {'char': 'а', 'start_offset': 496, 'end_offset': 497}, {'char': 'д', 'start_offset': 502, 'end_offset': 503}, {'char': 'е', 'start_offset': 504, 'end_offset': 505}, {'char': ' ', 'start_offset': 509, 'end_offset': 511}, {'char': 'н', 'start_offset': 511, 'end_offset': 512}, {'char': 'а', 'start_offset': 513, 'end_offset': 514}, {'char': ' ', 'start_offset': 515, 'end_offset': 517}, {'char': 'т', 'start_offset': 518, 'end_offset': 519}, {'char': 'а', 'start_offset': 519, 'end_offset': 520}, {'char': 'й', 'start_offset': 524, 'end_offset': 525}, {'char': 'в', 'start_offset': 527, 'end_offset': 528}, {'char': 'а', 'start_offset': 529, 'end_offset': 530}, {'char': 'н', 'start_offset': 535, 'end_offset': 536}, {'char': 'ь', 'start_offset': 536, 'end_offset': 537}, {'char': ' ', 'start_offset': 552, 'end_offset': 555}, {'char': 'а', 'start_offset': 555, 'end_offset': 556}, {'char': 'м', 'start_offset': 561, 'end_offset': 562}, {'char': 'е', 'start_offset': 562, 'end_offset': 563}, {'char': 'р', 'start_offset': 566, 'end_offset': 567}, {'char': 'и', 'start_offset': 567, 'end_offset': 568}, {'char': 'к', 'start_offset': 572, 'end_offset': 573}, {'char': 'а', 'start_offset': 574, 'end_offset': 575}, {'char': 'н', 'start_offset': 579, 'end_offset': 580}, {'char': 'с', 'start_offset': 582, 'end_offset': 583}, {'char': 'ь', 'start_offset': 583, 'end_offset': 585}, {'char': 'к', 'start_offset': 586, 'end_offset': 587}, {'char': 'и', 'start_offset': 588, 'end_offset': 589}, {'char': 'й', 'start_offset': 589, 'end_offset': 590}, {'char': ' ', 'start_offset': 591, 'end_offset': 593}, {'char': 'в', 'start_offset': 594, 'end_offset': 595}, {'char': 'і', 'start_offset': 595, 'end_offset': 596}, {'char': 'й', 'start_offset': 600, 'end_offset': 601}, {'char': 'с', 'start_offset': 604, 'end_offset': 605}, {'char': 'ь', 'start_offset': 605, 'end_offset': 607}, {'char': 'к', 'start_offset': 609, 'end_offset': 611}, {'char': 'о', 'start_offset': 612, 'end_offset': 613}, {'char': 'в', 'start_offset': 620, 'end_offset': 621}, {'char': 'і', 'start_offset': 622, 'end_offset': 623}, {'char': ' ', 'start_offset': 637, 'end_offset': 639}, {'char': 'м', 'start_offset': 641, 'end_offset': 642}, {'char': 'а', 'start_offset': 643, 'end_offset': 644}, {'char': 'ю', 'start_offset': 651, 'end_offset': 652}, {'char': 'т', 'start_offset': 654, 'end_offset': 655}, {'char': 'ь', 'start_offset': 655, 'end_offset': 656}, {'char': ' ', 'start_offset': 657, 'end_offset': 659}, {'char': 'й', 'start_offset': 659, 'end_offset': 660}, {'char': 'о', 'start_offset': 660, 'end_offset': 662}, {'char': 'г', 'start_offset': 664, 'end_offset': 665}, {'char': 'о', 'start_offset': 666, 'end_offset': 667}, {'char': ' ', 'start_offset': 677, 'end_offset': 679}, {'char': 'з', 'start_offset': 681, 'end_offset': 682}, {'char': 'а', 'start_offset': 683, 'end_offset': 684}, {'char': 'х', 'start_offset': 686, 'end_offset': 687}, {'char': 'и', 'start_offset': 689, 'end_offset': 690}, {'char': 'щ', 'start_offset': 696, 'end_offset': 697}, {'char': 'а', 'start_offset': 698, 'end_offset': 699}, {'char': 'т', 'start_offset': 707, 'end_offset': 708}, {'char': 'и', 'start_offset': 709, 'end_offset': 710}, {'char': ' ', 'start_offset': 733, 'end_offset': 734}, {'char': 'е', 'start_offset': 740, 'end_offset': 741}, {'char': 'в', 'start_offset': 747, 'end_offset': 748}, {'char': 'у', 'start_offset': 748, 'end_offset': 749}, {'char': 'й', 'start_offset': 752, 'end_offset': 753}, {'char': 'в', 'start_offset': 754, 'end_offset': 755}, {'char': 'г', 'start_offset': 757, 'end_offset': 758}, {'char': 'е', 'start_offset': 759, 'end_offset': 760}, {'char': 'р', 'start_offset': 767, 'end_offset': 768}, {'char': 'е', 'start_offset': 768, 'end_offset': 769}], word_offsets=None)
147
+ ```
148
+
149
+ ### `output_word_offsets=True`
150
+
151
+ ```
152
+ Wav2Vec2CTCTokenizerOutput(text='паня сполучені штати надважливий стратегічний партнер однак є різниця штати мають спеціальни закон я��ий передбачає якщо китай нападе на тайвань американський військові мають його захищати евуйвгере', char_offsets=[{'char': 'п', 'start_offset': 0, 'end_offset': 1}, {'char': 'а', 'start_offset': 1, 'end_offset': 2}, {'char': 'н', 'start_offset': 9, 'end_offset': 10}, {'char': 'я', 'start_offset': 11, 'end_offset': 12}, {'char': ' ', 'start_offset': 14, 'end_offset': 15}, {'char': 'с', 'start_offset': 16, 'end_offset': 17}, {'char': 'п', 'start_offset': 19, 'end_offset': 20}, {'char': 'о', 'start_offset': 21, 'end_offset': 22}, {'char': 'л', 'start_offset': 23, 'end_offset': 24}, {'char': 'у', 'start_offset': 25, 'end_offset': 26}, {'char': 'ч', 'start_offset': 30, 'end_offset': 31}, {'char': 'е', 'start_offset': 32, 'end_offset': 33}, {'char': 'н', 'start_offset': 37, 'end_offset': 38}, {'char': 'і', 'start_offset': 38, 'end_offset': 39}, {'char': ' ', 'start_offset': 40, 'end_offset': 42}, {'char': 'ш', 'start_offset': 43, 'end_offset': 44}, {'char': 'т', 'start_offset': 46, 'end_offset': 47}, {'char': 'а', 'start_offset': 48, 'end_offset': 49}, {'char': 'т', 'start_offset': 57, 'end_offset': 58}, {'char': 'и', 'start_offset': 58, 'end_offset': 59}, {'char': ' ', 'start_offset': 76, 'end_offset': 79}, {'char': 'н', 'start_offset': 85, 'end_offset': 86}, {'char': 'а', 'start_offset': 87, 'end_offset': 88}, {'char': 'д', 'start_offset': 93, 'end_offset': 94}, {'char': 'в', 'start_offset': 97, 'end_offset': 98}, {'char': 'а', 'start_offset': 99, 'end_offset': 100}, {'char': 'ж', 'start_offset': 105, 'end_offset': 106}, {'char': 'л', 'start_offset': 113, 'end_offset': 114}, {'char': 'и', 'start_offset': 114, 'end_offset': 115}, {'char': 'в', 'start_offset': 121, 'end_offset': 122}, {'char': 'и', 'start_offset': 123, 'end_offset': 124}, {'char': 'й', 'start_offset': 125, 'end_offset': 126}, {'char': ' ', 'start_offset': 127, 'end_offset': 129}, {'char': 'с', 'start_offset': 130, 'end_offset': 131}, {'char': 'т', 'start_offset': 134, 'end_offset': 136}, {'char': 'р', 'start_offset': 138, 'end_offset': 139}, {'char': 'а', 'start_offset': 139, 'end_offset': 140}, {'char': 'т', 'start_offset': 145, 'end_offset': 146}, {'char': 'е', 'start_offset': 146, 'end_offset': 147}, {'char': 'г', 'start_offset': 152, 'end_offset': 153}, {'char': 'і', 'start_offset': 153, 'end_offset': 154}, {'char': 'ч', 'start_offset': 160, 'end_offset': 161}, {'char': 'н', 'start_offset': 167, 'end_offset': 168}, {'char': 'и', 'start_offset': 168, 'end_offset': 169}, {'char': 'й', 'start_offset': 170, 'end_offset': 171}, {'char': ' ', 'start_offset': 171, 'end_offset': 173}, {'char': 'п', 'start_offset': 174, 'end_offset': 175}, {'char': 'а', 'start_offset': 176, 'end_offset': 177}, {'char': 'р', 'start_offset': 179, 'end_offset': 180}, {'char': 'т', 'start_offset': 183, 'end_offset': 184}, {'char': 'н', 'start_offset': 188, 'end_offset': 189}, {'char': 'е', 'start_offset': 189, 'end_offset': 190}, {'char': 'р', 'start_offset': 193, 'end_offset': 194}, {'char': ' ', 'start_offset': 201, 'end_offset': 203}, {'char': 'о', 'start_offset': 204, 'end_offset': 205}, {'char': 'д', 'start_offset': 208, 'end_offset': 209}, {'char': 'н', 'start_offset': 214, 'end_offset': 216}, {'char': 'а', 'start_offset': 216, 'end_offset': 217}, {'char': 'к', 'start_offset': 224, 'end_offset': 225}, {'char': ' ', 'start_offset': 227, 'end_offset': 229}, {'char': 'є', 'start_offset': 233, 'end_offset': 234}, {'char': ' ', 'start_offset': 237, 'end_offset': 239}, {'char': 'р', 'start_offset': 240, 'end_offset': 241}, {'char': 'і', 'start_offset': 241, 'end_offset': 242}, {'char': 'з', 'start_offset': 247, 'end_offset': 248}, {'char': 'н', 'start_offset': 253, 'end_offset': 254}, {'char': 'и', 'start_offset': 254, 'end_offset': 255}, {'char': 'ц', 'start_offset': 261, 'end_offset': 262}, {'char': 'я', 'start_offset': 262, 'end_offset': 263}, {'char': ' ', 'start_offset': 281, 'end_offset': 283}, {'char': 'ш', 'start_offset': 283, 'end_offset': 284}, {'char': 'т', 'start_offset': 286, 'end_offset': 287}, {'char': 'а', 'start_offset': 288, 'end_offset': 289}, {'char': 'т', 'start_offset': 294, 'end_offset': 295}, {'char': 'и', 'start_offset': 296, 'end_offset': 297}, {'char': ' ', 'start_offset': 297, 'end_offset': 299}, {'char': 'м', 'start_offset': 300, 'end_offset': 301}, {'char': 'а', 'start_offset': 301, 'end_offset': 302}, {'char': 'ю', 'start_offset': 306, 'end_offset': 307}, {'char': 'т', 'start_offset': 308, 'end_offset': 309}, {'char': 'ь', 'start_offset': 309, 'end_offset': 311}, {'char': ' ', 'start_offset': 311, 'end_offset': 313}, {'char': 'с', 'start_offset': 313, 'end_offset': 314}, {'char': 'п', 'start_offset': 316, 'end_offset': 317}, {'char': 'е', 'start_offset': 318, 'end_offset': 319}, {'char': 'ц', 'start_offset': 324, 'end_offset': 325}, {'char': 'і', 'start_offset': 325, 'end_offset': 326}, {'char': 'а', 'start_offset': 328, 'end_offset': 329}, {'char': 'л', 'start_offset': 333, 'end_offset': 334}, {'char': 'ь', 'start_offset': 334, 'end_offset': 336}, {'char': 'н', 'start_offset': 339, 'end_offset': 340}, {'char': 'и', 'start_offset': 341, 'end_offset': 342}, {'char': ' ', 'start_offset': 345, 'end_offset': 348}, {'char': 'з', 'start_offset': 351, 'end_offset': 352}, {'char': 'а', 'start_offset': 354, 'end_offset': 355}, {'char': 'к', 'start_offset': 361, 'end_offset': 362}, {'char': 'о', 'start_offset': 365, 'end_offset': 366}, {'char': 'н', 'start_offset': 373, 'end_offset': 374}, {'char': ' ', 'start_offset': 382, 'end_offset': 384}, {'char': 'я', 'start_offset': 386, 'end_offset': 387}, {'char': 'к', 'start_offset': 390, 'end_offset': 391}, {'char': 'и', 'start_offset': 392, 'end_offset': 393}, {'char': 'й', 'start_offset': 394, 'end_offset': 395}, {'char': ' ', 'start_offset': 396, 'end_offset': 398}, {'char': 'п', 'start_offset': 399, 'end_offset': 401}, {'char': 'е', 'start_offset': 402, 'end_offset': 403}, {'char': 'р', 'start_offset': 406, 'end_offset': 407}, {'char': 'е', 'start_offset': 407, 'end_offset': 408}, {'char': 'д', 'start_offset': 411, 'end_offset': 412}, {'char': 'б', 'start_offset': 415, 'end_offset': 416}, {'char': 'а', 'start_offset': 416, 'end_offset': 417}, {'char': 'ч', 'start_offset': 424, 'end_offset': 425}, {'char': 'а', 'start_offset': 428, 'end_offset': 429}, {'char': 'є', 'start_offset': 437, 'end_offset': 438}, {'char': ' ', 'start_offset': 445, 'end_offset': 447}, {'char': 'я', 'start_offset': 448, 'end_offset': 449}, {'char': 'к', 'start_offset': 452, 'end_offset': 453}, {'char': 'щ', 'start_offset': 455, 'end_offset': 456}, {'char': 'о', 'start_offset': 457, 'end_offset': 458}, {'char': ' ', 'start_offset': 460, 'end_offset': 463}, {'char': 'к', 'start_offset': 463, 'end_offset': 464}, {'char': 'и', 'start_offset': 465, 'end_offset': 466}, {'char': 'т', 'start_offset': 470, 'end_offset': 471}, {'char': 'а', 'start_offset': 472, 'end_offset': 473}, {'char': 'й', 'start_offset': 478, 'end_offset': 480}, {'char': ' ', 'start_offset': 484, 'end_offset': 486}, {'char': 'н', 'start_offset': 487, 'end_offset': 488}, {'char': 'а', 'start_offset': 488, 'end_offset': 489}, {'char': 'п', 'start_offset': 493, 'end_offset': 494}, {'char': 'а', 'start_offset': 496, 'end_offset': 497}, {'char': 'д', 'start_offset': 502, 'end_offset': 503}, {'char': 'е', 'start_offset': 504, 'end_offset': 505}, {'char': ' ', 'start_offset': 509, 'end_offset': 511}, {'char': 'н', 'start_offset': 511, 'end_offset': 512}, {'char': 'а', 'start_offset': 513, 'end_offset': 514}, {'char': ' ', 'start_offset': 515, 'end_offset': 517}, {'char': 'т', 'start_offset': 518, 'end_offset': 519}, {'char': 'а', 'start_offset': 519, 'end_offset': 520}, {'char': 'й', 'start_offset': 524, 'end_offset': 525}, {'char': 'в', 'start_offset': 527, 'end_offset': 528}, {'char': 'а', 'start_offset': 529, 'end_offset': 530}, {'char': 'н', 'start_offset': 535, 'end_offset': 536}, {'char': 'ь', 'start_offset': 536, 'end_offset': 537}, {'char': ' ', 'start_offset': 552, 'end_offset': 555}, {'char': 'а', 'start_offset': 555, 'end_offset': 556}, {'char': 'м', 'start_offset': 561, 'end_offset': 562}, {'char': 'е', 'start_offset': 562, 'end_offset': 563}, {'char': 'р', 'start_offset': 566, 'end_offset': 567}, {'char': 'и', 'start_offset': 567, 'end_offset': 568}, {'char': 'к', 'start_offset': 572, 'end_offset': 573}, {'char': 'а', 'start_offset': 574, 'end_offset': 575}, {'char': 'н', 'start_offset': 579, 'end_offset': 580}, {'char': 'с', 'start_offset': 582, 'end_offset': 583}, {'char': 'ь', 'start_offset': 583, 'end_offset': 585}, {'char': 'к', 'start_offset': 586, 'end_offset': 587}, {'char': 'и', 'start_offset': 588, 'end_offset': 589}, {'char': 'й', 'start_offset': 589, 'end_offset': 590}, {'char': ' ', 'start_offset': 591, 'end_offset': 593}, {'char': 'в', 'start_offset': 594, 'end_offset': 595}, {'char': 'і', 'start_offset': 595, 'end_offset': 596}, {'char': 'й', 'start_offset': 600, 'end_offset': 601}, {'char': 'с', 'start_offset': 604, 'end_offset': 605}, {'char': 'ь', 'start_offset': 605, 'end_offset': 607}, {'char': 'к', 'start_offset': 609, 'end_offset': 611}, {'char': 'о', 'start_offset': 612, 'end_offset': 613}, {'char': 'в', 'start_offset': 620, 'end_offset': 621}, {'char': 'і', 'start_offset': 622, 'end_offset': 623}, {'char': ' ', 'start_offset': 637, 'end_offset': 639}, {'char': 'м', 'start_offset': 641, 'end_offset': 642}, {'char': 'а', 'start_offset': 643, 'end_offset': 644}, {'char': 'ю', 'start_offset': 651, 'end_offset': 652}, {'char': 'т', 'start_offset': 654, 'end_offset': 655}, {'char': 'ь', 'start_offset': 655, 'end_offset': 656}, {'char': ' ', 'start_offset': 657, 'end_offset': 659}, {'char': 'й', 'start_offset': 659, 'end_offset': 660}, {'char': 'о', 'start_offset': 660, 'end_offset': 662}, {'char': 'г', 'start_offset': 664, 'end_offset': 665}, {'char': 'о', 'start_offset': 666, 'end_offset': 667}, {'char': ' ', 'start_offset': 677, 'end_offset': 679}, {'char': 'з', 'start_offset': 681, 'end_offset': 682}, {'char': 'а', 'start_offset': 683, 'end_offset': 684}, {'char': 'х', 'start_offset': 686, 'end_offset': 687}, {'char': 'и', 'start_offset': 689, 'end_offset': 690}, {'char': 'щ', 'start_offset': 696, 'end_offset': 697}, {'char': 'а', 'start_offset': 698, 'end_offset': 699}, {'char': 'т', 'start_offset': 707, 'end_offset': 708}, {'char': 'и', 'start_offset': 709, 'end_offset': 710}, {'char': ' ', 'start_offset': 733, 'end_offset': 734}, {'char': 'е', 'start_offset': 740, 'end_offset': 741}, {'char': 'в', 'start_offset': 747, 'end_offset': 748}, {'char': 'у', 'start_offset': 748, 'end_offset': 749}, {'char': 'й', 'start_offset': 752, 'end_offset': 753}, {'char': 'в', 'start_offset': 754, 'end_offset': 755}, {'char': 'г', 'start_offset': 757, 'end_offset': 758}, {'char': 'е', 'start_offset': 759, 'end_offset': 760}, {'char': 'р', 'start_offset': 767, 'end_offset': 768}, {'char': 'е', 'start_offset': 768, 'end_offset': 769}], word_offsets=[{'word': 'паня', 'start_offset': 0, 'end_offset': 12}, {'word': 'сполучені', 'start_offset': 16, 'end_offset': 39}, {'word': 'штати', 'start_offset': 43, 'end_offset': 59}, {'word': 'надважливий', 'start_offset': 85, 'end_offset': 126}, {'word': 'стратегічний', 'start_offset': 130, 'end_offset': 171}, {'word': 'партнер', 'start_offset': 174, 'end_offset': 194}, {'word': 'однак', 'start_offset': 204, 'end_offset': 225}, {'word': 'є', 'start_offset': 233, 'end_offset': 234}, {'word': 'різниця', 'start_offset': 240, 'end_offset': 263}, {'word': 'штати', 'start_offset': 283, 'end_offset': 297}, {'word': 'мають', 'start_offset': 300, 'end_offset': 311}, {'word': 'спеціальни', 'start_offset': 313, 'end_offset': 342}, {'word': 'закон', 'start_offset': 351, 'end_offset': 374}, {'word': 'який', 'start_offset': 386, 'end_offset': 395}, {'word': 'передбачає', 'start_offset': 399, 'end_offset': 438}, {'word': 'якщо', 'start_offset': 448, 'end_offset': 458}, {'word': 'китай', 'start_offset': 463, 'end_offset': 480}, {'word': 'нападе', 'start_offset': 487, 'end_offset': 505}, {'word': 'на', 'start_offset': 511, 'end_offset': 514}, {'word': 'тайвань', 'start_offset': 518, 'end_offset': 537}, {'word': 'американський', 'start_offset': 555, 'end_offset': 590}, {'word': 'військові', 'start_offset': 594, 'end_offset': 623}, {'word': 'мають', 'start_offset': 641, 'end_offset': 656}, {'word': 'його', 'start_offset': 659, 'end_offset': 667}, {'word': 'захищати', 'start_offset': 681, 'end_offset': 710}, {'word': 'евуйвгере', 'start_offset': 740, 'end_offset': 769}])
153
+ ```
154
+
155
+ ### Split by seconds
156
+
157
+ ```
158
+ 0.0 - 0.24: паня
159
+ 0.32 - 0.78: сполучені
160
+ 0.86 - 1.18: штати
161
+ 1.7 - 2.52: надважливий
162
+ 2.6 - 3.42: стратегічний
163
+ 3.48 - 3.88: партнер
164
+ 4.08 - 4.5: однак
165
+ 4.66 - 4.68: є
166
+ 4.8 - 5.26: різниця
167
+ 5.66 - 5.94: штати
168
+ 6.0 - 6.22: мають
169
+ 6.26 - 6.84: спеціальни
170
+ 7.02 - 7.48: закон
171
+ 7.72 - 7.9: який
172
+ 7.98 - 8.76: передбачає
173
+ 8.96 - 9.16: якщо
174
+ 9.26 - 9.6: китай
175
+ 9.74 - 10.1: нападе
176
+ 10.22 - 10.28: на
177
+ 10.36 - 10.74: тайвань
178
+ 11.1 - 11.8: американський
179
+ 11.88 - 12.46: військові
180
+ 12.82 - 13.12: мають
181
+ 13.18 - 13.34: його
182
+ 13.62 - 14.2: захищати
183
+ 14.8 - 15.38: евуйвгере
184
+ ```
app.py ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from transformers import Wav2Vec2CTCTokenizer, Wav2Vec2ForCTC, Wav2Vec2ProcessorWithLM
3
+ import torch
4
+ import torchaudio
5
+
6
+ model_name = "Yehor/wav2vec2-xls-r-1b-uk-with-lm"
7
+
8
+ tokenizer = Wav2Vec2CTCTokenizer.from_pretrained(model_name)
9
+ processor = Wav2Vec2ProcessorWithLM.from_pretrained(model_name)
10
+ model = Wav2Vec2ForCTC.from_pretrained(model_name)
11
+ model.to("cuda")
12
+
13
+
14
+ # define function to read in sound file
15
+ def speech_file_to_array_fn(path, max_seconds=10):
16
+ batch = {"file": path}
17
+ speech_array, sampling_rate = torchaudio.load(batch["file"])
18
+ if sampling_rate != 16000:
19
+ transform = torchaudio.transforms.Resample(
20
+ orig_freq=sampling_rate, new_freq=16000
21
+ )
22
+ speech_array = transform(speech_array)
23
+ speech_array = speech_array[0]
24
+ if max_seconds > 0:
25
+ speech_array = speech_array[: max_seconds * 16000]
26
+ batch["speech"] = speech_array.numpy()
27
+ batch["sampling_rate"] = 16000
28
+ return batch
29
+
30
+
31
+ # tokenize
32
+ def inference(audio):
33
+ # read in sound file
34
+ # load dummy dataset and read soundfiles
35
+ sp = speech_file_to_array_fn(audio.name)
36
+
37
+ sample_rate = 16000
38
+ # stride_length_s is a tuple of the left and right stride length.
39
+ # With only 1 number, both sides get the same stride, by default
40
+ # the stride_length on one side is 1/6th of the chunk_length_s
41
+ input_values = processor(
42
+ sp["speech"],
43
+ sample_rate=sample_rate,
44
+ chunk_length_s=10,
45
+ stride_length_s=(4, 2),
46
+ return_tensors="pt",
47
+ ).input_values
48
+ input_values = input_values.cuda()
49
+
50
+ with torch.no_grad():
51
+ logits = model(input_values).logits
52
+
53
+ pred_ids = torch.argmax(logits, axis=-1).cpu().tolist()
54
+ prediction = tokenizer.decode(pred_ids[0], output_word_offsets=True)
55
+
56
+ time_offset = 320 / sample_rate
57
+
58
+ total_prediction = []
59
+ for item in prediction.word_offsets:
60
+ r = item
61
+
62
+ s = round(r['start_offset'] * time_offset, 2)
63
+ e = round(r['end_offset'] * time_offset, 2)
64
+
65
+ total_prediction.append(f"{s} - {e}: {r['word']}")
66
+ print(prediction[0])
67
+ return "\n".join(total_prediction)
68
+
69
+
70
+ inputs = gr.inputs.Audio(label="Input Audio", type="file")
71
+ outputs = gr.outputs.Textbox(label="Output Text")
72
+ title = model_name
73
+ description = f"Gradio demo for a {model_name}. To use it, simply upload your audio, or click one of the examples to load them. Read more at the links below. Currently supports .wav 16_000hz files"
74
+ article = "<p style='text-align: center'><a href='https://github.com/egorsmkv/wav2vec2-uk-demo' target='_blank'> Github repo</a> | <a href='<HF Space link>' target='_blank'>Pretrained model</a> | Made with help from <a href='https://github.com/robinhad' target='_blank'>@robinhad</a></p>"
75
+ examples = [
76
+ ["long_1.wav"],
77
+ ["mer_lviv_interview.wav"],
78
+ ["short_1.wav"],
79
+ ["tsn_2.wav"],
80
+ ["tsn.wav"],
81
+ ]
82
+ gr.Interface(
83
+ inference,
84
+ inputs,
85
+ outputs,
86
+ title=title,
87
+ description=description,
88
+ article=article,
89
+ examples=examples,
90
+ ).launch()
inference.py ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import torch
3
+ import torchaudio
4
+ from pathlib import Path
5
+ from transformers import Wav2Vec2ProcessorWithLM, Wav2Vec2ForCTC
6
+
7
+
8
+ def main(args):
9
+ processor = Wav2Vec2ProcessorWithLM.from_pretrained(args.model_id)
10
+ model = Wav2Vec2ForCTC.from_pretrained(args.model_id)
11
+ model.to('cpu')
12
+
13
+ files = args.path_files.split(',')
14
+
15
+ for path_file in files:
16
+ print('File:', path_file)
17
+
18
+ wav_file_path = str(Path(path_file).absolute())
19
+ waveform, sample_rate = torchaudio.load(wav_file_path)
20
+
21
+ if sample_rate != 16000:
22
+ resample = torchaudio.transforms.Resample(
23
+ sample_rate, 16000, resampling_method='sinc_interpolation')
24
+ speech_array = resample(waveform)
25
+ sp = speech_array.squeeze().numpy()
26
+ else:
27
+ sp = waveform.squeeze().numpy()
28
+
29
+ # stride_length_s is a tuple of the left and right stride length.
30
+ # With only 1 number, both sides get the same stride, by default
31
+ # the stride_length on one side is 1/6th of the chunk_length_s
32
+ input_values = processor(sp,
33
+ sample_rate=16000,
34
+ chunk_length_s=args.chunk_length_s,
35
+ stride_length_s=(args.stride_length_s_l, args.stride_length_s_r),
36
+ return_tensors="pt").input_values
37
+
38
+ with torch.no_grad():
39
+ logits = model(input_values).logits
40
+
41
+ prediction = processor.batch_decode(logits.numpy()).text
42
+ print(prediction[0])
43
+
44
+
45
+ if __name__ == "__main__":
46
+ parser = argparse.ArgumentParser()
47
+
48
+ parser.add_argument(
49
+ "--path_files", type=str, required=True, help="WAV files to transcribe, separated by a comma"
50
+ )
51
+ parser.add_argument(
52
+ "--model_id", type=str, required=True, help="Model identifier. Should be loadable with 🤗 Transformers"
53
+ )
54
+ parser.add_argument(
55
+ "--chunk_length_s", type=float, default=None, help="Chunk length in seconds. Defaults to 5 seconds."
56
+ )
57
+ parser.add_argument(
58
+ "--stride_length_s_l", type=int, default=None, help="Stride of the audio chunks, left value."
59
+ )
60
+ parser.add_argument(
61
+ "--stride_length_s_r", type=int, default=None, help="Stride of the audio chunks, right value."
62
+ )
63
+ parser.add_argument(
64
+ "--log_outputs", action="store_true", help="If defined, write outputs to log file for analysis."
65
+ )
66
+ args = parser.parse_args()
67
+
68
+ main(args)
inference_gpu.py ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import torch
3
+ import torchaudio
4
+ from pathlib import Path
5
+ from transformers import Wav2Vec2ProcessorWithLM, Wav2Vec2ForCTC
6
+
7
+
8
+ def main(args):
9
+ processor = Wav2Vec2ProcessorWithLM.from_pretrained(args.model_id)
10
+ model = Wav2Vec2ForCTC.from_pretrained(args.model_id)
11
+ model.to('cuda')
12
+
13
+ files = args.path_files.split(',')
14
+
15
+ for path_file in files:
16
+ print('File:', path_file)
17
+
18
+ wav_file_path = str(Path(path_file).absolute())
19
+ waveform, sample_rate = torchaudio.load(wav_file_path)
20
+
21
+ if sample_rate != 16000:
22
+ resample = torchaudio.transforms.Resample(
23
+ sample_rate, 16000, resampling_method='sinc_interpolation')
24
+ speech_array = resample(waveform)
25
+ sp = speech_array.squeeze().numpy()
26
+ else:
27
+ sp = waveform.squeeze().numpy()
28
+
29
+ # stride_length_s is a tuple of the left and right stride length.
30
+ # With only 1 number, both sides get the same stride, by default
31
+ # the stride_length on one side is 1/6th of the chunk_length_s
32
+ input_values = processor(sp,
33
+ sample_rate=16000,
34
+ chunk_length_s=args.chunk_length_s,
35
+ stride_length_s=(args.stride_length_s_l, args.stride_length_s_r),
36
+ return_tensors="pt").input_values
37
+ input_values = input_values.cuda()
38
+
39
+ with torch.no_grad():
40
+ logits = model(input_values).logits
41
+
42
+ prediction = processor.batch_decode(logits.cpu().numpy()).text
43
+ print(prediction[0])
44
+
45
+
46
+ if __name__ == "__main__":
47
+ parser = argparse.ArgumentParser()
48
+
49
+ parser.add_argument(
50
+ "--path_files", type=str, required=True, help="WAV files to transcribe, separated by a comma"
51
+ )
52
+ parser.add_argument(
53
+ "--model_id", type=str, required=True, help="Model identifier. Should be loadable with 🤗 Transformers"
54
+ )
55
+ parser.add_argument(
56
+ "--chunk_length_s", type=float, default=None, help="Chunk length in seconds. Defaults to 5 seconds."
57
+ )
58
+ parser.add_argument(
59
+ "--stride_length_s_l", type=int, default=None, help="Stride of the audio chunks, left value."
60
+ )
61
+ parser.add_argument(
62
+ "--stride_length_s_r", type=int, default=None, help="Stride of the audio chunks, right value."
63
+ )
64
+ parser.add_argument(
65
+ "--log_outputs", action="store_true", help="If defined, write outputs to log file for analysis."
66
+ )
67
+ args = parser.parse_args()
68
+
69
+ main(args)
inference_timestamps.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ from time import gmtime, strftime
3
+
4
+ import torch
5
+ import torchaudio
6
+ from pathlib import Path
7
+ from transformers import Wav2Vec2ProcessorWithLM, Wav2Vec2ForCTC, Wav2Vec2CTCTokenizer
8
+
9
+
10
+ def main(args):
11
+ tokenizer = Wav2Vec2CTCTokenizer.from_pretrained(args.model_id)
12
+ processor = Wav2Vec2ProcessorWithLM.from_pretrained(args.model_id)
13
+ model = Wav2Vec2ForCTC.from_pretrained(args.model_id)
14
+ model.to('cpu')
15
+
16
+ files = args.path_files.split(',')
17
+
18
+ for path_file in files:
19
+ print('File:', path_file)
20
+
21
+ wav_file_path = str(Path(path_file).absolute())
22
+ waveform, sample_rate = torchaudio.load(wav_file_path)
23
+
24
+ if sample_rate != 16000:
25
+ resample = torchaudio.transforms.Resample(
26
+ sample_rate, 16000, resampling_method='sinc_interpolation')
27
+ sample_rate = 16000
28
+ speech_array = resample(waveform)
29
+ sp = speech_array.squeeze().numpy()
30
+ else:
31
+ sp = waveform.squeeze().numpy()
32
+
33
+ # stride_length_s is a tuple of the left and right stride length.
34
+ # With only 1 number, both sides get the same stride, by default
35
+ # the stride_length on one side is 1/6th of the chunk_length_s
36
+ input_values = processor(sp,
37
+ sample_rate=16000,
38
+ chunk_length_s=args.chunk_length_s,
39
+ stride_length_s=(args.stride_length_s_l, args.stride_length_s_r),
40
+ return_tensors="pt").input_values
41
+
42
+ with torch.no_grad():
43
+ logits = model(input_values).logits
44
+
45
+ # prediction = tokenizer.decode(pred_ids[0], output_word_offsets=True)
46
+ # prediction = tokenizer.decode(pred_ids[0], output_char_offsets=True)
47
+
48
+ pred_ids = torch.argmax(logits, axis=-1).cpu().tolist()
49
+ prediction = tokenizer.decode(pred_ids[0], output_word_offsets=True)
50
+
51
+ print(f'Sample rate: {sample_rate}')
52
+ time_offset = 320 / sample_rate
53
+
54
+ for item in prediction.word_offsets:
55
+ r = item
56
+
57
+ s = round(r['start_offset'] * time_offset, 2)
58
+ e = round(r['end_offset'] * time_offset, 2)
59
+
60
+ print(f"{s} - {e}: {r['word']}")
61
+
62
+
63
+ if __name__ == "__main__":
64
+ parser = argparse.ArgumentParser()
65
+
66
+ parser.add_argument(
67
+ "--path_files", type=str, required=True, help="WAV files to transcribe, separated by a comma"
68
+ )
69
+ parser.add_argument(
70
+ "--model_id", type=str, required=True, help="Model identifier. Should be loadable with 🤗 Transformers"
71
+ )
72
+ parser.add_argument(
73
+ "--chunk_length_s", type=float, default=None, help="Chunk length in seconds. Defaults to 5 seconds."
74
+ )
75
+ parser.add_argument(
76
+ "--stride_length_s_l", type=int, default=None, help="Stride of the audio chunks, left value."
77
+ )
78
+ parser.add_argument(
79
+ "--stride_length_s_r", type=int, default=None, help="Stride of the audio chunks, right value."
80
+ )
81
+ parser.add_argument(
82
+ "--log_outputs", action="store_true", help="If defined, write outputs to log file for analysis."
83
+ )
84
+ args = parser.parse_args()
85
+
86
+ main(args)
long_1.wav ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:348f9c2f15d378b2b489b12e17adb969d7aa7306c0dfde5093856e48288c736c
3
+ size 6164574
mer_lviv_interview.wav ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:921bda3185b93787b15887a715688801a4fa9c2a0c255cfbdc674380a21f9d17
3
+ size 12759536
requirements.txt ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # gradio requirements
2
+ gradio==2.8.2
3
+ jinja2==3.0.3
4
+ # ml requirements
5
+ git+https://github.com/huggingface/transformers@bb7949b35a0a2247bc20c7cb6d86764770ca3232
6
+ pyctcdecode==0.3.0
7
+ https://github.com/kpu/kenlm/archive/master.zip
8
+ # torch
9
+ -f https://download.pytorch.org/whl/cu113/torch_stable.html
10
+ torch==1.10.2+cu113
11
+ -f https://download.pytorch.org/whl/cu113/torch_stable.html
12
+ torchaudio===0.10.2+cu113
short_1.wav ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5ad55ed79a9fe597f6e836fe6a7f3c1bd25d9d48cb6f795ef114ccfa601ee14d
3
+ size 1481694
tsn.wav ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:0cd10579f46c14c99ac623f4e854c7b359d232e6f8c7c29c6c4c1789b83b2a73
3
+ size 1008510
tsn_2.wav ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c4b9a8ac0426792b22b9ef5c59b76db659774ac91699b00eb1748249ae24f2fb
3
+ size 2941310