Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
af98fe6
refactor: remove too-many-statements em buzz/cli.py
josiasdev Jun 17, 2026
d1a453b
Merge branch 'main' into refactor/remove-code-smell-too-many-statements
josiasdev Jun 23, 2026
a49164f
refactor: remove too-many-statements em buzz/transformers_whisper.py
josiasdev Jun 25, 2026
1868238
Merge branch 'main' into refactor/remove-code-smell-too-many-statements
josiasdev Jun 25, 2026
c5c3a0a
refactor: extract run() into smaller methods to fix R0915
josiasdev Jun 26, 2026
14162b6
refactor: extrair branches do metodo run em ModelDownloader para reso…
josiasdev Jun 26, 2026
fa010af
docs: add refactoring reports for R0915 fixes
josiasdev Jun 26, 2026
114ce49
Merge branch 'main' into refactor/remove-code-smell-too-many-statements
josiasdev Jun 26, 2026
84437db
refactor: extract download_model into smaller methods to fix R0915
josiasdev Jun 26, 2026
2983aaa
Merge branch 'main' into refactor/remove-code-smell-too-many-statements
raivisdejus Jun 27, 2026
734eea5
Cleanup
raivisdejus Jun 27, 2026
281f86f
refactor: extract methods from FileTranscriber.run to fix too-many-st…
josiasdev Jun 29, 2026
b6d7eb4
fix: resolve merge conflict in file_transcriber_queue_worker.py
josiasdev Jun 29, 2026
1ad2fba
Merge branch 'main' into refactor/remove-code-smell-too-many-statements
josiasdev Jun 29, 2026
4469228
refactor: extract methods from RecordingTranscriber.start to fix too-…
josiasdev Jun 29, 2026
572ae6e
Merge branch 'main' into refactor/remove-code-smell-too-many-statements
raivisdejus Jul 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
193 changes: 98 additions & 95 deletions buzz/transcriber/file_transcriber.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,88 +38,9 @@ def __init__(self, task: FileTranscriptionTask, parent: Optional["QObject"] = No
@pyqtSlot()
def run(self):
if self.transcription_task.source == FileTranscriptionTask.Source.URL_IMPORT:
cookiefile = os.getenv("BUZZ_DOWNLOAD_COOKIEFILE")

# First extract info to get the video title
extract_options = {
"logger": logging.getLogger(),
}
if cookiefile:
extract_options["cookiefile"] = cookiefile

try:
with YoutubeDL(extract_options) as ydl_info:
info = ydl_info.extract_info(self.transcription_task.url, download=False)
video_title = info.get("title", "audio")
except Exception as exc:
logging.debug(f"Error extracting video info: {exc}")
video_title = "audio"

# Sanitize title for use as filename
video_title = YoutubeDL.sanitize_info({"title": video_title})["title"]
# Remove characters that are problematic in filenames
for char in ['/', '\\', ':', '*', '?', '"', '<', '>', '|']:
video_title = video_title.replace(char, '_')

# Create temp directory and use video title as filename
temp_dir = tempfile.mkdtemp()
temp_output_path = os.path.join(temp_dir, video_title)
wav_file = temp_output_path + ".wav"
wav_file = str(Path(wav_file).resolve())

options = {
"format": "bestaudio/best",
"progress_hooks": [self.on_download_progress],
"outtmpl": temp_output_path,
"logger": logging.getLogger(),
}

if cookiefile:
options["cookiefile"] = cookiefile

ydl = YoutubeDL(options)

try:
logging.debug(f"Downloading audio file from URL: {self.transcription_task.url}")
ydl.download([self.transcription_task.url])
except Exception as exc:
logging.debug(f"Error downloading audio: {exc.msg}")
self.error.emit(exc.msg)
if not self._download_from_url():
return

cmd = [
"ffmpeg",
"-nostdin",
"-threads", "0",
"-i", temp_output_path,
"-ac", "1",
"-ar", str(whisper_audio.SAMPLE_RATE),
"-acodec", "pcm_s16le",
"-loglevel", "panic",
wav_file
]

if sys.platform == "win32":
si = subprocess.STARTUPINFO()
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
si.wShowWindow = subprocess.SW_HIDE
result = subprocess.run(
cmd,
capture_output=True,
startupinfo=si,
env=app_env,
creationflags=subprocess.CREATE_NO_WINDOW
)
else:
result = subprocess.run(cmd, capture_output=True)

if len(result.stderr):
logging.warning(f"Error processing downloaded audio. Error: {result.stderr.decode()}")
raise Exception(f"Error processing downloaded audio: {result.stderr.decode()}")

self.transcription_task.file_path = wav_file
logging.debug(f"Downloaded audio to file: {self.transcription_task.file_path}")

try:
segments = self.transcribe()
except Exception as exc:
Expand Down Expand Up @@ -149,22 +70,104 @@ def run(self):
)

if self.transcription_task.source == FileTranscriptionTask.Source.FOLDER_WATCH:
# Use original_file_path if available (before speech extraction changed file_path)
source_path = (
self.transcription_task.original_file_path
or self.transcription_task.file_path
self._handle_folder_watch()

def _download_from_url(self) -> bool:
cookiefile = os.getenv("BUZZ_DOWNLOAD_COOKIEFILE")

extract_options = {
"logger": logging.getLogger(),
}
if cookiefile:
extract_options["cookiefile"] = cookiefile

try:
with YoutubeDL(extract_options) as ydl_info:
info = ydl_info.extract_info(self.transcription_task.url, download=False)
video_title = info.get("title", "audio")
except Exception as exc:
logging.debug(f"Error extracting video info: {exc}")
video_title = "audio"

video_title = YoutubeDL.sanitize_info({"title": video_title})["title"]
for char in ['/', '\\', ':', '*', '?', '"', '<', '>', '|']:
video_title = video_title.replace(char, '_')

temp_dir = tempfile.mkdtemp()
temp_output_path = os.path.join(temp_dir, video_title)
wav_file = temp_output_path + ".wav"
wav_file = str(Path(wav_file).resolve())

options = {
"format": "bestaudio/best",
"progress_hooks": [self.on_download_progress],
"outtmpl": temp_output_path,
"logger": logging.getLogger(),
}

if cookiefile:
options["cookiefile"] = cookiefile

ydl = YoutubeDL(options)

try:
logging.debug(f"Downloading audio file from URL: {self.transcription_task.url}")
ydl.download([self.transcription_task.url])
except Exception as exc:
logging.debug(f"Error downloading audio: {exc.msg}")
self.error.emit(exc.msg)
return False

cmd = [
"ffmpeg",
"-nostdin",
"-threads", "0",
"-i", temp_output_path,
"-ac", "1",
"-ar", str(whisper_audio.SAMPLE_RATE),
"-acodec", "pcm_s16le",
"-loglevel", "panic",
wav_file
]

if sys.platform == "win32":
si = subprocess.STARTUPINFO()
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
si.wShowWindow = subprocess.SW_HIDE
result = subprocess.run(
cmd,
capture_output=True,
startupinfo=si,
env=app_env,
creationflags=subprocess.CREATE_NO_WINDOW
)
if source_path and os.path.exists(source_path):
if self.transcription_task.delete_source_file:
os.remove(source_path)
else:
shutil.move(
source_path,
os.path.join(
self.transcription_task.output_directory,
os.path.basename(source_path),
),
)
else:
result = subprocess.run(cmd, capture_output=True)

if len(result.stderr):
logging.warning(f"Error processing downloaded audio. Error: {result.stderr.decode()}")
raise Exception(f"Error processing downloaded audio: {result.stderr.decode()}")

self.transcription_task.file_path = wav_file
logging.debug(f"Downloaded audio to file: {self.transcription_task.file_path}")
return True

def _handle_folder_watch(self):
source_path = (
self.transcription_task.original_file_path
or self.transcription_task.file_path
)
if source_path and os.path.exists(source_path):
if self.transcription_task.delete_source_file:
os.remove(source_path)
else:
shutil.move(
source_path,
os.path.join(
self.transcription_task.output_directory,
os.path.basename(source_path),
),
)

def on_download_progress(self, data: dict):
if data["status"] == "downloading":
Expand Down
Loading
Loading