Stt / app.py
archivartaunik's picture
Update app.py
0cebf66 verified
import gradio as gr
from argparse import Namespace
import os
import shutil
import sys
import yt_dlp # для працы з YouTube
import glob # Import glob for file searching
GEMINI_API_KEY = os.getenv("gem2")
from sub_tools.media.converter import hls_to_media, media_to_signature, video_to_audio
from sub_tools.media.segmenter import segment_audio
from sub_tools.subtitles.combiner import combine_subtitles
from sub_tools.system.directory import change_directory
from sub_tools.system.console import header, success, error
from sub_tools.transcribe import transcribe
# Вызначэнне функцый для дэактывацыі процілеглага поля
def update_on_audio_change(audio):
if audio is not None:
return gr.update(interactive=False)
return gr.update(interactive=True)
def update_on_video_change(video):
if video is not None:
return gr.update(interactive=False)
return gr.update(interactive=True)
def main_logic(args: Namespace) -> tuple:
"""
Асноўная логіка прыкладання: ад загрузкі відэа/аўдыё да зліцця субтытраў.
Пасля зліцця субтытраў вяртае (тэкст субтытраў, шлях да SRT‑файла для спампоўкі).
"""
output_str = ""
subtitles_text = ""
srt_file_path = None
try:
change_directory(args.output_path)
step = 1
if "video" in args.tasks:
if not args.hls_url:
output_str += f"{step}. Download Video: No video file uploaded\n"
raise Exception("No video file uploaded")
header(f"{step}. Download Video")
output_str += f"{step}. Download Video: Started\n"
hls_to_media(args.hls_url, args.video_file, False, args.overwrite)
success("Done!")
output_str += "Done!\n"
step += 1
if "audio" in args.tasks:
header(f"{step}. Video to Audio")
output_str += f"{step}. Video to Audio: Started\n"
video_to_audio(args.video_file, args.audio_file, args.overwrite)
success("Done!")
output_str += "Done!\n"
step += 1
if "signature" in args.tasks:
header(f"{step}. Audio to Signature")
output_str += f"{step}. Audio to Signature: Started\n"
media_to_signature(args.audio_file, args.signature_file, args.overwrite)
success("Done!")
output_str += "Done!\n"
step += 1
if "segment" in args.tasks:
header(f"{step}. Segment Audio")
output_str += f"{step}. Segment Audio: Started\n"
print(f"Current working directory before segment_audio: {os.getcwd()}") # Debug CWD
print(f"Audio file path for segmentation: {args.audio_file}") # Debug audio file path
if not os.path.exists(args.audio_file): # Critical file existence check
error_msg = f"Error: Audio file not found before segmentation: {args.audio_file}"
error(error_msg)
return (error_msg, None)
print(f"Audio file exists before segmentation: {args.audio_file}") # Debug file existence
segment_audio(args.audio_file, args.audio_segment_prefix, args.audio_segment_format, args.audio_segment_length, args.overwrite)
success("Done!")
output_str += "Done!\n"
step += 1
if "transcribe" in args.tasks:
if not (args.gemini_api_key and args.gemini_api_key.strip()):
output_str += f"{step}. Transcribe Audio: No Gemini API Key provided\n"
raise Exception("No Gemini API Key provided")
header(f"{step}. Transcribe Audio")
output_str += f"{step}. Transcribe Audio: Started\n"
transcribe(args)
success("Done!")
output_str += "Done!\n"
step += 1
if "combine" in args.tasks:
header(f"{step}. Combine Subtitles")
output_str += f"{step}. Combine Subtitles: Started\n"
combine_subtitles(args.languages, args.audio_segment_prefix, args.audio_segment_format)
success("Done!")
output_str += "Done!\n"
if args.languages:
language = args.languages[0]
srt_file_path = os.path.join(os.getcwd(), f"{language}.srt")
try:
with open(srt_file_path, "r", encoding="utf-8") as f:
subtitles_text = f.read()
except Exception as e:
subtitles_text = f"Error reading subtitles file: {str(e)}"
else:
subtitles_text = "No language specified"
step += 1
return (subtitles_text, srt_file_path)
except Exception as e:
error_msg = f"Error: {str(e)}"
error(error_msg)
return (error_msg, None)
def run_subtools(
tasks,
hls_url,
video_file,
audio_file,
signature_file,
output_path,
languages,
overwrite,
retry,
gemini_api_key,
debug,
audio_segment_prefix,
audio_segment_format,
audio_segment_length
):
"""
Падрыхтоўка каталога вываду і запуск асноўнай логікі.
"""
if os.path.exists(output_path):
shutil.rmtree(output_path)
os.makedirs(output_path, exist_ok=True)
if isinstance(languages, str):
languages = [lang.strip() for lang in languages.split(",") if lang.strip()]
args = Namespace(
tasks=tasks,
hls_url=hls_url,
video_file=video_file,
audio_file=audio_file,
signature_file=signature_file,
output_path=output_path,
languages=languages,
overwrite=overwrite,
retry=retry,
gemini_api_key=gemini_api_key,
debug=debug,
audio_segment_prefix=audio_segment_prefix,
audio_segment_format=audio_segment_format,
audio_segment_length=audio_segment_length,
)
return main_logic(args)
def transcribe_youtube(youtube_url: str) -> tuple:
"""
Спампоўвае аўдыё з відэа YouTube праз yt_dlp і вяртае паведамленне і шлях да часовага аўдыёфайла.
Выкарыстоўвае chromewebstore.google.com_cookies.txt, калі ён ёсць.
"""
if not youtube_url:
return "Не ўведзена спасылка", None
output_dir = "output_youtube_downloads" # Define a specific output directory
os.makedirs(output_dir, exist_ok=True) # Create the directory if it doesn't exist
outtmpl = os.path.join(output_dir, "temp_youtube_audio.%(ext)s") # Path within the output dir
try:
ydl_opts = {
'format': 'bestaudio/best',
'outtmpl': outtmpl,
#'quiet': True, # Прыбіраем quiet для адладкі
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3', # Download as MP3
'preferredquality': '0', # лепшая якасць
}],
}
default_cookies_file = "chromewebstore.google.com_cookies.txt"
if os.path.exists(default_cookies_file):
ydl_opts['cookiefile'] = default_cookies_file
print(f"Выкарыстоўваецца файл cookie па змаўчанні: {default_cookies_file}")
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
ydl.download([youtube_url])
# Шукаем створаны аўдыёфайл у output_dir
audio_files = glob.glob(os.path.join(output_dir, "temp_youtube_audio.*"))
print(f"Знойдзеныя аўдыёфайлы ў {output_dir}: {audio_files}") # Дадаем вывад для адладкі
if not audio_files:
return ("Памылка: файл аўдыё не створаны", None)
audio_file_rel = None # Relative path
for f in audio_files:
if f.endswith(".mp3"):
audio_file_rel = f
break
if audio_file_rel is None:
audio_file_rel = audio_files[0]
audio_file_abs = os.path.abspath(audio_file_rel) # Get absolute path here!
print(f"Абраны аўдыёфайл (relative): {audio_file_rel}") # Дадаем вывад для адладкі
print(f"Абраны аўдыёфайл (absolute): {audio_file_abs}") # Дадаем вывад для адладкі
return ("Спампоўка YouTube аўдыё завершана", audio_file_abs) # Return absolute path!
except Exception as e:
err_msg = f"Памылка пры апрацоўцы YouTube (yt_dlp): {e}. Калі ласка, пераканайцеся, што спасылка сапраўдная, і праверце, ці даступныя відэа."
print(err_msg)
return (err_msg, None)
def process_youtube_url(youtube_url):
"""
Апрацоўвае YouTube спасылку: спампоўвае аўдыё, адлюстроўвае аўдыёфайл і запускае ланцуг апрацоўкі для стварэння субтытраў.
"""
download_msg, audio_file = transcribe_youtube(youtube_url)
if not audio_file:
return download_msg, None # Return None for other outputs if download fails
full_audio_file_path = audio_file
print(f"Поўны шлях да аўдыёфайла: {full_audio_file_path}")
if not os.path.exists(full_audio_file_path):
return f"Памылка: Аўдыёфайл не знойдзены па шляху: {full_audio_file_path}", None
print(f"Файл існуе: {full_audio_file_path}")
output_text_file, output_file_file = process_uploaded_file(audio=full_audio_file_path, video=None)
return output_text_file, output_file_file # Correct return order: text, file_path
def process_uploaded_file(audio, video):
"""
Выбірае, які файл загружаны, і фармуе параметры для апрацоўкі.
Калі загружаны аўдыёфайл – запускае апрацоўку для аўдыё,
калі відэафайл – запускае поўны ланцуг апрацоўкі.
"""
if audio is not None and video is None:
tasks = ["signature", "segment", "transcribe", "combine"]
video_file = "" # відэа не выкарыстоўваецца
audio_file = audio
hls_url = "" # не патрабуецца
elif video is not None and audio is None:
tasks = ["video", "audio", "signature", "segment", "transcribe", "combine"]
video_file = video
audio_file = "audio.mp3" # прызначаем імя для аўдыёфайла
hls_url = "dummy" # задаём няпустое значэнне для праверкі
else:
return "Error: Загрузіце толькі АЎДЫЁ або ВІДЭАфайл, а не абодва.", None
return run_subtools(
tasks=tasks,
hls_url=hls_url,
video_file=video_file,
audio_file=audio_file,
signature_file="message.shazamsignature",
output_path="output",
languages="be",
overwrite=False,
retry=50,
gemini_api_key=GEMINI_API_KEY,
debug=True,
audio_segment_prefix="audio_segment",
audio_segment_format="mp3",
audio_segment_length=300000
)
# --------------------- Gradio UI ---------------------
with gr.Blocks() as demo:
gr.Markdown("# пакуль не працуе! Транскрыпцыя аўдыя для беларускай мовы. Перарабляем на больш якаснае разпазнаванне для доўгіх відэа")
gr.Markdown(
"""
## [Можна выкарыстаць сэрвіс для кароткіх відэа тут] (https://huggingface.co/spaces/archivartaunik/SubtitlesBE)
[Ёсць пытанні ці прапановы? Далучайцеся да беларускаймоўнай суполкі штучнага інтэлекту](https://t.me/belarusai)
**Хочаце каб сэрвіс працаваў? Налівайце каву! :** [Buy me a coffee](https://buymeacoffee.com/tuteishygpt)
**Агучце беларускую мову тут :** [Беларуская мадэль маўлення](https://huggingface.co/spaces/archivartaunik/Bextts)
"""
)
with gr.Tabs():
with gr.Tab("Файл"):
with gr.Row():
audio_input = gr.Audio(type="filepath", label="Аўдыёфайл") # Keep type="filepath"
video_input = gr.Video(label="Відэафайл", interactive=True) # Reset to interactive True initially
audio_input.change(fn=update_on_audio_change, inputs=audio_input, outputs=video_input)
video_input.change(fn=update_on_video_change, inputs=video_input, outputs=audio_input)
submit_btn_file = gr.Button("Submit")
output_text_file = gr.Textbox(label="Тэкст субтытраў")
output_file_file = gr.File(label="Спампаваць SRT файл")
submit_btn_file.click(fn=process_uploaded_file, inputs=[audio_input, video_input], outputs=[output_text_file, output_file_file])
with gr.Tab("YouTube"):
youtube_url_input = gr.Textbox(label="YouTube URL", placeholder="Устаўце спасылку на відэа YouTube")
submit_btn_youtube = gr.Button("Submit")
output_text_youtube = gr.Textbox(label="Тэкст субтытраў")
output_file_youtube = gr.File(label="Спампаваць SRT файл")
submit_btn_youtube.click(
fn=process_youtube_url,
inputs=youtube_url_input,
outputs=[output_text_youtube, output_file_youtube] # Correct output order
)
demo.launch(allowed_paths=["output_youtube_downloads"])