intermediate commit
This commit is contained in:
12
app.py
12
app.py
@@ -115,7 +115,13 @@ def main():
|
|||||||
|
|
||||||
recognizeBtn.click(
|
recognizeBtn.click(
|
||||||
gh.handleRecognizeBtn,
|
gh.handleRecognizeBtn,
|
||||||
|
<<<<<<< HEAD
|
||||||
inputs=[audioFiles, fastWhisperModel, device, compute_type, beamSize, vadFilter, minSilenceDurationMs, speechPadMs, temp0, temp1, temp2, wordTimestamps, noSpeechThreshold, conditionOnPreviousText, gr.State(GLUED_AUDIO_FILENAME), gr.State(OUTPUT_PATH)]
|
inputs=[audioFiles, fastWhisperModel, device, compute_type, beamSize, vadFilter, minSilenceDurationMs, speechPadMs, temp0, temp1, temp2, wordTimestamps, noSpeechThreshold, conditionOnPreviousText, gr.State(GLUED_AUDIO_FILENAME), gr.State(OUTPUT_PATH)]
|
||||||
|
=======
|
||||||
|
inputs=[audioFiles, fastWhisperModel, device, compute_type, beamSize,
|
||||||
|
vadFilter, minSilenceDurationMs, speechPadMs, temp0, temp1, temp2,
|
||||||
|
wordTimestamps, noSpeechThreshold, conditionOnPreviousText, gr.State(GLUED_AUDIO_FILENAME), gr.State(OUTPUT_PATH)],
|
||||||
|
>>>>>>> 1e5105b7d658310c159c65ba318c08522506c3fb
|
||||||
outputs=[recognizedText],
|
outputs=[recognizedText],
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -123,7 +129,8 @@ def main():
|
|||||||
# автоматический пайплайн
|
# автоматический пайплайн
|
||||||
recognizedText.change(
|
recognizedText.change(
|
||||||
gh.generateByCondition,
|
gh.generateByCondition,
|
||||||
inputs=[apiKey, llmProvider, llmModel, systemPrompt, recognizedText, llmTemperature, isPipelineEnabledCheckbox, gr.State("change"), saveFileCheckbox, filename, filenamePdf, gr.State(OUTPUT_PATH)],
|
inputs=[apiKey, llmProvider, llmModel, systemPrompt, recognizedText, llmTemperature,
|
||||||
|
isPipelineEnabledCheckbox, gr.State("change"), saveFileCheckbox, filename, filenamePdf, gr.State(OUTPUT_PATH)],
|
||||||
outputs=[refinedText, refinedTextMD]
|
outputs=[refinedText, refinedTextMD]
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -137,7 +144,8 @@ def main():
|
|||||||
)
|
)
|
||||||
refineTextBtn.click(
|
refineTextBtn.click(
|
||||||
gh.generateByCondition,
|
gh.generateByCondition,
|
||||||
inputs=[apiKey, llmProvider, llmModel, systemPrompt, recognizedText, llmTemperature, isPipelineEnabledCheckbox, gr.State("click"), saveFileCheckbox, filename, filenamePdf, gr.State(OUTPUT_PATH)],
|
inputs=[apiKey, llmProvider, llmModel, systemPrompt, recognizedText, llmTemperature,
|
||||||
|
isPipelineEnabledCheckbox, gr.State("click"), saveFileCheckbox, filename, filenamePdf, gr.State(OUTPUT_PATH)],
|
||||||
outputs=[refinedText, refinedTextMD]
|
outputs=[refinedText, refinedTextMD]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,74 @@
|
|||||||
from pydub import AudioSegment
|
import subprocess
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
class GlueAudio():
|
class GlueAudio():
|
||||||
def glue(self, audio_files: list, output_path: str, output_filename: str) -> Path:
|
def glue(self, audio_files: list, output_path: str, output_filename: str) -> Path:
|
||||||
"""
|
"""
|
||||||
|
<<<<<<< HEAD
|
||||||
Склеивает аудиофайлы с помощью FFmpeg, используя промежуточный список файлов.
|
Склеивает аудиофайлы с помощью FFmpeg, используя промежуточный список файлов.
|
||||||
Этот метод чрезвычайно эффективен по памяти и скорости.
|
Этот метод чрезвычайно эффективен по памяти и скорости.
|
||||||
|
=======
|
||||||
|
Склеивает аудиофайлы РАЗНЫХ форматов с помощью FFmpeg и filter_complex.
|
||||||
|
Это универсальный и эффективный по памяти метод.
|
||||||
|
>>>>>>> 1e5105b7d658310c159c65ba318c08522506c3fb
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
audio_files (list): Список путей к исходным аудиофайлам.
|
audio_files (list): Список путей к исходным аудиофайлам.
|
||||||
output_path (str): Директория для сохранения итогового файла.
|
output_path (str): Директория для сохранения итогового файла.
|
||||||
output_filename (str): Имя итогового склеенного файла.
|
output_filename (str): Имя итогового склеенного файла.
|
||||||
|
<<<<<<< HEAD
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Path: Путь к созданному склеенному файлу.
|
Path: Путь к созданному склеенному файлу.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
=======
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Path: Путь к созданному склеенному файлу.
|
||||||
|
"""
|
||||||
|
output_dir = Path(output_path)
|
||||||
|
output_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
final_audio_path = output_dir / output_filename
|
||||||
|
|
||||||
|
if not audio_files:
|
||||||
|
raise ValueError("Список аудиофайлов для склейки пуст.")
|
||||||
|
|
||||||
|
# 1. Формируем часть команды с входными файлами (-i file1 -i file2 ...)
|
||||||
|
input_args = []
|
||||||
|
for file_path in audio_files:
|
||||||
|
input_args.extend(['-i', str(Path(file_path).resolve())])
|
||||||
|
|
||||||
|
# 2. Формируем строку для filter_complex
|
||||||
|
num_files = len(audio_files)
|
||||||
|
stream_specifiers = "".join([f"[{i}:a]" for i in range(num_files)])
|
||||||
|
filter_complex_str = f"{stream_specifiers}concat=n={num_files}:v=0:a=1[outa]"
|
||||||
|
|
||||||
|
# 3. Собираем полную команду
|
||||||
|
command = [
|
||||||
|
'ffmpeg',
|
||||||
|
*input_args, # Распаковываем список входных файлов
|
||||||
|
'-filter_complex', filter_complex_str,
|
||||||
|
'-map', '[outa]',
|
||||||
|
'-c:a', 'libmp3lame',
|
||||||
|
'-q:a', '2',
|
||||||
|
str(final_audio_path),
|
||||||
|
'-y'
|
||||||
|
]
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 4. Выполняем команду
|
||||||
|
print(f"Выполнение команды FFmpeg: {' '.join(command)}")
|
||||||
|
subprocess.run(command, check=True, capture_output=True, text=True)
|
||||||
|
print("FFmpeg успешно завершил склейку.")
|
||||||
|
|
||||||
|
except FileNotFoundError:
|
||||||
|
raise FileNotFoundError("FFmpeg не найден. Убедитесь, что он установлен и доступен в системной переменной PATH.")
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print("Ошибка при выполнении FFmpeg!")
|
||||||
|
print("Stderr:", e.stderr)
|
||||||
|
raise RuntimeError(f"Ошибка FFmpeg при склейке файлов: {e.stderr}")
|
||||||
|
|
||||||
|
return final_audio_path
|
||||||
|
>>>>>>> 1e5105b7d658310c159c65ba318c08522506c3fb
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ class GradioHandlers:
|
|||||||
self.llm_factory = llm_factory
|
self.llm_factory = llm_factory
|
||||||
|
|
||||||
def handleRecognizeBtn(
|
def handleRecognizeBtn(
|
||||||
|
<<<<<<< HEAD
|
||||||
self,
|
self,
|
||||||
audioFiles, model, device, compute_type, beamSize, vadFilter,
|
audioFiles, model, device, compute_type, beamSize, vadFilter,
|
||||||
minSilenceDurationMs, speechPadMs, temp0, temp1, temp2, wordTimestamps,
|
minSilenceDurationMs, speechPadMs, temp0, temp1, temp2, wordTimestamps,
|
||||||
@@ -27,9 +28,31 @@ class GradioHandlers:
|
|||||||
# Если FFmpeg не найден или произошла ошибка, сообщаем пользователю
|
# Если FFmpeg не найден или произошла ошибка, сообщаем пользователю
|
||||||
gr.Warning(str(e))
|
gr.Warning(str(e))
|
||||||
return "" # Возвращаем пустую строку в текстовое поле
|
return "" # Возвращаем пустую строку в текстовое поле
|
||||||
|
=======
|
||||||
|
self, audioFiles, model, device, compute_type, beamSize, vadFilter,
|
||||||
|
minSilenceDurationMs, speechPadMs, temp0, temp1, temp2,
|
||||||
|
wordTimestamps, noSpeechThreshold, conditionOnPreviousText, filename, outPath
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
glued_audio_path = self.ga.glue(
|
||||||
|
audio_files=[f.name for f in audioFiles], # Передаем список путей
|
||||||
|
output_path=outPath,
|
||||||
|
output_filename=filename
|
||||||
|
)
|
||||||
|
except (FileNotFoundError, RuntimeError) as e:
|
||||||
|
# Если FFmpeg не найден или произошла ошибка, сообщаем пользователю
|
||||||
|
gr.Warning(str(e))
|
||||||
|
return "" # Возвращаем пустую строку в текстовое поле
|
||||||
|
|
||||||
|
# Передаем путь к склеенному файлу в FasterWhisper
|
||||||
|
return self.FasterWhisper.recognize(model, device, compute_type, str(glued_audio_path), beamSize, vadFilter, minSilenceDurationMs, speechPadMs, temp0, temp1, temp2, wordTimestamps, noSpeechThreshold, conditionOnPreviousText)
|
||||||
|
>>>>>>> 1e5105b7d658310c159c65ba318c08522506c3fb
|
||||||
|
|
||||||
# Функция улучшения текста
|
# Функция улучшения текста
|
||||||
def generateByCondition(self, api_key, llm_provider, llm_model, system_prompt, recognized_text, llm_temperature, is_pipeline_enabled, trigger, isSaveFile, filename, filenamePdf, output_path):
|
def generateByCondition(self, api_key, llm_provider,
|
||||||
|
llm_model, system_prompt, recognized_text,
|
||||||
|
llm_temperature, is_pipeline_enabled, trigger,
|
||||||
|
isSaveFile, filename, filenamePdf, output_path):
|
||||||
try:
|
try:
|
||||||
# Получаем нужный провайдер через фабрику
|
# Получаем нужный провайдер через фабрику
|
||||||
provider = self.llm_factory(llm_provider, api_key)
|
provider = self.llm_factory(llm_provider, api_key)
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
from faster_whisper import WhisperModel
|
from faster_whisper import WhisperModel
|
||||||
|
|
||||||
class FasterWhisper:
|
class FasterWhisper:
|
||||||
def recognize(self, model, device, compute_type, audioFile, beamSize, vadFilter, minSilenceDurationMs, speechPadMs, temp0, temp1, temp2, wordTimestamps, noSpeechThreshold, conditionOnPreviousText):
|
def recognize(self, model, device, compute_type,
|
||||||
|
audioFile, beamSize, vadFilter,
|
||||||
|
minSilenceDurationMs, speechPadMs,
|
||||||
|
temp0, temp1, temp2, wordTimestamps,
|
||||||
|
noSpeechThreshold, conditionOnPreviousText):
|
||||||
model = WhisperModel(model, device=device, compute_type=compute_type) # Задаем модель
|
model = WhisperModel(model, device=device, compute_type=compute_type) # Задаем модель
|
||||||
|
|
||||||
segments, _ = model.transcribe( # Распознаем текст
|
segments, _ = model.transcribe( # Распознаем текст
|
||||||
@@ -22,6 +26,7 @@ class FasterWhisper:
|
|||||||
|
|
||||||
for seg in segments:
|
for seg in segments:
|
||||||
text += f"[{self.format_timestamp(seg.start)} -> {self.format_timestamp(seg.end)}] {seg.text}" + '\n'
|
text += f"[{self.format_timestamp(seg.start)} -> {self.format_timestamp(seg.end)}] {seg.text}" + '\n'
|
||||||
|
print(f"[{self.format_timestamp(seg.start)} -> {self.format_timestamp(seg.end)}] {seg.text}")
|
||||||
|
|
||||||
return text
|
return text
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user