Repository navigation
Download URL audio before speech extraction and plugins - #1667
Merged
Merged
Conversation
URL tasks now reach plugins after their download, under the fixed temp name audio.wav. The result file check then looked for audio*.txt/srt/vtt next to it and in the output folder, so any unrelated match marked a new URL import as skipped and gave it that file's segments. The temp name says nothing about the video, so URL imports are never skipped, as before the download moved ahead of plugins. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ozoVtp2JvfpDkZ1SpBgvW
The download's completed handler checked self.current.task, so a late completion from a canceled download could start transcription for whichever task was current by then. It now carries the task and activity token it was started for, like the error handler, and ignores signals for a task that is no longer current. This also stops a second _on_task_finished() for a task that cancel_task already finished. Between the download and the transcriber thread there is no transcriber for cancel_task to stop. A cancel there was lost: the task was set back to in progress and transcribed in full. The worker now checks for a cancel before and after speech extraction and after plugins. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ozoVtp2JvfpDkZ1SpBgvW
FileTranscriber.stop() did nothing, so canceling a download blocked the GUI thread for up to 5 s in QThread.wait() and then terminate()d a thread running Python code. stop() now sets a flag that the yt-dlp progress hook checks, raising DownloadCancelled (yt-dlp re-raises it out of extract_info), and kills the ffmpeg conversion, which now runs with Popen. Subclasses chain to it. yt-dlp can't be interrupted while it resolves the URL, so cancel_task no longer waits for a download thread. It releases the queue at once, and the download's progress and error signals are dropped once its task is no longer current, so they can't mark the next task as failed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ozoVtp2JvfpDkZ1SpBgvW
- Send task_started once per URL task. The second send, from the transcription phase, reset time_started (dropping the download from the recorded duration) and could overwrite a status written between the two phases. - Download only in download(). run() skipped the download whenever a URL task already had a file_path, so a stale path from an earlier run would have been transcribed instead of a fresh download. - Reset original_file_path after a download. A value kept from an earlier run's speech extraction pointed plugins at the previous download. - Give the download phase its own _setup_download_thread instead of a download_only flag in _setup_transcriber_thread. - Check in the test that the download runs before speech extraction, plugins and transcription, and which file each step gets. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ozoVtp2JvfpDkZ1SpBgvW
Apply ruff format only to lines this branch added. The rest of these files is left as is, since main is not ruff-formatted either. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ozoVtp2JvfpDkZ1SpBgvW
run() no longer downloads URL tasks; the queue worker calls download() first. The test called run() directly, so it now does the same. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ozoVtp2JvfpDkZ1SpBgvW
doqhu
force-pushed
the
fix/url-download-phase
branch
from
October 20, 2026 16:04
6fffe6f to
87fbd4c
Compare
- Store the downloaded audio, not the deleted speech file, for URL imports with speech extraction. - Remove the extracted speech file when a task is canceled before its transcriber starts. - Don't report a canceled speech extraction as a failure, and remove the partial file the killed process leaves behind. - Drop the pass-through stop() override in OpenAIWhisperAPIFileTranscriber. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012ozoVtp2JvfpDkZ1SpBgvW
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1667 +/- ##
==========================================
+ Coverage 83.94% 84.14% +0.20%
==========================================
Files 115 115
Lines 13835 13928 +93
==========================================
+ Hits 11614 11720 +106
+ Misses 2221 2208 -13
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
URL imports had no local file until
FileTranscriber.run()downloaded the audio. Speech extraction and thebefore_transcription/check_skipplugins run before that, so they gotfile_path=None. URL imports with Extract speech enabled could not work, and plugins never saw the audio.Fix
The download is now its own phase. For URL tasks the queue worker runs
FileTranscriber.download()on a worker thread first. When the audio is on disk, it continues with speech extraction, plugins and transcription, as for local files.Moving the download earlier exposed a few issues, fixed in separate commits:
audio.wav. The result file check then matched anyaudio*.txt/srt/vttand marked new imports as skipped. URL imports are never skipped now, which was the behaviour before.completedsignal from a canceled download could start transcription for whichever task was current by then. Download signals now carry their own task and activity token and are ignored once that task is no longer current.FileTranscriber.stop()did nothing, socancel_taskblocked the GUI thread for up to 5 s and thenterminate()d the thread.stop()now aborts yt-dlp from its progress hook (DownloadCancelled) and kills the ffmpeg conversion, which now runs withPopen.cancel_taskreleases the queue right away instead of waiting for a download thread.task_startedis sent once per URL task. A second send resettime_started.download().original_file_pathis reset after a download, so it can't point at a previous run's file._setup_download_thread.The commits can be reviewed one by one. Every commit passes the affected tests.
Testing
tests/widgets/speaker_count_test.py(MSDDDiarizer.diarize() got an unexpected keyword argument 'num_speakers'). They fail the same way onmain, and this PR doesn't touch speaker code. On machines with an NVIDIA GPU,test_should_run_file_transcription_taskcan also fail intermittently; that is fixed separately in Fix CUDA prompt firing on a deleted main window #1668.test_transcribe_from_urlcallsrun()directly, so it now callsdownload()first, as the queue worker does.stop()aborts yt-dlp and kills ffmpeg;ruff checkreports nothing new. Only the lines this PR adds are ruff-formatted; the rest of each file is unchanged.🤖 Generated with Claude Code
https://claude.ai/code/session_012ozoVtp2JvfpDkZ1SpBgvW