mirror of
https://github.com/chidiwilliams/buzz.git
synced 2026-03-14 14:45:46 +01:00
Add Speechmatics API as transcriber
This commit is contained in:
parent
ff1f521a6a
commit
296fe41201
9 changed files with 340 additions and 24 deletions
|
|
@ -59,6 +59,7 @@ from buzz.transcriber.file_transcriber import FileTranscriber
|
|||
from buzz.transcriber.openai_whisper_api_file_transcriber import (
|
||||
OpenAIWhisperAPIFileTranscriber,
|
||||
)
|
||||
from buzz.transcriber.speechmatics_file_transcriber import SpeechmaticsFileTranscriber
|
||||
from buzz.transcriber.transcriber import FileTranscriptionTask, Segment
|
||||
from buzz.transcriber.whisper_file_transcriber import WhisperFileTranscriber
|
||||
|
||||
|
|
@ -173,6 +174,10 @@ class FileTranscriberQueueWorker(QObject):
|
|||
self.current_transcriber = OpenAIWhisperAPIFileTranscriber(
|
||||
task=self.current_task
|
||||
)
|
||||
elif model_type == ModelType.SPEECHMATICS:
|
||||
self.current_transcriber = SpeechmaticsFileTranscriber(
|
||||
task=self.current_task
|
||||
)
|
||||
elif (
|
||||
model_type == ModelType.WHISPER_CPP
|
||||
or model_type == ModelType.HUGGING_FACE
|
||||
|
|
|
|||
|
|
@ -162,6 +162,7 @@ class ModelType(enum.Enum):
|
|||
HUGGING_FACE = "Hugging Face"
|
||||
FASTER_WHISPER = "Faster Whisper"
|
||||
OPEN_AI_WHISPER_API = "OpenAI Whisper API"
|
||||
SPEECHMATICS = "Speechmatics"
|
||||
|
||||
@property
|
||||
def supports_initial_prompt(self):
|
||||
|
|
@ -170,7 +171,7 @@ class ModelType(enum.Enum):
|
|||
ModelType.WHISPER_CPP,
|
||||
ModelType.OPEN_AI_WHISPER_API,
|
||||
ModelType.FASTER_WHISPER,
|
||||
)
|
||||
) # SPEECHMATICS does not use an initial prompt
|
||||
|
||||
def is_available(self):
|
||||
if (
|
||||
|
|
@ -187,7 +188,7 @@ class ModelType(enum.Enum):
|
|||
ModelType.WHISPER,
|
||||
ModelType.WHISPER_CPP,
|
||||
ModelType.FASTER_WHISPER,
|
||||
)
|
||||
) # SPEECHMATICS is cloud-only, no local model
|
||||
|
||||
|
||||
HUGGING_FACE_MODEL_ALLOW_PATTERNS = [
|
||||
|
|
@ -307,6 +308,8 @@ class TranscriptionModel:
|
|||
return f"Faster Whisper ({self.whisper_model_size})"
|
||||
case ModelType.OPEN_AI_WHISPER_API:
|
||||
return "OpenAI Whisper API"
|
||||
case ModelType.SPEECHMATICS:
|
||||
return "Speechmatics"
|
||||
case _:
|
||||
raise Exception("Unknown model type")
|
||||
|
||||
|
|
@ -424,6 +427,9 @@ class TranscriptionModel:
|
|||
if self.model_type == ModelType.OPEN_AI_WHISPER_API:
|
||||
return ""
|
||||
|
||||
if self.model_type == ModelType.SPEECHMATICS:
|
||||
return "" # Cloud-only; no local model path needed
|
||||
|
||||
if self.model_type == ModelType.HUGGING_FACE:
|
||||
try:
|
||||
return huggingface_hub.snapshot_download(
|
||||
|
|
@ -780,6 +786,10 @@ class ModelDownloader(QRunnable):
|
|||
self.signals.finished.emit("")
|
||||
return
|
||||
|
||||
if self.model.model_type == ModelType.SPEECHMATICS:
|
||||
self.signals.finished.emit("") # Cloud-only; no local model to download
|
||||
return
|
||||
|
||||
raise Exception("Invalid model type: " + self.model.model_type.value)
|
||||
|
||||
def download_model_to_path(
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ class Settings:
|
|||
OPENAI_API_MODEL = "transcriber/openai-api-model"
|
||||
CUSTOM_FASTER_WHISPER_ID = "transcriber/custom-faster-whisper-id"
|
||||
HUGGINGFACE_MODEL_ID = "transcriber/huggingface-model-id"
|
||||
CUSTOM_SPEECHMATICS_URL = "transcriber/custom-speechmatics-url"
|
||||
SPEECHMATICS_API_KEY = "transcriber/speechmatics-api-key"
|
||||
|
||||
SHORTCUTS = "shortcuts"
|
||||
|
||||
|
|
|
|||
199
buzz/transcriber/speechmatics_file_transcriber.py
Normal file
199
buzz/transcriber/speechmatics_file_transcriber.py
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
import asyncio
|
||||
import logging
|
||||
import time
|
||||
from typing import Optional, List
|
||||
|
||||
from PyQt6.QtCore import QObject
|
||||
from speechmatics.batch._models import Transcript
|
||||
|
||||
from buzz.settings.settings import Settings
|
||||
from buzz.transcriber.file_transcriber import FileTranscriber
|
||||
from buzz.transcriber.transcriber import FileTranscriptionTask, Segment, Stopped
|
||||
|
||||
|
||||
class SpeechmaticsFileTranscriber(FileTranscriber):
|
||||
"""Batch transcription via the Speechmatics cloud API (speechmatics-batch package)."""
|
||||
|
||||
def __init__(self, task: FileTranscriptionTask, parent: Optional["QObject"] = None):
|
||||
super().__init__(task=task, parent=parent)
|
||||
self._stopped = False
|
||||
settings = Settings()
|
||||
self.custom_speechmatics_url = settings.value(
|
||||
key=Settings.Key.CUSTOM_SPEECHMATICS_URL, default_value=""
|
||||
)
|
||||
logging.debug("Will use speechmatics API on %s", self.custom_speechmatics_url)
|
||||
|
||||
def transcribe(self) -> List[Segment]:
|
||||
api_key = self.transcription_task.transcription_options.speechmatics_access_token
|
||||
if not api_key:
|
||||
raise Exception(
|
||||
"Speechmatics API key is not set. Please enter your API key in the settings."
|
||||
)
|
||||
|
||||
language = self.transcription_task.transcription_options.language or "auto"
|
||||
file_path = self.transcription_task.file_path
|
||||
identify_speaker = self.transcription_task.transcription_options.identify_speaker
|
||||
|
||||
logging.debug(
|
||||
"Starting Speechmatics batch transcription: file=%s, language=%s",
|
||||
file_path,
|
||||
language,
|
||||
)
|
||||
|
||||
self.progress.emit((0, 100))
|
||||
|
||||
return asyncio.run(self._run_transcription(api_key, language, file_path, identify_speaker))
|
||||
|
||||
async def _run_transcription(
|
||||
self, api_key: str, language: str, file_path: str, identify_speaker: bool
|
||||
) -> List[Segment]:
|
||||
from speechmatics.batch import (
|
||||
AsyncClient,
|
||||
JobConfig,
|
||||
JobType,
|
||||
JobStatus,
|
||||
TranscriptionConfig,
|
||||
FormatType,
|
||||
)
|
||||
|
||||
async with AsyncClient(
|
||||
api_key=api_key,
|
||||
url=self.custom_speechmatics_url if self.custom_speechmatics_url else None,
|
||||
) as client:
|
||||
config = JobConfig(
|
||||
type=JobType.TRANSCRIPTION,
|
||||
transcription_config=TranscriptionConfig(language=language),
|
||||
)
|
||||
|
||||
logging.debug("Submitting Speechmatics job for file: %s", file_path)
|
||||
job = await client.submit_job(file_path, config=config)
|
||||
logging.debug("Speechmatics job submitted: id=%s", job.id)
|
||||
|
||||
self.progress.emit((10, 100))
|
||||
|
||||
# Poll until complete or stopped
|
||||
poll_interval = 3.0
|
||||
while True:
|
||||
if self._stopped:
|
||||
logging.debug("Speechmatics transcription stopped by user")
|
||||
raise Stopped()
|
||||
|
||||
job_info = await client.get_job_info(job.id)
|
||||
status = job_info.status
|
||||
logging.debug("Speechmatics job %s status: %s", job.id, status)
|
||||
|
||||
if status == JobStatus.DONE:
|
||||
break
|
||||
elif status in (JobStatus.REJECTED, JobStatus.DELETED):
|
||||
raise Exception(
|
||||
f"Speechmatics job failed with status: {status.value}"
|
||||
)
|
||||
|
||||
# Emit a rough progress update while waiting
|
||||
self.progress.emit((20, 100))
|
||||
await asyncio.sleep(poll_interval)
|
||||
|
||||
# Retrieve JSON transcript
|
||||
logging.debug("Retrieving Speechmatics transcript for job: %s", job.id)
|
||||
self.progress.emit((90, 100))
|
||||
result = await client.get_transcript(job.id, format_type=FormatType.JSON)
|
||||
|
||||
segments = self._parse_segments(result, identify_speaker)
|
||||
self.progress.emit((100, 100))
|
||||
logging.debug(
|
||||
"Speechmatics transcription complete: %d segments", len(segments)
|
||||
)
|
||||
return segments
|
||||
|
||||
def _parse_segments(self, transcript: Transcript, identify_speaker: bool) -> List[Segment]:
|
||||
"""Parse Speechmatics JSON result into Segment objects.
|
||||
|
||||
The JSON-v2 result has a `results` list where each item has:
|
||||
- start_time (float, seconds)
|
||||
- end_time (float, seconds)
|
||||
- alternatives: list of dicts with 'content' key
|
||||
- type: 'word' | 'punctuation'
|
||||
We group consecutive words/punctuation into sentence-level segments
|
||||
by collapsing them all into a single segment per result item.
|
||||
"""
|
||||
if not transcript.results:
|
||||
return []
|
||||
|
||||
# Get language pack info for word delimiter
|
||||
word_delimiter = " " # Default
|
||||
if transcript.metadata and transcript.metadata.language_pack_info and "word_delimiter" in transcript.metadata.language_pack_info:
|
||||
word_delimiter = transcript.metadata.language_pack_info["word_delimiter"]
|
||||
|
||||
# Group results by speaker and process
|
||||
segments = []
|
||||
current_speaker = None
|
||||
current_start = None
|
||||
current_end = None
|
||||
current_group: list[str] = []
|
||||
prev_eos = "word"
|
||||
|
||||
for result in transcript.results:
|
||||
if not result.alternatives:
|
||||
continue
|
||||
|
||||
alternative = result.alternatives[0]
|
||||
content = alternative.content
|
||||
speaker = alternative.speaker
|
||||
|
||||
# Handle speaker changes, end of sentence or if segment is too long
|
||||
if speaker != current_speaker or prev_eos or (current_end - current_start > 60):
|
||||
# Process accumulated group for previous speaker
|
||||
if current_group:
|
||||
text = transcript._join_content_items(current_group, word_delimiter)
|
||||
if current_speaker:
|
||||
text = f"{current_speaker}: {text}" if identify_speaker else text
|
||||
segments.append(
|
||||
Segment(
|
||||
start=int(current_start * 1000),
|
||||
end=int(current_end * 1000),
|
||||
text=text,
|
||||
)
|
||||
)
|
||||
else:
|
||||
segments.append(Segment(
|
||||
start=int(current_start * 1000),
|
||||
end=int(current_end * 1000),
|
||||
text=text,
|
||||
))
|
||||
current_group = []
|
||||
current_start = None
|
||||
|
||||
current_speaker = speaker
|
||||
|
||||
# Add content to current group
|
||||
if content:
|
||||
current_group.append(content)
|
||||
prev_eos = result.type == "punctuation" and content in ".?!"
|
||||
|
||||
if current_start is None:
|
||||
current_start = result.start_time
|
||||
current_end = result.end_time
|
||||
|
||||
# Process final group
|
||||
if current_group:
|
||||
text = transcript._join_content_items(current_group, word_delimiter)
|
||||
if current_speaker:
|
||||
text = f"{current_speaker}: {text}" if identify_speaker else text
|
||||
segments.append(
|
||||
Segment(
|
||||
start=int(current_start * 1000),
|
||||
end=int(current_end * 1000),
|
||||
text=text,
|
||||
)
|
||||
)
|
||||
else:
|
||||
segments.append(Segment(
|
||||
start=int(current_start * 1000),
|
||||
end=int(current_end * 1000),
|
||||
text=text,
|
||||
))
|
||||
|
||||
return segments
|
||||
|
||||
def stop(self):
|
||||
self._stopped = True
|
||||
|
|
@ -150,6 +150,10 @@ class TranscriptionOptions:
|
|||
openai_access_token: str = field(
|
||||
default="", metadata=config(exclude=Exclude.ALWAYS)
|
||||
)
|
||||
speechmatics_access_token: str = field(
|
||||
default="", metadata=config(exclude=Exclude.ALWAYS)
|
||||
)
|
||||
identify_speaker: bool = False
|
||||
enable_llm_translation: bool = False
|
||||
llm_prompt: str = ""
|
||||
llm_model: str = ""
|
||||
|
|
|
|||
|
|
@ -137,6 +137,18 @@ class GeneralPreferencesWidget(QWidget):
|
|||
self.openai_api_model_line_edit.setPlaceholderText("whisper-1")
|
||||
layout.addRow(_("OpenAI API model"), self.openai_api_model_line_edit)
|
||||
|
||||
self.custom_speechmatics_url = self.settings.value(
|
||||
key=Settings.Key.CUSTOM_SPEECHMATICS_URL, default_value=""
|
||||
)
|
||||
|
||||
self.custom_speechmatics_url_line_edit = LineEdit(self.custom_speechmatics_url, self)
|
||||
self.custom_speechmatics_url_line_edit.textChanged.connect(
|
||||
self.on_custom_speechmatics_url_changed
|
||||
)
|
||||
self.custom_speechmatics_url_line_edit.setMinimumWidth(200)
|
||||
self.custom_speechmatics_url_line_edit.setPlaceholderText("https://asr.api.speechmatics.com/v2")
|
||||
layout.addRow(_("Speechmatics base url"), self.custom_speechmatics_url_line_edit)
|
||||
|
||||
default_export_file_name = self.settings.get_default_export_file_template()
|
||||
|
||||
default_export_file_name_line_edit = LineEdit(default_export_file_name, self)
|
||||
|
|
@ -263,6 +275,9 @@ class GeneralPreferencesWidget(QWidget):
|
|||
def on_openai_api_model_changed(self, text: str):
|
||||
self.settings.set_value(Settings.Key.OPENAI_API_MODEL, text)
|
||||
|
||||
def on_custom_speechmatics_url_changed(self, text: str):
|
||||
self.settings.set_value(Settings.Key.CUSTOM_SPEECHMATICS_URL, text)
|
||||
|
||||
def on_recording_export_enable_changed(self, state: int):
|
||||
self.recording_export_enabled = state == 2
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ import logging
|
|||
import platform
|
||||
from typing import Optional, List
|
||||
|
||||
from PyQt6.QtCore import pyqtSignal, QLocale
|
||||
from PyQt6.QtCore import pyqtSignal, Qt, QLocale
|
||||
from PyQt6.QtGui import QIcon
|
||||
from PyQt6.QtWidgets import QGroupBox, QWidget, QFormLayout, QComboBox, QLabel, QHBoxLayout
|
||||
from PyQt6.QtWidgets import QGroupBox, QWidget, QFormLayout, QComboBox, QLabel, QHBoxLayout, QLineEdit, QCheckBox
|
||||
|
||||
from buzz.locale import _
|
||||
from buzz.settings.settings import Settings
|
||||
|
|
@ -98,6 +98,31 @@ class TranscriptionOptionsGroupBox(QGroupBox):
|
|||
self.mms_language_line_edit.languageChanged.connect(self.on_mms_language_changed)
|
||||
self.mms_language_line_edit.setVisible(False)
|
||||
|
||||
# Speechmatics API key field
|
||||
speechmatics_api_key = self.settings.value(
|
||||
Settings.Key.SPEECHMATICS_API_KEY, default_value=""
|
||||
)
|
||||
# Pre-populate from settings if present, or from passed-in options
|
||||
if speechmatics_api_key:
|
||||
self.transcription_options.speechmatics_access_token = speechmatics_api_key
|
||||
self.speechmatics_api_key_edit = QLineEdit(self)
|
||||
self.speechmatics_api_key_edit.setPlaceholderText(_("Enter Speechmatics API key"))
|
||||
self.speechmatics_api_key_edit.setEchoMode(QLineEdit.EchoMode.Password)
|
||||
self.speechmatics_api_key_edit.setText(
|
||||
self.transcription_options.speechmatics_access_token
|
||||
)
|
||||
self.speechmatics_api_key_edit.textChanged.connect(
|
||||
self.on_speechmatics_api_key_changed
|
||||
)
|
||||
|
||||
self.identify_speaker_checkbox = QCheckBox(
|
||||
"Identify Speaker", parent=self
|
||||
)
|
||||
self.identify_speaker_checkbox.setChecked(self.transcription_options.identify_speaker)
|
||||
self.identify_speaker_checkbox.stateChanged.connect(
|
||||
self.on_identify_speaker_changed
|
||||
)
|
||||
|
||||
self.advanced_settings_button = AdvancedSettingsButton(self)
|
||||
self.advanced_settings_button.clicked.connect(self.open_advanced_settings)
|
||||
|
||||
|
|
@ -127,6 +152,8 @@ class TranscriptionOptionsGroupBox(QGroupBox):
|
|||
self.form_layout.addRow(_("Task:"), self.tasks_combo_box)
|
||||
self.form_layout.addRow(_("Language:"), self.languages_combo_box)
|
||||
self.form_layout.addRow(_("Language:"), self.mms_language_line_edit)
|
||||
self.form_layout.addRow(_("Api Key:"), self.speechmatics_api_key_edit)
|
||||
self.form_layout.addRow("", self.identify_speaker_checkbox)
|
||||
|
||||
self.reset_visible_rows()
|
||||
|
||||
|
|
@ -138,6 +165,15 @@ class TranscriptionOptionsGroupBox(QGroupBox):
|
|||
self.transcription_options.openai_access_token = access_token
|
||||
self.transcription_options_changed.emit(self.transcription_options)
|
||||
|
||||
def on_speechmatics_api_key_changed(self, api_key: str):
|
||||
self.transcription_options.speechmatics_access_token = api_key
|
||||
self.settings.set_value(Settings.Key.SPEECHMATICS_API_KEY, api_key)
|
||||
self.transcription_options_changed.emit(self.transcription_options)
|
||||
|
||||
def on_identify_speaker_changed(self, state: int):
|
||||
self.transcription_options.identify_speaker = state == Qt.CheckState.Checked.value
|
||||
self.transcription_options_changed.emit(self.transcription_options)
|
||||
|
||||
def on_language_changed(self, language: str):
|
||||
if language == "":
|
||||
language = None
|
||||
|
|
@ -243,6 +279,20 @@ class TranscriptionOptionsGroupBox(QGroupBox):
|
|||
self.openai_access_token_edit, model_type == ModelType.OPEN_AI_WHISPER_API
|
||||
)
|
||||
|
||||
self.form_layout.setRowVisible(
|
||||
self.speechmatics_api_key_edit, model_type == ModelType.SPEECHMATICS
|
||||
)
|
||||
|
||||
self.form_layout.setRowVisible(
|
||||
self.identify_speaker_checkbox, model_type == ModelType.SPEECHMATICS
|
||||
)
|
||||
|
||||
# Hide task/model-size controls for Speechmatics (cloud handles it)
|
||||
self.form_layout.setRowVisible(
|
||||
self.tasks_combo_box,
|
||||
model_type != ModelType.SPEECHMATICS,
|
||||
)
|
||||
|
||||
# Note on Apple Silicon Macs
|
||||
if self.load_note_tooltip_icon is not None:
|
||||
self.load_note_tooltip_icon.setVisible(
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ dependencies = [
|
|||
"posthog>=3.23.0,<4",
|
||||
# This version works, newer have issues on Windows
|
||||
"onnxruntime==1.18.1",
|
||||
"onnx>=1.20.0", # Required for nemo-toolkit, ensures ml-dtypes is installed
|
||||
"onnx>=1.20.0", # Required for nemo-toolkit, ensures ml-dtypes is installed
|
||||
"vulkan>=1.3.275.1,<2",
|
||||
"hf-xet>=1.1.5,<2",
|
||||
"hatchling>=1.28.0",
|
||||
|
|
@ -85,6 +85,7 @@ dependencies = [
|
|||
"torch>=2.2.2",
|
||||
"torchaudio>=2.2.2",
|
||||
"datasets>=4.4.1",
|
||||
"speechmatics-batch>=0.4.5",
|
||||
]
|
||||
repository = "https://github.com/chidiwilliams/buzz"
|
||||
documentation = "https://chidiwilliams.github.io/buzz/docs"
|
||||
|
|
|
|||
68
uv.lock
generated
68
uv.lock
generated
|
|
@ -1,8 +1,9 @@
|
|||
version = 1
|
||||
revision = 3
|
||||
revision = 2
|
||||
requires-python = "==3.12.*"
|
||||
resolution-markers = [
|
||||
"(platform_machine != 'aarch64' and sys_platform == 'linux') or (platform_python_implementation != 'CPython' and sys_platform == 'linux')",
|
||||
"platform_machine != 'aarch64' and sys_platform == 'linux'",
|
||||
"platform_machine == 'aarch64' and platform_python_implementation != 'CPython' and sys_platform == 'linux'",
|
||||
"sys_platform != 'darwin' and sys_platform != 'linux'",
|
||||
"platform_machine == 'aarch64' and platform_python_implementation == 'CPython' and sys_platform == 'linux'",
|
||||
"platform_machine == 'arm64' and sys_platform == 'darwin'",
|
||||
|
|
@ -45,6 +46,15 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/9f/d2/c581486aa6c4fbd7394c23c47b83fa1a919d34194e16944241daf9e762dd/accelerate-1.12.0-py3-none-any.whl", hash = "sha256:3e2091cd341423207e2f084a6654b1efcd250dc326f2a37d6dde446e07cabb11", size = 380935, upload-time = "2025-11-21T11:27:44.522Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aiofiles"
|
||||
version = "25.1.0"
|
||||
source = { registry = "https://pypi.org/simple/" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/41/c3/534eac40372d8ee36ef40df62ec129bee4fdb5ad9706e58a29be53b2c970/aiofiles-25.1.0.tar.gz", hash = "sha256:a8d728f0a29de45dc521f18f07297428d56992a742f0cd2701ba86e44d23d5b2", size = 46354, upload-time = "2025-10-09T20:51:04.358Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/8a/340a1555ae33d7354dbca4faa54948d76d89a27ceef032c8c3bc661d003e/aiofiles-25.1.0-py3-none-any.whl", hash = "sha256:abe311e527c862958650f9438e859c1fa7568a141b22abcd015e120e86a85695", size = 14668, upload-time = "2025-10-09T20:51:03.174Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aiohappyeyeballs"
|
||||
version = "2.6.1"
|
||||
|
|
@ -233,7 +243,8 @@ name = "bitsandbytes"
|
|||
version = "0.47.0"
|
||||
source = { registry = "https://pypi.org/simple/" }
|
||||
resolution-markers = [
|
||||
"(platform_machine != 'aarch64' and sys_platform == 'linux') or (platform_python_implementation != 'CPython' and sys_platform == 'linux')",
|
||||
"platform_machine != 'aarch64' and sys_platform == 'linux'",
|
||||
"platform_machine == 'aarch64' and platform_python_implementation != 'CPython' and sys_platform == 'linux'",
|
||||
"sys_platform != 'darwin' and sys_platform != 'linux'",
|
||||
"platform_machine == 'aarch64' and platform_python_implementation == 'CPython' and sys_platform == 'linux'",
|
||||
]
|
||||
|
|
@ -324,6 +335,7 @@ dependencies = [
|
|||
{ name = "requests" },
|
||||
{ name = "sounddevice" },
|
||||
{ name = "soundfile" },
|
||||
{ name = "speechmatics-batch" },
|
||||
{ name = "srt-equalizer" },
|
||||
{ name = "stable-ts" },
|
||||
{ name = "submitit" },
|
||||
|
|
@ -331,9 +343,9 @@ dependencies = [
|
|||
{ name = "torch", version = "2.8.0", source = { registry = "https://pypi.org/simple/" }, marker = "platform_machine != 'x86_64' and sys_platform == 'darwin'" },
|
||||
{ name = "torch", version = "2.8.0+cu129", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "sys_platform != 'darwin'" },
|
||||
{ name = "torchaudio", version = "2.2.2", source = { registry = "https://pypi.org/simple/" }, marker = "platform_machine == 'x86_64' and sys_platform == 'darwin'" },
|
||||
{ name = "torchaudio", version = "2.8.0", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "platform_machine == 'aarch64' and platform_python_implementation == 'CPython' and sys_platform == 'linux'" },
|
||||
{ name = "torchaudio", version = "2.8.0", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },
|
||||
{ name = "torchaudio", version = "2.8.0", source = { registry = "https://pypi.org/simple/" }, marker = "platform_machine != 'x86_64' and sys_platform == 'darwin'" },
|
||||
{ name = "torchaudio", version = "2.8.0+cu129", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or (platform_python_implementation != 'CPython' and sys_platform == 'linux') or (sys_platform != 'darwin' and sys_platform != 'linux')" },
|
||||
{ name = "torchaudio", version = "2.8.0+cu129", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or (sys_platform != 'darwin' and sys_platform != 'linux')" },
|
||||
{ name = "torchcodec", marker = "platform_machine != 'x86_64' or sys_platform != 'darwin'" },
|
||||
{ name = "tqdm" },
|
||||
{ name = "transformers" },
|
||||
|
|
@ -415,6 +427,7 @@ requires-dist = [
|
|||
{ name = "requests", specifier = ">=2.31.0,<3" },
|
||||
{ name = "sounddevice", specifier = ">=0.5.3,<0.6" },
|
||||
{ name = "soundfile", specifier = ">=0.13.1,<0.14" },
|
||||
{ name = "speechmatics-batch", specifier = ">=0.4.5" },
|
||||
{ name = "srt-equalizer", specifier = ">=0.1.10,<0.2" },
|
||||
{ name = "stable-ts", specifier = ">=2.19.1,<3" },
|
||||
{ name = "submitit", specifier = ">=1.5.2,<2" },
|
||||
|
|
@ -714,7 +727,8 @@ name = "ctranslate2"
|
|||
version = "4.6.2"
|
||||
source = { registry = "https://pypi.org/simple/" }
|
||||
resolution-markers = [
|
||||
"(platform_machine != 'aarch64' and sys_platform == 'linux') or (platform_python_implementation != 'CPython' and sys_platform == 'linux')",
|
||||
"platform_machine != 'aarch64' and sys_platform == 'linux'",
|
||||
"platform_machine == 'aarch64' and platform_python_implementation != 'CPython' and sys_platform == 'linux'",
|
||||
"sys_platform != 'darwin' and sys_platform != 'linux'",
|
||||
"platform_machine == 'aarch64' and platform_python_implementation == 'CPython' and sys_platform == 'linux'",
|
||||
"platform_machine == 'arm64' and sys_platform == 'darwin'",
|
||||
|
|
@ -1132,6 +1146,7 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/f8/0a/a3871375c7b9727edaeeea994bfff7c63ff7804c9829c19309ba2e058807/greenlet-3.3.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:b01548f6e0b9e9784a2c99c5651e5dc89ffcbe870bc5fb2e5ef864e9cc6b5dcb", size = 276379, upload-time = "2025-12-04T14:23:30.498Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/ab/7ebfe34dce8b87be0d11dae91acbf76f7b8246bf9d6b319c741f99fa59c6/greenlet-3.3.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:349345b770dc88f81506c6861d22a6ccd422207829d2c854ae2af8025af303e3", size = 597294, upload-time = "2025-12-04T14:50:06.847Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/39/f1c8da50024feecd0793dbd5e08f526809b8ab5609224a2da40aad3a7641/greenlet-3.3.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e8e18ed6995e9e2c0b4ed264d2cf89260ab3ac7e13555b8032b25a74c6d18655", size = 607742, upload-time = "2025-12-04T14:57:42.349Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/cb/43692bcd5f7a0da6ec0ec6d58ee7cddb606d055ce94a62ac9b1aa481e969/greenlet-3.3.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c024b1e5696626890038e34f76140ed1daf858e37496d33f2af57f06189e70d7", size = 622297, upload-time = "2025-12-04T15:07:13.552Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/75/b0/6bde0b1011a60782108c01de5913c588cf51a839174538d266de15e4bf4d/greenlet-3.3.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:047ab3df20ede6a57c35c14bf5200fcf04039d50f908270d3f9a7a82064f543b", size = 609885, upload-time = "2025-12-04T14:26:02.368Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/49/0e/49b46ac39f931f59f987b7cd9f34bfec8ef81d2a1e6e00682f55be5de9f4/greenlet-3.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2d9ad37fc657b1102ec880e637cccf20191581f75c64087a549e66c57e1ceb53", size = 1567424, upload-time = "2025-12-04T15:04:23.757Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/f5/49a9ac2dff7f10091935def9165c90236d8f175afb27cbed38fb1d61ab6b/greenlet-3.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83cd0e36932e0e7f36a64b732a6f60c2fc2df28c351bae79fbaf4f8092fe7614", size = 1636017, upload-time = "2025-12-04T14:27:29.688Z" },
|
||||
|
|
@ -2375,7 +2390,7 @@ name = "nvidia-cufft-cu12"
|
|||
version = "11.4.1.4"
|
||||
source = { registry = "https://download.pytorch.org/whl/cu129" }
|
||||
dependencies = [
|
||||
{ name = "nvidia-nvjitlink-cu12", marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or (platform_python_implementation != 'CPython' and sys_platform == 'linux')" },
|
||||
{ name = "nvidia-nvjitlink-cu12", marker = "platform_machine != 'aarch64' and sys_platform == 'linux'" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://pypi.nvidia.com/nvidia-cufft-cu12/nvidia_cufft_cu12-11.4.1.4-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c67884f2a7d276b4b80eb56a79322a95df592ae5e765cf1243693365ccab4e28" },
|
||||
|
|
@ -2402,9 +2417,9 @@ name = "nvidia-cusolver-cu12"
|
|||
version = "11.7.5.82"
|
||||
source = { registry = "https://download.pytorch.org/whl/cu129" }
|
||||
dependencies = [
|
||||
{ name = "nvidia-cublas-cu12", marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or (platform_python_implementation != 'CPython' and sys_platform == 'linux')" },
|
||||
{ name = "nvidia-cusparse-cu12", marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or (platform_python_implementation != 'CPython' and sys_platform == 'linux')" },
|
||||
{ name = "nvidia-nvjitlink-cu12", marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or (platform_python_implementation != 'CPython' and sys_platform == 'linux')" },
|
||||
{ name = "nvidia-cublas-cu12", marker = "platform_machine != 'aarch64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-cusparse-cu12", marker = "platform_machine != 'aarch64' and sys_platform == 'linux'" },
|
||||
{ name = "nvidia-nvjitlink-cu12", marker = "platform_machine != 'aarch64' and sys_platform == 'linux'" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://pypi.nvidia.com/nvidia-cusolver-cu12/nvidia_cusolver_cu12-11.7.5.82-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:15da72d1340d29b5b3cf3fd100e3cd53421dde36002eda6ed93811af63c40d88" },
|
||||
|
|
@ -2415,7 +2430,7 @@ name = "nvidia-cusparse-cu12"
|
|||
version = "12.5.10.65"
|
||||
source = { registry = "https://download.pytorch.org/whl/cu129" }
|
||||
dependencies = [
|
||||
{ name = "nvidia-nvjitlink-cu12", marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or (platform_python_implementation != 'CPython' and sys_platform == 'linux')" },
|
||||
{ name = "nvidia-nvjitlink-cu12", marker = "platform_machine != 'aarch64' and sys_platform == 'linux'" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://pypi.nvidia.com/nvidia-cusparse-cu12/nvidia_cusparse_cu12-12.5.10.65-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:73060ce019ac064a057267c585bf1fd5a353734151f87472ff02b2c5c9984e78" },
|
||||
|
|
@ -2552,9 +2567,9 @@ dependencies = [
|
|||
{ name = "torch", version = "2.8.0", source = { registry = "https://pypi.org/simple/" }, marker = "platform_machine != 'x86_64' and sys_platform == 'darwin'" },
|
||||
{ name = "torch", version = "2.8.0+cu129", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "sys_platform != 'darwin'" },
|
||||
{ name = "torchaudio", version = "2.2.2", source = { registry = "https://pypi.org/simple/" }, marker = "platform_machine == 'x86_64' and sys_platform == 'darwin'" },
|
||||
{ name = "torchaudio", version = "2.8.0", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "platform_machine == 'aarch64' and platform_python_implementation == 'CPython' and sys_platform == 'linux'" },
|
||||
{ name = "torchaudio", version = "2.8.0", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },
|
||||
{ name = "torchaudio", version = "2.8.0", source = { registry = "https://pypi.org/simple/" }, marker = "platform_machine != 'x86_64' and sys_platform == 'darwin'" },
|
||||
{ name = "torchaudio", version = "2.8.0+cu129", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or (platform_python_implementation != 'CPython' and sys_platform == 'linux') or (sys_platform != 'darwin' and sys_platform != 'linux')" },
|
||||
{ name = "torchaudio", version = "2.8.0+cu129", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or (sys_platform != 'darwin' and sys_platform != 'linux')" },
|
||||
{ name = "tqdm" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/42/ef/4ad54e3ecb1e89f7f7bdb4c7b751e43754e892d3c32a8550e5d0882565df/openunmix-1.3.0.tar.gz", hash = "sha256:cc9245ce728700f5d0b72c67f01be4162777e617cdc47f9b035963afac180fc8", size = 45889, upload-time = "2024-04-16T11:10:47.121Z" }
|
||||
|
|
@ -3790,6 +3805,19 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/ce/04/530252227f4d0721a5524a936336485dfb429bb206a66baf8e470384f4a2/soxr-1.0.0-cp312-abi3-win_amd64.whl", hash = "sha256:2a3b77b115ae7c478eecdbd060ed4f61beda542dfb70639177ac263aceda42a2", size = 172070, upload-time = "2025-09-07T13:22:07.62Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "speechmatics-batch"
|
||||
version = "0.4.5"
|
||||
source = { registry = "https://pypi.org/simple/" }
|
||||
dependencies = [
|
||||
{ name = "aiofiles" },
|
||||
{ name = "aiohttp" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/fa/f5/68239c57174972ed0b717b141e256881d9fad50c2cb230a0140650f38bd6/speechmatics_batch-0.4.5.tar.gz", hash = "sha256:02328a567eceaecb6791f0b80b912c7b6f95a0a403aeab2bc3b7ff9933ed47a6", size = 22224, upload-time = "2026-02-02T15:34:41.347Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/15/f2/951d12504d371909804995c57ab7c96ad3c0b3a2f3148bef2f69991303a2/speechmatics_batch-0.4.5-py3-none-any.whl", hash = "sha256:0303d86cf3e17186fef8ca38018f17099063e318b9965e81ee90ccbd7fdef4c8", size = 22868, upload-time = "2026-02-02T15:34:39.303Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlalchemy"
|
||||
version = "2.0.44"
|
||||
|
|
@ -3840,9 +3868,9 @@ dependencies = [
|
|||
{ name = "torch", version = "2.8.0", source = { registry = "https://pypi.org/simple/" }, marker = "platform_machine != 'x86_64' and sys_platform == 'darwin'" },
|
||||
{ name = "torch", version = "2.8.0+cu129", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "sys_platform != 'darwin'" },
|
||||
{ name = "torchaudio", version = "2.2.2", source = { registry = "https://pypi.org/simple/" }, marker = "platform_machine == 'x86_64' and sys_platform == 'darwin'" },
|
||||
{ name = "torchaudio", version = "2.8.0", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "platform_machine == 'aarch64' and platform_python_implementation == 'CPython' and sys_platform == 'linux'" },
|
||||
{ name = "torchaudio", version = "2.8.0", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },
|
||||
{ name = "torchaudio", version = "2.8.0", source = { registry = "https://pypi.org/simple/" }, marker = "platform_machine != 'x86_64' and sys_platform == 'darwin'" },
|
||||
{ name = "torchaudio", version = "2.8.0+cu129", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or (platform_python_implementation != 'CPython' and sys_platform == 'linux') or (sys_platform != 'darwin' and sys_platform != 'linux')" },
|
||||
{ name = "torchaudio", version = "2.8.0+cu129", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or (sys_platform != 'darwin' and sys_platform != 'linux')" },
|
||||
{ name = "tqdm" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/94/d9/d326f9dbbb7da6806aa8cfc080342e5f78dc33552f4339bdc8a6251d11a3/stable_ts-2.19.1.tar.gz", hash = "sha256:0ecaf1ed93e029839569618d2da9a57b883ad04db21f0680146e0650caaf4f52", size = 189132, upload-time = "2025-08-16T16:53:48.811Z" }
|
||||
|
|
@ -4105,7 +4133,8 @@ name = "torch"
|
|||
version = "2.8.0+cu129"
|
||||
source = { registry = "https://download.pytorch.org/whl/cu129" }
|
||||
resolution-markers = [
|
||||
"(platform_machine != 'aarch64' and sys_platform == 'linux') or (platform_python_implementation != 'CPython' and sys_platform == 'linux')",
|
||||
"platform_machine != 'aarch64' and sys_platform == 'linux'",
|
||||
"platform_machine == 'aarch64' and platform_python_implementation != 'CPython' and sys_platform == 'linux'",
|
||||
"sys_platform != 'darwin' and sys_platform != 'linux'",
|
||||
"platform_machine == 'aarch64' and platform_python_implementation == 'CPython' and sys_platform == 'linux'",
|
||||
]
|
||||
|
|
@ -4158,10 +4187,11 @@ name = "torchaudio"
|
|||
version = "2.8.0"
|
||||
source = { registry = "https://download.pytorch.org/whl/cu129" }
|
||||
resolution-markers = [
|
||||
"platform_machine == 'aarch64' and platform_python_implementation != 'CPython' and sys_platform == 'linux'",
|
||||
"platform_machine == 'aarch64' and platform_python_implementation == 'CPython' and sys_platform == 'linux'",
|
||||
]
|
||||
dependencies = [
|
||||
{ name = "torch", version = "2.8.0+cu129", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "platform_machine == 'aarch64' and platform_python_implementation == 'CPython' and sys_platform == 'linux'" },
|
||||
{ name = "torch", version = "2.8.0+cu129", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "platform_machine == 'aarch64' and sys_platform == 'linux'" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://download.pytorch.org/whl/cu129/torchaudio-2.8.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:67d4f6cbfcb795157850db6a3735301b929cdfe2b56032dc3365105b49a4ee84" },
|
||||
|
|
@ -4187,11 +4217,11 @@ name = "torchaudio"
|
|||
version = "2.8.0+cu129"
|
||||
source = { registry = "https://download.pytorch.org/whl/cu129" }
|
||||
resolution-markers = [
|
||||
"(platform_machine != 'aarch64' and sys_platform == 'linux') or (platform_python_implementation != 'CPython' and sys_platform == 'linux')",
|
||||
"platform_machine != 'aarch64' and sys_platform == 'linux'",
|
||||
"sys_platform != 'darwin' and sys_platform != 'linux'",
|
||||
]
|
||||
dependencies = [
|
||||
{ name = "torch", version = "2.8.0+cu129", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or (platform_python_implementation != 'CPython' and sys_platform == 'linux') or (sys_platform != 'darwin' and sys_platform != 'linux')" },
|
||||
{ name = "torch", version = "2.8.0+cu129", source = { registry = "https://download.pytorch.org/whl/cu129" }, marker = "(platform_machine != 'aarch64' and sys_platform == 'linux') or (sys_platform != 'darwin' and sys_platform != 'linux')" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://download.pytorch.org/whl/cu129/torchaudio-2.8.0%2Bcu129-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:40df9011972519120f284f56e5e7d131d4250ea69653499028d1d30b353f932e" },
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue