File size: 10,116 Bytes
2381c77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
import os
import re
import random

import gradio as gr
import pandas as pd

from glob import glob
from pathlib import Path

output_file = "annotation.csv"
current_audio="Sample_verse.wav"
current_text = " ".join(str("طَيِّ السِّجِلِّ لِلْكُتُبِ").replace(" ", "_"))

audio_root = "./recordings_OI" 

wav_files= list(glob(f"{audio_root}/*/*.wav"))
wav_files.sort()
txt_files=[x.replace(".wav",".txt") for x in wav_files]

aud_text = list(zip(wav_files, txt_files))

global index
with open(output_file, 'r') as f:
    index = sum(1 for line in f)

def get_audio_path(aud_text):
    for i in aud_text:
        yield i
     
pattern = r'>(.*?)<span style=".*?">(.*?)</span>(.*?)</p>'   
def read_txt(path):
    with open(path,"r") as f:
        x = f.readline().strip()
        match = re.search(pattern, x)
        if match is not None:
            x_ = f"{match.group(1)}{match.group(2)}{match.group(3)}"
        else:
            x_ = x.replace("<p>", "").replace("</p>", "")\
                .replace('<span style="color:red;">', "").replace("</span>", "")\
                .replace('<h4>', "").replace("</h4>", "")
    return x, x_

# file_path = "./Record Prompts - Extra.csv"
file_path = "./Record Prompts - Sheet3.csv"

texts_instructions = {}

texts_plain_instruction = {}
def get_separated(text):
    return " ".join([x.replace("  "," ").replace(" ", "_") for x in text])\
            .replace(" @ ","@")
            
    return " ".join([x.replace("  ", " ").replace(" ", "_") if "@" not in x else x for x in text])

with open(file_path, "r") as f:
    header = f.readline()
    for line in f:
        data = line.strip().split(",")
        data = [d.replace('\n','').replace("  "," ") for d in data]
        # text = f"{data[0]}{data[1]}{data[2]}"
        text = f"{data[1]}{data[2]}{data[3]}"
        # texts_instructions[text] = get_separated(data[0])
        text = text.replace(" ", "")
        texts_instructions[text] = get_separated(data[0])
        
        
with open(file_path, "r") as f:
    header = f.readline()
    for line in f:
        data = line.strip().split(",")
        data = [d.replace('\n','').replace("  "," ") for d in data]
        # text = f"{data[0]}{data[1]}{data[2]}"
        text = f"{data[1]}{data[2]}{data[3]}"
        text = text.replace(" ", "")
        texts_plain_instruction[text] = '<p style="font-family:"Traditional Arabic",font-size:150px;"><mark>{0}</mark></p>'.format(data[4])

def give_audio_text(gen=None):
    global current_audio
    global current_text
    global aud_text_generator
    global index, ai_annotation, plain_instruction
    # Use the passed generator or default to the global one
    if gen is None:
        gen = aud_text_generator
    try:
        current_audio, current_text = next(gen)
        current_text, x_ = read_txt(current_text)
        ai_annotation = texts_instructions.get(x_.strip().replace(" ", "").replace("ۚ",""), get_separated(x_.strip()))
        plain_instruction = texts_plain_instruction.get(x_.strip().replace(" ", "").replace("ۚ",""), "")
        # x_ = " ".join(str(x_).replace(" ", "_"))
        index +=1
        return current_audio, current_audio, ai_annotation ,current_text, plain_instruction
    
    except StopIteration:
        aud_text_generator = get_audio_path(aud_text) # Reset the generator
        current_audio = next(aud_text_generator)  # Start from the beginning
        print("Current Audio after reset: ", current_audio)
        gr.Info("Annotation Completed! Thank you for your time. Please close the tab!", duration=0)
        return current_audio, current_audio, current_text,current_text, current_text

def save_transcription(path, text, additional_errors=""):
    with open(f"{output_file}", "a") as f:
        f.write(f"{path}\t{text}\t{additional_errors}\n")
    return gr.Button("Get New Audio/Save updated transcription",interactive=False)

def activate_button():
    return gr.Button("Get New Audio/Save updated transcription",interactive=True)

def increase(num):
    if num == len(aud_text):
        return 1
    return num + 1

start_index = 1

def begin_annotation(annotator):
    os.makedirs(f"./annotations/{annotator}", exist_ok=True)
    global output_file, index, current_audio, current_text, ai_annotation, plain_instruction, start_index
    output_file = f"./annotations/{annotator}/annotation.csv"
    with open(output_file, 'r') as f:
        index = sum(1 for line in f)
    start_index = index
    aud_text_generator = get_audio_path(aud_text[index:])
    current_audio, current_text = next(aud_text_generator)
    current_text, x_ = read_txt(current_text)
    ai_annotation = texts_instructions.get(x_.strip().replace(" ", "").replace("ۚ",""), get_separated(x_.strip()))
    plain_instruction = texts_plain_instruction.get(x_.strip().replace(" ", "").replace("ۚ",""), "")
    return gr.Column(visible=True), gr.Column(visible=False), \
        start_index, current_audio,current_audio, current_text,plain_instruction, ai_annotation

aud_text_generator = get_audio_path(aud_text[index:])
current_audio, current_text = next(aud_text_generator)
current_text, x_ = read_txt(current_text)
ai_annotation = texts_instructions.get(x_.strip().replace(" ", "").replace("ۚ",""), get_separated(x_.strip()))
plain_instruction = texts_plain_instruction.get(x_.strip().replace(" ", "").replace("ۚ",""), "")
    
with gr.Blocks(title = "Transcription Instruction") as instruction:
    gr.Markdown("""
    <div align="center"> 
        <h2>Quran Pronunciation Annotation</h2> 
    </div> 
                
    # **الغرض من العمل**

    ستقوم بتحديد الأخطاء النطقية التي يقوم بها المتكلم أثناء نطقه للجمل، وفقًا للإرشادات التالية

    # **خطوات العمل**

    1. استمع بعناية للتسجيل الصوتي المرفق. تأكد من متابعة كل كلمة بدقة.
    2. قبل البدء، اقرأ وصف الخطأ المطلوب (مثال: استبدال الفتحة بالكسرة، أو نطق الحرف بطريقة غير صحيحة).
    3. افهم الجملة المتوقعة مع تمييز الخطأ المطلوب فيها باللون الأحمر.
    4. استمع مجددًا للتسجيل الصوتي للتحقق مما إذا كان المتكلم قد قام بالخطأ النطقي المطلوب.
    5. إذا لاحظت وجود أي أخطاء إضافية قام بها المتكلم ولم يتم تحديدها مسبقًا، قم بتوثيقها أيضًا.
    6. راجع كل كلمة منطوقة لتحديد أي انحراف إضافي عن النطق الصحيح.
    7. قم بتوثيق الأخطاء بطريقة منظمة وواضحة، مع الإشارة إلى نوع الخطأ وموقعه في الجملة.
    8. إستخدم الرمز @ للإشارة إلى كل حرف أو حركة خاطئة.
    9. بعد رمز @، قم بإضافة النسخة التي نُطقت بشكل خاطئ.
    10. يوجد ثلاث أنواع للاخطاء: استبدال , حذف أو أضافة:

    ## **الاستبدال**

    - إستبدال حرف بحرف أو حركة بحركة
    - مثال استبدال العين بالحاء في العسر الي الحسر. تكتب ا ل ع@ح ُ س ر

    ## **حذف**

    - حذف حرف أو حركة
    - مثال حذف التشديد في أنَّ الي أنَ. تكتب إ ِ نّ@  َ. يوجد مسافة بعد ال@ في حالة الحذف.

    ## **إضافة**

    - إضافة حرف أو حركة
    - مثال إضافة حرف في العُسر الي العُوسر. تكتب ا ل ع ُ @و س ر. يوجد مسافة قبل ال @ في حالة الأضافة.

    في حال وجود أي استفسارات أو مواجهة أي مشكلات، يمكنك التواصل عبر البريد الإلكتروني التالي:
    omnia@lst.uni-saarland.de


    شكراً جزيلاً لتعاونك والتزامك بالدقة
    """)

with gr.Blocks(title = "Fix Transcription") as tool:  
    
    with gr.Column(visible=True) as annotation_name:
        annotator_name = gr.Textbox(label="Annotator Name", placeholder="Enter your name", interactive=True)
        begin_annotate = gr.Button("Begin Annotation", variant="primary")
    
    with gr.Column(visible=False) as annotation_block:
        progress = gr.Number(start_index, label = f"X of {len(aud_text)} audios" ,interactive=False)
        audio = gr.Audio(label="Audio", interactive=False, value=current_audio, autoplay=True)
        audio_file_name = gr.Textbox(value=current_audio, label="Audio File Name", interactive=False, visible=False)
        
        gr.Markdown('<h3>Expected Transcription:</h3>')
        original_text = gr.Markdown(value=current_text)
        gr.Markdown('<h3>Error Details:</h3>')
        original_annotation = gr.Markdown(f"{plain_instruction}")
        
        transcription = gr.Textbox(label="Actual transcription (editable)", value=ai_annotation, interactive=True, rtl=True)

        additional_errors = gr.Textbox(label="Additional Errors (optional)", value="", placeholder="Enter additional errors", interactive=True, rtl=True)
        get_new_audio = gr.Button("Get New Audio/Save updated transcription",
                            variant="primary")
    
    begin_annotate.click(begin_annotation, [annotator_name], \
                         [annotation_block, annotation_name, progress, audio, audio_file_name,\
                             original_text, original_annotation, transcription])
    
    get_new_audio.click(save_transcription, [audio_file_name, transcription, additional_errors], [get_new_audio]).\
        then(give_audio_text, outputs=[audio,audio_file_name, transcription, original_text, original_annotation]).\
            then(activate_button, outputs=[get_new_audio]).then(increase,progress, progress)
    
    
    
demo = gr.TabbedInterface([instruction, tool], ["Instructions", "Annotate"])
    
if __name__ == "__main__":
    demo.launch(share=True)