import os import time import gradio as gr from pathlib import Path import pysrt import pandas as pd if os.path.isdir(f'{os.getcwd() + os.sep}whisper.cpp'): print("Models already loaded") else: os.system('git clone https://github.com/ggerganov/whisper.cpp.git') os.system('git clone https://huggingface.co/Finnish-NLP/Finnish-finetuned-whisper-models-ggml-format') os.system('make -C ./whisper.cpp') whisper_models = ["medium", "large"] whisper_modelpath_translator= { "medium": "./Finnish-finetuned-whisper-models-ggml-format/ggml-model-fi-medium.bin", "large": "./Finnish-finetuned-whisper-models-ggml-format/ggml-model-fi-large-v3.bin" } def speech_to_text(audio_path, whisper_model): if(audio_path is None): retry_cnt = 0 for retry_cnt in range(3): if(audio_path is None): print(f'Retrying, retry counter: {retry_cnt +1}') time.sleep(0.5) retry_cnt +=1 if retry_cnt == 3: raise ValueError("Error no audio input") else: break print(audio_path) try: _,file_ending = os.path.splitext(f'{audio_path}') print(f'file enging is {file_ending}') print("starting conversion to wav") new_path = audio_path.replace(file_ending, "_converted.wav") os.system(f'ffmpeg -i "{audio_path}" -ar 16000 -y -ac 1 -c:a pcm_s16le "{new_path}"') print("conversion to wav ready") except Exception as e: raise RuntimeError(f'Error Running inference with local model: {e}') from e try: print("starting whisper c++") srt_path = new_path + ".srt" os.system(f'rm -f {srt_path}') os.system(f'./whisper.cpp/main "{new_path}" -t 4 -m ./{whisper_modelpath_translator.get(whisper_model)} -osrt') print("starting whisper done with whisper") except Exception as e: raise RuntimeError(f'Error running Whisper cpp model: {e}') from e try: df = pd.DataFrame(columns = ['start','end','text']) subs = pysrt.open(srt_path) rows = [] for sub in subs: start_hours = str(str(sub.start.hours) + "00")[0:2] if len(str(sub.start.hours)) == 2 else str("0" + str(sub.start.hours) + "00")[0:2] end_hours = str(str(sub.end.hours) + "00")[0:2] if len(str(sub.end.hours)) == 2 else str("0" + str(sub.end.hours) + "00")[0:2] start_minutes = str(str(sub.start.minutes) + "00")[0:2] if len(str(sub.start.minutes)) == 2 else str("0" + str(sub.start.minutes) + "00")[0:2] end_minutes = str(str(sub.end.minutes) + "00")[0:2] if len(str(sub.end.minutes)) == 2 else str("0" + str(sub.end.minutes) + "00")[0:2] start_seconds = str(str(sub.start.seconds) + "00")[0:2] if len(str(sub.start.seconds)) == 2 else str("0" + str(sub.start.seconds) + "00")[0:2] end_seconds = str(str(sub.end.seconds) + "00")[0:2] if len(str(sub.end.seconds)) == 2 else str("0" + str(sub.end.seconds) + "00")[0:2] start_millis = str(str(sub.start.milliseconds) + "000")[0:3] end_millis = str(str(sub.end.milliseconds) + "000")[0:3] rows.append([sub.text, f'{start_hours}:{start_minutes}:{start_seconds}.{start_millis}', f'{end_hours}:{end_minutes}:{end_seconds}.{end_millis}']) for row in rows: srt_to_df = { 'start': [row[1]], 'end': [row[2]], 'text': [row[0]] } df = pd.concat([df, pd.DataFrame(srt_to_df)]) except Exception as e: print(f"Error creating srt df with error: {e}") return df def output_to_files(df): df.reset_index(inplace=True) print("Starting SRT-file creation") print(df.head()) with open('subtitles.vtt','w', encoding="utf-8") as file: print("Starting WEBVTT-file creation") for i in range(len(df)): if i == 0: file.write('WEBVTT') file.write('\n') else: file.write(str(i+1)) file.write('\n') start = df.iloc[i]['start'] file.write(f"{start.strip()}") stop = df.iloc[i]['end'] file.write(' --> ') file.write(f"{stop}") file.write('\n') file.writelines(df.iloc[i]['text']) if int(i) != len(df)-1: file.write('\n\n') print("WEBVTT DONE") with open('subtitles.srt','w', encoding="utf-8") as file: print("Starting SRT-file creation") for i in range(len(df)): file.write(str(i+1)) file.write('\n') start = df.iloc[i]['start'] file.write(f"{start.strip()}") stop = df.iloc[i]['end'] file.write(' --> ') file.write(f"{stop}") file.write('\n') file.writelines(df.iloc[i]['text']) if int(i) != len(df)-1: file.write('\n\n') print("SRT DONE") subtitle_files_out = ['subtitles.vtt','subtitles.srt'] return subtitle_files_out # ---- Gradio Layout ----- demo = gr.Blocks(css=''' #cut_btn, #reset_btn { align-self:stretch; } #\\31 3 { max-width: 540px; } .output-markdown {max-width: 65ch !important;} ''') demo.encrypt = False with demo: with gr.Row(): with gr.Column(): gr.Markdown(''' # Simple Finnish Audio --> Text app ### This space allows you to: 1. Insert audio file or record with microphone 2. Run audio through transcription process using speech recognition models 3. Download generated transcriptions in .vtt and .srt formats ''') with gr.Row(): with gr.Column(): audio_in = gr.Audio(label="Audio file", type='filepath') transcribe_btn = gr.Button("Step 1. Transcribe audio") selected_whisper_model = gr.Dropdown(choices=whisper_models, type="value", value="large", label="Selected Whisper model", interactive=True) with gr.Row(): with gr.Column(): transcription_df = gr.DataFrame(headers = ['start','end','text'], label="Transcription dataframe") with gr.Row(): with gr.Column(): translate_transcriptions_button = gr.Button("Step 2. Create subtitle files") with gr.Row(): with gr.Column(): gr.Markdown('''##### From here you can download subtitles in .srt or .vtt format''') subtitle_files = gr.File( label="Download files", file_count="multiple", type="filepath", interactive=False, ) # Functionalities transcribe_btn.click(speech_to_text, [audio_in, selected_whisper_model], [transcription_df]) translate_transcriptions_button.click(output_to_files, transcription_df, [subtitle_files]) demo.launch()