From eda1398a2b9269d2bcddf174340910fbb1d64f8d Mon Sep 17 00:00:00 2001 From: yusufipk Date: Wed, 2 Sep 2026 12:43:07 +0300 Subject: [PATCH] Call the OpenRouter subtitle model the audio file model Timestamps are a file transcription option, so the model box is named after the file rather than the format it ends up in. --- dikte/api.py | 14 +++++++------- dikte/config.py | 6 +++--- dikte/i18n.py | 6 +++--- dikte/settings_ui.py | 34 +++++++++++++++++----------------- tests/test_api.py | 8 ++++---- tests/test_config.py | 14 +++++++------- tests/test_ui.py | 14 +++++++------- 7 files changed, 48 insertions(+), 48 deletions(-) diff --git a/dikte/api.py b/dikte/api.py index f74e282..13c4381 100644 --- a/dikte/api.py +++ b/dikte/api.py @@ -48,17 +48,17 @@ LOCAL_TIMEOUT = 3600 # Where a transcription request goes; built by config.Config.transcribe_target(). # `service` is the name the user sees in an error, `provider` the one the code -# branches on. `subtitle_model` is what a timestamped run asks for instead of +# branches on. `file_model` is what a timestamped run asks for instead of # `model`, where the two differ; empty means the provider's own whisper. Target = collections.namedtuple( - "Target", "provider service api_key base_url model subtitle_model", + "Target", "provider service api_key base_url model file_model", defaults=[""]) # What answers with segment times on OpenRouter when nothing else was chosen. -OPENROUTER_SUBTITLE_MODEL = "openai/whisper-1" +OPENROUTER_FILE_MODEL = "openai/whisper-1" -def timestamp_model(provider, selected="", subtitle=""): +def timestamp_model(provider, selected="", file_model=""): """Which model answers with segment times. OpenAI keeps them to whisper-1. Everything Groq transcribes with is a @@ -68,12 +68,12 @@ def timestamp_model(provider, selected="", subtitle=""): one it has never heard of. OpenRouter fronts several models that do times and several that do not, and a request to the wrong one gets a transcript with no segments in it, so the one to use is a setting of its own - (`subtitle`) and whisper-1 is only where that setting is left empty. + (`file_model`) and whisper-1 is only where that setting is left empty. """ if provider in ("groq", "local"): return selected or "whisper-large-v3-turbo" if provider == "openrouter": - return subtitle or OPENROUTER_SUBTITLE_MODEL + return file_model or OPENROUTER_FILE_MODEL return "whisper-1" @@ -456,7 +456,7 @@ def transcribe_segments(target, audio_path, language="", prompt="", timeout=300, """[(start_seconds, end_seconds, text)] using whisper-1's verbose response.""" data = _transcribe_request( target._replace(model=timestamp_model(target.provider, target.model, - target.subtitle_model)), + target.file_model)), audio_path, language, prompt, "verbose_json", granularity="segment", timeout=timeout, aborter=aborter, ) diff --git a/dikte/config.py b/dikte/config.py index 6f96f37..567d5b7 100644 --- a/dikte/config.py +++ b/dikte/config.py @@ -399,7 +399,7 @@ DEFAULTS = { "openrouter_transcribe_model": "openai/gpt-4o-transcribe", # What a timestamped run (subtitles) asks OpenRouter for: not every model # there returns segment times. Empty -> openai/whisper-1. - "openrouter_subtitle_model": "", + "openrouter_file_model": "", "language": "tr", "transcribe_prompt": "", @@ -672,9 +672,9 @@ class Config: # to land on rather than reading it from there. name = "openai" who = TRANSCRIBERS[name] - subtitle = self["openrouter_subtitle_model"] if name == "openrouter" else "" + file_model = self["openrouter_file_model"] if name == "openrouter" else "" return api.Target(name, who.service, self.api_key(who.key), - self[who.url], self[who.model], subtitle.strip()) + self[who.url], self[who.model], file_model.strip()) def transcribe_ready(self): """Whether speech to text could run right now, without opening Settings.""" diff --git a/dikte/i18n.py b/dikte/i18n.py index ecfa0e3..4ff7aea 100644 --- a/dikte/i18n.py +++ b/dikte/i18n.py @@ -228,10 +228,10 @@ TR = { "Transcript cleanup": "Transkripti temizleme", "API key": "API anahtarı", "Model": "Model", - "Subtitle model": "Altyazı modeli", - "The model a timestamped run (subtitles) asks for. Not every model on " + "Audio file model": "Ses dosyası modeli", + "The model a timestamped audio file (subtitles) is sent to. Not every model on " "OpenRouter returns segment times; empty means openai/whisper-1.": - "Zaman damgalı bir çeviride (altyazı) istenen model. OpenRouter'daki her " + "Zaman damgalı bir ses dosyasının (altyazı) gönderildiği model. OpenRouter'daki her " "model segment zamanı döndürmez; boşsa openai/whisper-1 kullanılır.", "Provider": "Sağlayıcı", "sk-… (falls back to OPENAI_API_KEY)": "sk-… (boşsa OPENAI_API_KEY kullanılır)", diff --git a/dikte/settings_ui.py b/dikte/settings_ui.py index 4cafda1..f2d4f22 100644 --- a/dikte/settings_ui.py +++ b/dikte/settings_ui.py @@ -865,14 +865,14 @@ class SettingsWindow(QDialog): self.refresh_transcribe_models) stt_form.addRow(t("Model"), self.transcribe_model_row) # OpenRouter only: which of its models a timestamped run asks for. - self.subtitle_model = QComboBox() - self.subtitle_model.setEditable(True) - self.subtitle_model.lineEdit().setPlaceholderText(api.OPENROUTER_SUBTITLE_MODEL) - self.subtitle_model.setToolTip( - t("The model a timestamped run (subtitles) asks for. Not every model " + self.file_model = QComboBox() + self.file_model.setEditable(True) + self.file_model.lineEdit().setPlaceholderText(api.OPENROUTER_FILE_MODEL) + self.file_model.setToolTip( + t("The model a timestamped audio file (subtitles) is sent to. Not every model " "on OpenRouter returns segment times; empty means openai/whisper-1.")) - self.subtitle_model_row = self._row(self.subtitle_model) - stt_form.addRow(t("Subtitle model"), self.subtitle_model_row) + self.file_model_row = self._row(self.file_model) + stt_form.addRow(t("Audio file model"), self.file_model_row) # A spanning row: in the narrow field column a wrapped label gets a # height that fits one line, and the rest of the text is cut off. self.transcribe_status = QLabel("") @@ -1756,7 +1756,7 @@ class SettingsWindow(QDialog): self._shown_provider = "" self._select_data(self.transcribe_provider, conf["transcribe_provider"]) self._provider_changed() # selecting index 0 fires no signal - self.subtitle_model.setCurrentText(conf["openrouter_subtitle_model"]) + self.file_model.setCurrentText(conf["openrouter_file_model"]) self.local_gpu.setChecked(conf["local_gpu"]) self.local_preload.setChecked(conf["local_preload"]) self.local_threads.setValue(int(conf["local_threads"])) @@ -1874,7 +1874,7 @@ class SettingsWindow(QDialog): for name, who in cfg.TRANSCRIBERS.items(): conf[who.key] = self._key_fields[name].text().strip() conf[who.model] = self._models[name].strip() or cfg.DEFAULTS[who.model] - conf["openrouter_subtitle_model"] = self.subtitle_model.currentText().strip() + conf["openrouter_file_model"] = self.file_model.currentText().strip() conf["gemini_api_key"] = self.gemini_key.text().strip() conf["opencode_api_key"] = self.opencode_key.text().strip() conf["local_model"] = self.local_whisper.selected() @@ -2048,7 +2048,7 @@ class SettingsWindow(QDialog): self._shown_provider = provider local = provider == "local" self.stt_form.setRowVisible(self.transcribe_model_row, not local) - self.stt_form.setRowVisible(self.subtitle_model_row, provider == "openrouter") + self.stt_form.setRowVisible(self.file_model_row, provider == "openrouter") self.stt_form.setRowVisible(self.transcribe_status, not local) self.stt_form.setRowVisible(self.local_whisper, local) self.stt_form.setRowVisible(self.local_options, local) @@ -2058,14 +2058,14 @@ class SettingsWindow(QDialog): self.transcribe_model.addItems(TRANSCRIBE_MODELS[provider]) self.transcribe_model.setCurrentText(self._models[provider]) if provider == "openrouter": - self._fill_subtitle_models(TRANSCRIBE_MODELS[provider]) + self._fill_file_models(TRANSCRIBE_MODELS[provider]) self.transcribe_status.setText("") - def _fill_subtitle_models(self, models): - current = self.subtitle_model.currentText() - self.subtitle_model.clear() - self.subtitle_model.addItems(models) - self.subtitle_model.setCurrentText(current) + def _fill_file_models(self, models): + current = self.file_model.currentText() + self.file_model.clear() + self.file_model.addItems(models) + self.file_model.setCurrentText(current) def _load_transcribe_models(self): """The model list of whichever provider is selected.""" @@ -2096,7 +2096,7 @@ class SettingsWindow(QDialog): self.transcribe_model.addItems(models) self.transcribe_model.setCurrentText(current) if self._shown_provider == "openrouter": - self._fill_subtitle_models(models) + self._fill_file_models(models) self.transcribe_status.setText(t("{count} models loaded.", count=len(models))) def _load_models(self): diff --git a/tests/test_api.py b/tests/test_api.py index bbc5033..50b4ef7 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -53,13 +53,13 @@ class TimestampModel(unittest.TestCase): self.assertEqual(api.timestamp_model("openai", "gpt-4o-transcribe"), "whisper-1") - def test_openrouter_takes_the_subtitle_model_that_was_set(self): + def test_openrouter_takes_the_file_model_that_was_set(self): self.assertEqual( api.timestamp_model("openrouter", "openai/gpt-4o-transcribe", "openai/whisper-large-v3"), "openai/whisper-large-v3") - def test_openrouter_with_no_subtitle_model_falls_back_to_whisper(self): + def test_openrouter_with_no_file_model_falls_back_to_whisper(self): self.assertEqual(api.timestamp_model("openrouter", "openai/gpt-4o-transcribe", ""), "openai/whisper-1") @@ -328,8 +328,8 @@ class TranscribeSegments(DikteTest): api.transcribe_segments(OPENROUTER, self.wav) self.assertEqual(multipart_fields(calls[0])["model"], "openai/whisper-1") - def test_openrouter_asks_for_the_subtitle_model_when_one_is_set(self): - target = OPENROUTER._replace(subtitle_model="mistralai/voxtral-mini-transcribe") + def test_openrouter_asks_for_the_file_model_when_one_is_set(self): + target = OPENROUTER._replace(file_model="mistralai/voxtral-mini-transcribe") with fake_urlopen(self.reply([{"start": 0, "end": 1, "text": "hi"}])) as calls: api.transcribe_segments(target, self.wav) self.assertEqual(multipart_fields(calls[0])["model"], diff --git a/tests/test_config.py b/tests/test_config.py index 03bca9c..0138a04 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -220,19 +220,19 @@ class TranscribeTarget(DikteTest): self.assertEqual(target.service, "OpenRouter") self.assertEqual(target.api_key, "sk-or-test") self.assertEqual(target.model, "openai/whisper-1") - self.assertEqual(target.subtitle_model, "") + self.assertEqual(target.file_model, "") - def test_openrouter_carries_its_subtitle_model(self): + def test_openrouter_carries_its_file_model(self): conf = self.config(transcribe_provider="openrouter", openrouter_api_key="sk-or-test", - openrouter_subtitle_model=" openai/whisper-large-v3 ") - self.assertEqual(conf.transcribe_target().subtitle_model, + openrouter_file_model=" openai/whisper-large-v3 ") + self.assertEqual(conf.transcribe_target().file_model, "openai/whisper-large-v3") - def test_only_openrouter_has_a_subtitle_model(self): + def test_only_openrouter_has_a_file_model(self): conf = self.config(transcribe_provider="openai", openai_api_key="sk-test", - openrouter_subtitle_model="openai/whisper-large-v3") - self.assertEqual(conf.transcribe_target().subtitle_model, "") + openrouter_file_model="openai/whisper-large-v3") + self.assertEqual(conf.transcribe_target().file_model, "") def test_groq_when_it_is_picked(self): conf = self.config(transcribe_provider="groq", groq_api_key="gsk-test", diff --git a/tests/test_ui.py b/tests/test_ui.py index 12751e8..25d9e4f 100644 --- a/tests/test_ui.py +++ b/tests/test_ui.py @@ -504,19 +504,19 @@ class Settings(DikteTest): self.assertEqual(conf["transcribe_model"], "gpt-4o-transcribe") self.assertEqual(conf["groq_transcribe_model"], "whisper-large-v3") - def test_the_subtitle_model_is_saved_and_only_shown_for_openrouter(self): + def test_the_file_model_is_saved_and_only_shown_for_openrouter(self): self.write_config({"transcribe_provider": "openrouter", - "openrouter_subtitle_model": "openai/whisper-large-v3"}) + "openrouter_file_model": "openai/whisper-large-v3"}) conf = cfg.Config() window = self.window(conf) - self.assertEqual(window.subtitle_model.currentText(), "openai/whisper-large-v3") - self.assertTrue(window.stt_form.isRowVisible(window.subtitle_model_row)) - window.subtitle_model.setCurrentText(" deepgram/nova-3 ") + self.assertEqual(window.file_model.currentText(), "openai/whisper-large-v3") + self.assertTrue(window.stt_form.isRowVisible(window.file_model_row)) + window.file_model.setCurrentText(" deepgram/nova-3 ") window._save() - self.assertEqual(conf["openrouter_subtitle_model"], "deepgram/nova-3") + self.assertEqual(conf["openrouter_file_model"], "deepgram/nova-3") window.transcribe_provider.setCurrentIndex( window.transcribe_provider.findData("openai")) - self.assertFalse(window.stt_form.isRowVisible(window.subtitle_model_row)) + self.assertFalse(window.stt_form.isRowVisible(window.file_model_row)) def test_the_provider_box_offers_every_provider_config_knows(self): window = self.window(cfg.Config())