Spaces:
Running
Running
File size: 10,874 Bytes
6160629 4ba47fd d9d75ab 06555da 04c273e 6160629 c3bc5d7 e64464f 89be3e8 a9913d9 4ba47fd 265d4cc 89be3e8 6160629 04c273e d9d75ab 265d4cc 89be3e8 265d4cc 6160629 3ab57cd 4ba47fd 89be3e8 4ba47fd 82ff83b 4ba47fd 89be3e8 a9913d9 265d4cc 89be3e8 04c273e 89be3e8 6160629 04c273e a9913d9 265d4cc 89be3e8 04c273e 265d4cc 89be3e8 265d4cc 631160f 4ba47fd 82ff83b 4ba47fd a9913d9 631160f 04c273e 265d4cc 3ab57cd a9913d9 265d4cc 89be3e8 04c273e d9d75ab f2c750c d9d75ab f2c750c d9d75ab 04c273e a9913d9 265d4cc 89be3e8 04c273e 265d4cc 04c273e a9913d9 89be3e8 631160f 89be3e8 a9913d9 6160629 265d4cc 89be3e8 04c273e 9dab23b 06555da 6c7418c 265d4cc 9dab23b 04c273e a9913d9 265d4cc 89be3e8 04c273e 265d4cc 9dab23b 265d4cc 9dab23b a9913d9 265d4cc 89be3e8 04c273e 89be3e8 04c273e 89be3e8 04c273e 9dab23b 265d4cc a9913d9 89be3e8 04c273e 265d4cc 89be3e8 265d4cc f2c750c 4ba47fd 82ff83b 4ba47fd a9913d9 89be3e8 f2c750c 04c273e 265d4cc 04c273e 89be3e8 04c273e 3ab57cd 04c273e f2c750c d9d75ab 04c273e 82ff83b |
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 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
import os
import gradio as gr
from google import genai
from google.genai import types
import mimetypes
from pydub import AudioSegment
import asyncio
import logging
# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
# Атрыманне ключоў і мадэляў з пераменных асяроддзя
GEMINI_API_KEY = os.getenv("gemini")
MODEL_NAME_TH = os.getenv("modTH") # Мадэль для транскрыпцыі
MODEL_NAME = os.getenv("mod") # Мадэль для выпраўлення фармату і перакладу
PROMPT_TRANSCRIBE = os.getenv("p") # Промпт для транскрыпцыі
# Стварэнне кліента
client = genai.Client(api_key=GEMINI_API_KEY)
def transcribe_audio(audio_file: str) -> str:
"""Транскрыбуе аўдыяфайл з дапамогай Google GenAI."""
try:
if not audio_file or not os.path.exists(audio_file):
return "Памылка: Файл не знойдзены або не указаны."
mime_type, _ = mimetypes.guess_type(audio_file)
if not mime_type or not mime_type.startswith("audio"):
return (
"Немагчыма вызначыць тып файла або файл не з'яўляецца аўдыяфайлам. "
"Падтрымліваюцца толькі аўдыяфайлы."
)
with open(audio_file, "rb") as f:
audio_data = f.read()
# Стварэнне contents для перадачы ў API
contents = [
{"text": PROMPT_TRANSCRIBE},
{"mime_type": mime_type, "data": audio_data},
]
# Выклік API
response = client.models.generate_content(
model=MODEL_NAME_TH,
contents=contents,
config={"temperature": 0.2}
)
# Атрыманне адказу
return response.text.strip()
except FileNotFoundError:
logger.error(f"Файл не знойдзены: {audio_file}")
return "Памылка: Файл не знойдзены."
except Exception as e:
logger.error(f"Памылка пры транскрыпцыі: {str(e)}", exc_info=True)
return f"Нечаканая памылка: {str(e)}"
def fix_subtitles_format(transcript: str) -> str:
"""Выпраўляе фармат часу ў субцітрах."""
if not transcript:
return ""
prompt_fix = (
"Не змяняй тэксты, выправі толькі часовы фармат у субцітрах на правільны, "
"вось прыклад 00:00:01,589. \nУ адказ напішы толькі субцітры:\n"
f"{transcript}"
)
try:
response_fix = client.models.generate_content(
model=MODEL_NAME,
contents=[{"text": prompt_fix}],
config={"temperature": 0.2}
)
return response_fix.text.strip()
except Exception as e:
logger.error(f"Памылка пры выпраўленні субцітраў: {str(e)}", exc_info=True)
return transcript
def create_srt(transcript: str, filename: str = "subtitles.srt") -> tuple[str, str]:
"""Стварае SRT-файл з транскрыпцыі."""
if not transcript:
return "", ""
try:
with open(filename, "w", encoding="utf-8") as f:
f.write(transcript)
return transcript, filename
except Exception as e:
logger.error(f"Памылка пры запісе SRT-файла: {str(e)}", exc_info=True)
return f"Памылка пры запісе SRT-файла: {str(e)}", ""
def process_audio(audio_path: str) -> tuple[str, str]:
"""Апрацоўвае аўдыёфайл: транскрыбуе і стварае SRT."""
if not audio_path:
return "Не указаны шлях да аўдыёфайла.", ""
transcript = transcribe_audio(audio_path)
if transcript.startswith("Памылка") or transcript.startswith("Немагчыма") or transcript.startswith("Нечаканая"):
return transcript, ""
fixed_transcript = fix_subtitles_format(transcript)
text, srt_file = create_srt(fixed_transcript)
return text, srt_file
def extract_audio_from_video(video_file: str) -> tuple[str, str]:
"""Выдзяляе аўдыёдарожку з відэафайла."""
if not video_file or not os.path.exists(video_file):
return "", "Памылка: Відэафайл не знойдзены або не указаны."
try:
audio = AudioSegment.from_file(video_file)
audio_path = "extracted_audio.mp3"
audio.export(audio_path, format="mp3")
return audio_path, ""
except Exception as e:
logger.error(f"Памылка пры выдзяленні аўдыё з відэафайла: {str(e)}", exc_info=True)
return "", f"Памылка пры выдзяленні аўдыё з відэафайла: {str(e)}"
def process_video(video_path: str) -> tuple[str, str]:
"""Апрацоўвае відэафайл: выдзяляе аўдыё, транскрыбуе і стварае SRT."""
if not video_path:
return "Не указаны шлях да відэафайла.", ""
audio_path, error = extract_audio_from_video(video_path)
if error:
return error, ""
return process_audio(audio_path)
def process_file(audio_path: str | None, video_path: str | None) -> tuple[str, str]:
"""Апрацоўвае файл (аўдыё або відэа)."""
try:
if audio_path:
return process_audio(audio_path)
elif video_path:
return process_video(video_path)
else:
return "Няма файла для апрацоўкі.", ""
except Exception as e:
logger.error(f"Памылка пры апрацоўцы файла: {str(e)}", exc_info=True)
return f"Памылка пры апрацоўцы файла: {str(e)}", ""
def update_on_audio_change(audio_path: str | None) -> gr.update:
"""Абнаўляе інтэрфейс пры змене аўдыёфайла."""
try:
return gr.update(value=None, interactive=not bool(audio_path))
except Exception as e:
logger.error(f"Памылка пры абнаўленні інтэрфейса: {str(e)}", exc_info=True)
return gr.update(value=None, interactive=True)
def update_on_video_change(video_path: str | None) -> gr.update:
"""Абнаўляе інтэрфейс пры змене відэафайла."""
try:
return gr.update(value=None, interactive=not bool(video_path))
except Exception as e:
logger.error(f"Памылка пры абнаўленні інтэрфейса: {str(e)}", exc_info=True)
return gr.update(value=None, interactive=True)
def translate_transcript(transcript: str, target_language: str) -> tuple[str, str]:
"""Перакладае транскрыпцыю на іншую мову і стварае SRT."""
if not transcript:
return "Няма тэксту для перакладу.", ""
prompt_text = (
f"Перакладзі толькі тэксты субцітраў на {target_language} мову. "
"Астатняе пакінь як ёсць.\nТэкст:\n{transcript}"
)
try:
response = client.models.generate_content(
model=MODEL_NAME,
contents=[{"text": prompt_text}],
config={"temperature": 0.2}
)
translated = response.text.strip()
translated_srt_filename = "translated_subtitles.srt"
return create_srt(translated, translated_srt_filename)
except Exception as e:
logger.error(f"Памылка пры перакладзе: {str(e)}", exc_info=True)
return f"Памылка пры перакладзе: {str(e)}", ""
try:
with gr.Blocks() as demo:
gr.Markdown("# Транскрыпцыя аўдыя для беларускай мовы")
gr.Markdown(
"""
## Загрузіце аўдыёфайл або відэафайл да 15 хвілін. Калі загружаны аўдыёфайл, відэа неактыўна, і наадварот.
Субцітры будуць аўтаматычна згенераваны разам з SRT-файлам.
[Далучайцеся да беларускаймоўнай суполкі ў ТГ](https://t.me/belarusai)
**Падтрымаць праект:** [Buy me a coffee](https://buymeacoffee.com/tuteishygpt)
"""
)
with gr.Row():
audio_input = gr.Audio(type="filepath", label="Аўдыёфайл")
video_input = gr.Video(label="Відэафайл")
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
)
btn = gr.Button("Апрацаваць")
transcript_output = gr.Textbox(label="Транскрыпцыя", lines=10)
file_output = gr.File(label="SRT-файл")
btn.click(
fn=process_file, inputs=[audio_input, video_input], outputs=[transcript_output, file_output]
)
gr.Markdown("## Пераклад субцітраў")
with gr.Row():
language_dropdown = gr.Dropdown(
choices=["English", "Руcкая", "Польская", "Літоўская", "Нямецкая"],
label="Выберы мову перакладу",
value="English",
)
translate_btn = gr.Button("Пераклад")
translation_output = gr.Textbox(label="Пераклад", lines=10)
translation_file_output = gr.File(label="Translated SRT-файл")
translate_btn.click(
fn=translate_transcript,
inputs=[transcript_output, language_dropdown],
outputs=[translation_output, translation_file_output],
)
# Запуск з дадатковымі параметрамі для стабільнасці
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=False,
debug=False,
show_error=True,
prevent_thread_lock=True
)
except Exception as e:
logger.critical(f"Крытычная памылка пры запуску праграмы: {str(e)}", exc_info=True)
print(f"Крытычная памылка: {str(e)}")
|