refactor: rename the package from ccn-transcribe to audio-scribe
The distribution, console script and import package are now audio-scribe / audio_scribe (src/audio_scribe). Everything named for the old project follows: - CcnError -> AudioScribeError, and its code "ccn_error" -> "audio_scribe_error" (the code is never persisted, so existing job state still loads) - CCN_LIVE -> AUDIO_SCRIBE_LIVE for the live-GPU tests - OpenVINO kernel cache moves to <cache>/audio-scribe/ov_cache; the first run after upgrading recompiles kernels, and the old directory is left in place - README, build-binary.sh, hatch/coverage config and uv.lock updated to match Breaking: the command is now `audio-scribe`; reinstall any tool install of the old name with `uv tool uninstall ccn-transcribe && uv tool install .`. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# ccn-transcribe
|
||||
# audio-scribe
|
||||
|
||||
Download a video, extract its audio losslessly as FLAC, and transcribe it with
|
||||
Whisper on whatever GPU the machine actually has.
|
||||
@@ -7,9 +7,9 @@ Resumable from any completed stage, with errors that tell you what to do next.
|
||||
|
||||
```bash
|
||||
uv sync
|
||||
uv run ccn-transcribe doctor # check the environment first
|
||||
uv run ccn-transcribe run 'https://youtu.be/...'
|
||||
uv run ccn-transcribe run -i urls.txt --formats txt,srt
|
||||
uv run audio-scribe doctor # check the environment first
|
||||
uv run audio-scribe run 'https://youtu.be/...'
|
||||
uv run audio-scribe run -i urls.txt --formats txt,srt
|
||||
```
|
||||
|
||||
Hardware setup for the Intel path is documented separately in
|
||||
@@ -163,13 +163,13 @@ under cron without any PATH setup.
|
||||
|
||||
## Installing
|
||||
|
||||
Either route puts `ccn-transcribe` on your PATH; `ccn-transcribe doctor` tells you
|
||||
Either route puts `audio-scribe` on your PATH; `audio-scribe doctor` tells you
|
||||
whether the machine can actually run it.
|
||||
|
||||
**As a tool** (needs uv; tracks nothing but what it installed):
|
||||
|
||||
```bash
|
||||
uv tool install . # then: ccn-transcribe doctor
|
||||
uv tool install . # then: audio-scribe doctor
|
||||
uv tool install . --reinstall # pick up later commits
|
||||
uv tool install . --editable # or track the checkout instead
|
||||
```
|
||||
@@ -177,12 +177,12 @@ uv tool install . --editable # or track the checkout instead
|
||||
**As a self-contained directory** (needs neither Python nor uv at runtime):
|
||||
|
||||
```bash
|
||||
scripts/build-binary.sh # then: dist/ccn-transcribe/ccn-transcribe doctor
|
||||
scripts/build-binary.sh # then: dist/audio-scribe/audio-scribe doctor
|
||||
```
|
||||
|
||||
~450 MB, most of it OpenVINO and its 47 runtime-loaded plugins. It is `onedir`
|
||||
rather than `onefile` on purpose: `onefile` extracts the whole bundle to `/tmp`
|
||||
on every launch. Move or copy the whole `ccn-transcribe/` directory, not just
|
||||
on every launch. Move or copy the whole `audio-scribe/` directory, not just
|
||||
the executable inside it. `ffmpeg`, `ffprobe` and `aria2c` are still expected on
|
||||
the system either way — they are not bundled.
|
||||
|
||||
@@ -196,6 +196,6 @@ uv run pytest
|
||||
|
||||
Commits run ruff, pyright and the full suite at 100% coverage; pushes run pylint
|
||||
and mypy. No unit test touches the GPU, the network or a real model, which is
|
||||
what keeps the commit gate fast. Live checks sit behind `CCN_LIVE=1`.
|
||||
what keeps the commit gate fast. Live checks sit behind `AUDIO_SCRIBE_LIVE=1`.
|
||||
|
||||
Conventional commits are enforced.
|
||||
|
||||
+4
-4
@@ -3,7 +3,7 @@ requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "ccn-transcribe"
|
||||
name = "audio-scribe"
|
||||
version = "0.1.0"
|
||||
description = "Download videos, extract FLAC, and transcribe with Whisper on whatever GPU is present."
|
||||
requires-python = ">=3.12"
|
||||
@@ -18,7 +18,7 @@ dependencies = [
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
ccn-transcribe = "ccn_transcribe.cli:main"
|
||||
audio-scribe = "audio_scribe.cli:main"
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
@@ -32,7 +32,7 @@ dev = [
|
||||
]
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = ["src/ccn_transcribe"]
|
||||
packages = ["src/audio_scribe"]
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 100
|
||||
@@ -92,7 +92,7 @@ addopts = "-q"
|
||||
|
||||
[tool.coverage.run]
|
||||
branch = true
|
||||
source = ["src/ccn_transcribe"]
|
||||
source = ["src/audio_scribe"]
|
||||
|
||||
[tool.coverage.report]
|
||||
fail_under = 100
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build a self-contained ccn-transcribe directory that runs without Python or uv.
|
||||
# Build a self-contained audio-scribe directory that runs without Python or uv.
|
||||
#
|
||||
# onedir, never onefile: onefile extracts ~450 MB to /tmp on every launch.
|
||||
# deno lands in bin/ because PyInstaller points sys.prefix at the bundle, which
|
||||
@@ -10,7 +10,7 @@ cd "$(dirname "$0")/.."
|
||||
DIST=${1:-dist}
|
||||
|
||||
uv run --locked --with pyinstaller pyinstaller \
|
||||
--noconfirm --onedir --name ccn-transcribe \
|
||||
--noconfirm --onedir --name audio-scribe \
|
||||
--distpath "$DIST" --workpath "build/pyinstaller" --specpath "build" \
|
||||
--collect-all openvino \
|
||||
--collect-all openvino_genai \
|
||||
@@ -18,8 +18,8 @@ uv run --locked --with pyinstaller pyinstaller \
|
||||
--collect-all yt_dlp \
|
||||
--collect-all yt_dlp_ejs \
|
||||
--add-binary "$PWD/.venv/bin/deno:bin" \
|
||||
src/ccn_transcribe/__main__.py
|
||||
src/audio_scribe/__main__.py
|
||||
|
||||
echo
|
||||
echo "built $DIST/ccn-transcribe ($(du -sh "$DIST/ccn-transcribe" | cut -f1))"
|
||||
echo "verify it with: $DIST/ccn-transcribe/ccn-transcribe doctor"
|
||||
echo "built $DIST/audio-scribe ($(du -sh "$DIST/audio-scribe" | cut -f1))"
|
||||
echo "verify it with: $DIST/audio-scribe/audio-scribe doctor"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
"""python -m ccn_transcribe"""
|
||||
"""python -m audio_scribe"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from ccn_transcribe.cli import main
|
||||
from audio_scribe.cli import main
|
||||
|
||||
__all__ = ["main"]
|
||||
|
||||
+6
-6
@@ -13,9 +13,9 @@ from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, ClassVar
|
||||
|
||||
from ccn_transcribe import errors
|
||||
from ccn_transcribe.backends import probe
|
||||
from ccn_transcribe.backends.base import ToolchainStatus
|
||||
from audio_scribe import errors
|
||||
from audio_scribe.backends import probe
|
||||
from audio_scribe.backends.base import ToolchainStatus
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
@@ -23,12 +23,12 @@ if TYPE_CHECKING:
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
|
||||
from ccn_transcribe.backends.base import TranscribeRequest
|
||||
from ccn_transcribe.transcript import TranscriptResult
|
||||
from audio_scribe.backends.base import TranscribeRequest
|
||||
from audio_scribe.transcript import TranscriptResult
|
||||
|
||||
_NOT_IMPLEMENTED = "an AMD GPU was detected, but the AMD backend is not implemented in this build"
|
||||
_HINT = (
|
||||
"Implement src/ccn_transcribe/backends/amd_backend.py using transformers with a "
|
||||
"Implement src/audio_scribe/backends/amd_backend.py using transformers with a "
|
||||
"ROCm build of torch (pip --index-url https://download.pytorch.org/whl/rocm6.2). "
|
||||
"The cached OpenVINO IR model cannot be loaded on ROCm."
|
||||
)
|
||||
@@ -16,7 +16,7 @@ if TYPE_CHECKING:
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
|
||||
from ccn_transcribe.transcript import TranscriptResult
|
||||
from audio_scribe.transcript import TranscriptResult
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
+6
-6
@@ -13,9 +13,9 @@ from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, ClassVar
|
||||
|
||||
from ccn_transcribe import errors
|
||||
from ccn_transcribe.backends import probe
|
||||
from ccn_transcribe.backends.base import ToolchainStatus
|
||||
from audio_scribe import errors
|
||||
from audio_scribe.backends import probe
|
||||
from audio_scribe.backends.base import ToolchainStatus
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
@@ -23,14 +23,14 @@ if TYPE_CHECKING:
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
|
||||
from ccn_transcribe.backends.base import TranscribeRequest
|
||||
from ccn_transcribe.transcript import TranscriptResult
|
||||
from audio_scribe.backends.base import TranscribeRequest
|
||||
from audio_scribe.transcript import TranscriptResult
|
||||
|
||||
_NOT_IMPLEMENTED = (
|
||||
"an NVIDIA GPU was detected, but the NVIDIA backend is not implemented in this build"
|
||||
)
|
||||
_HINT = (
|
||||
"Implement src/ccn_transcribe/backends/nvidia_backend.py using faster-whisper "
|
||||
"Implement src/audio_scribe/backends/nvidia_backend.py using faster-whisper "
|
||||
"(CTranslate2) with a CTranslate2 model. The cached OpenVINO IR model cannot "
|
||||
"be loaded on CUDA."
|
||||
)
|
||||
+8
-8
@@ -13,16 +13,16 @@ import time
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, Any, ClassVar
|
||||
|
||||
from ccn_transcribe import errors
|
||||
from ccn_transcribe.backends import probe
|
||||
from ccn_transcribe.backends.base import ToolchainStatus
|
||||
from ccn_transcribe.transcript import TranscriptResult, normalize_segments
|
||||
from audio_scribe import errors
|
||||
from audio_scribe.backends import probe
|
||||
from audio_scribe.backends.base import ToolchainStatus
|
||||
from audio_scribe.transcript import TranscriptResult, normalize_segments
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
|
||||
from ccn_transcribe.backends.base import TranscribeRequest
|
||||
from audio_scribe.backends.base import TranscribeRequest
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -33,7 +33,7 @@ SAMPLE_RATE = 16_000
|
||||
|
||||
def cache_root() -> Path:
|
||||
base = os.environ.get("XDG_CACHE_HOME") or str(Path.home() / ".cache")
|
||||
return Path(base) / "ccn-transcribe" / "ov_cache"
|
||||
return Path(base) / "audio-scribe" / "ov_cache"
|
||||
|
||||
|
||||
def language_token(code: str | None, allowed: set[str] | None = None) -> str | None:
|
||||
@@ -153,14 +153,14 @@ class _OpenvinoBackend:
|
||||
|
||||
def load_hint(self) -> str:
|
||||
if self.device != "GPU":
|
||||
return "Try --device cpu, or run `ccn-transcribe doctor`."
|
||||
return "Try --device cpu, or run `audio-scribe doctor`."
|
||||
nodes = [n for n in probe.render_nodes() if n.vendor == "intel"]
|
||||
if nodes and not nodes[0].writable:
|
||||
return (
|
||||
f"{nodes[0].path} is not writable by this user. "
|
||||
"Run: sudo usermod -aG render $USER, then log out and back in."
|
||||
)
|
||||
return "Run `ccn-transcribe doctor` to separate driver problems from plugin ones."
|
||||
return "Run `audio-scribe doctor` to separate driver problems from plugin ones."
|
||||
|
||||
def transcribe(
|
||||
self, pcm: npt.NDArray[np.float32], request: TranscribeRequest
|
||||
@@ -5,10 +5,10 @@ from __future__ import annotations
|
||||
import logging
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ccn_transcribe import errors
|
||||
from ccn_transcribe.backends.amd_backend import AmdBackend
|
||||
from ccn_transcribe.backends.nvidia_backend import NvidiaBackend
|
||||
from ccn_transcribe.backends.openvino_backend import OpenvinoCpuBackend, OpenvinoGpuBackend
|
||||
from audio_scribe import errors
|
||||
from audio_scribe.backends.amd_backend import AmdBackend
|
||||
from audio_scribe.backends.nvidia_backend import NvidiaBackend
|
||||
from audio_scribe.backends.openvino_backend import OpenvinoCpuBackend, OpenvinoGpuBackend
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Iterator
|
||||
@@ -17,8 +17,8 @@ if TYPE_CHECKING:
|
||||
import numpy as np
|
||||
import numpy.typing as npt
|
||||
|
||||
from ccn_transcribe.backends.base import Backend, TranscribeRequest
|
||||
from ccn_transcribe.transcript import TranscriptResult
|
||||
from audio_scribe.backends.base import Backend, TranscribeRequest
|
||||
from audio_scribe.transcript import TranscriptResult
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -172,5 +172,5 @@ def transcribe_with_fallback(
|
||||
)
|
||||
raise errors.TranscribeError(
|
||||
"no usable backend remains",
|
||||
hint=str(last) if last else "Run `ccn-transcribe doctor` to see what was detected.",
|
||||
hint=str(last) if last else "Run `audio-scribe doctor` to see what was detected.",
|
||||
) from last
|
||||
@@ -8,14 +8,14 @@ from typing import Any, NoReturn
|
||||
|
||||
import click
|
||||
|
||||
from ccn_transcribe import doctor as doctor_mod
|
||||
from ccn_transcribe import errors, logsetup, paths
|
||||
from ccn_transcribe.config import DEFAULT_FORMATS, RunConfig
|
||||
from ccn_transcribe.formats import FORMATS
|
||||
from ccn_transcribe.jobs import batch, store
|
||||
from ccn_transcribe.jobs.plan import Stage
|
||||
from ccn_transcribe.media import ffmpeg, ytdlp_opts
|
||||
from ccn_transcribe.stages import download as download_stage
|
||||
from audio_scribe import doctor as doctor_mod
|
||||
from audio_scribe import errors, logsetup, paths
|
||||
from audio_scribe.config import DEFAULT_FORMATS, RunConfig
|
||||
from audio_scribe.formats import FORMATS
|
||||
from audio_scribe.jobs import batch, store
|
||||
from audio_scribe.jobs.plan import Stage
|
||||
from audio_scribe.media import ffmpeg, ytdlp_opts
|
||||
from audio_scribe.stages import download as download_stage
|
||||
|
||||
STAGE_NAMES = [s.value for s in Stage]
|
||||
|
||||
@@ -78,7 +78,7 @@ def build_config(**kw: Any) -> RunConfig:
|
||||
|
||||
|
||||
@click.group(context_settings={"help_option_names": ["-h", "--help"]})
|
||||
@click.version_option(package_name="ccn-transcribe")
|
||||
@click.version_option(package_name="audio-scribe")
|
||||
def main() -> None:
|
||||
"""Download videos, extract FLAC, and transcribe with Whisper."""
|
||||
|
||||
@@ -177,7 +177,7 @@ def run_command(urls: tuple[str, ...], input_files: tuple[Path, ...], **kw: Any)
|
||||
raise errors.ConfigError("no URLs given", hint="Pass a URL or -i urls.txt.")
|
||||
batch.confirm_retention(config)
|
||||
result = batch.run_batch(targets, config, dry_run=bool(kw["dry_run"]))
|
||||
except errors.CcnError as exc:
|
||||
except errors.AudioScribeError as exc:
|
||||
_fail(exc, verbose=bool(kw["verbose"]))
|
||||
click.echo(result.summary())
|
||||
sys.exit(result.exit_code)
|
||||
@@ -213,7 +213,7 @@ def status_command(job_ids: tuple[str, ...], workdir: Path) -> None:
|
||||
)
|
||||
|
||||
|
||||
def _fail(exc: errors.CcnError, *, verbose: bool) -> NoReturn:
|
||||
def _fail(exc: errors.AudioScribeError, *, verbose: bool) -> NoReturn:
|
||||
click.echo(f"ERROR: {exc}", err=True)
|
||||
if exc.hint:
|
||||
click.echo(f"hint: {exc.hint}", err=True)
|
||||
@@ -6,11 +6,11 @@ from dataclasses import dataclass, field, replace
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ccn_transcribe.jobs.plan import Stage
|
||||
from ccn_transcribe.media.ytdlp_opts import DEFAULT_DOWNLOAD, DownloadConfig
|
||||
from audio_scribe.jobs.plan import Stage
|
||||
from audio_scribe.media.ytdlp_opts import DEFAULT_DOWNLOAD, DownloadConfig
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ccn_transcribe.backends.base import TranscribeRequest
|
||||
from audio_scribe.backends.base import TranscribeRequest
|
||||
|
||||
DEFAULT_FORMATS = ("txt", "srt", "vtt", "json")
|
||||
|
||||
@@ -49,7 +49,7 @@ class RunConfig:
|
||||
return "; ".join(parts)
|
||||
|
||||
def request(self) -> TranscribeRequest:
|
||||
from ccn_transcribe.backends.base import ( # pylint: disable=import-outside-toplevel
|
||||
from audio_scribe.backends.base import ( # pylint: disable=import-outside-toplevel
|
||||
TranscribeRequest,
|
||||
)
|
||||
|
||||
@@ -13,13 +13,13 @@ from dataclasses import dataclass
|
||||
from enum import StrEnum
|
||||
from pathlib import Path
|
||||
|
||||
from ccn_transcribe.backends import probe
|
||||
from ccn_transcribe.backends.openvino_backend import (
|
||||
from audio_scribe.backends import probe
|
||||
from audio_scribe.backends.openvino_backend import (
|
||||
DEFAULT_MODEL,
|
||||
cache_root,
|
||||
snapshot,
|
||||
)
|
||||
from ccn_transcribe.media import ffmpeg, ytdlp_opts
|
||||
from audio_scribe.media import ffmpeg, ytdlp_opts
|
||||
|
||||
|
||||
class Status(StrEnum):
|
||||
@@ -15,8 +15,8 @@ EXIT_FATAL = 2
|
||||
EXIT_INTERRUPTED = 130
|
||||
|
||||
|
||||
class CcnError(Exception):
|
||||
code: ClassVar[str] = "ccn_error"
|
||||
class AudioScribeError(Exception):
|
||||
code: ClassVar[str] = "audio_scribe_error"
|
||||
exit_code: ClassVar[int] = EXIT_JOB_FAILED
|
||||
retryable: ClassVar[bool] = False
|
||||
|
||||
@@ -29,7 +29,7 @@ class CcnError(Exception):
|
||||
return self.message
|
||||
|
||||
|
||||
class FatalError(CcnError):
|
||||
class FatalError(AudioScribeError):
|
||||
"""Aborts the run. Continuing would only produce more bad artifacts."""
|
||||
|
||||
code: ClassVar[str] = "fatal"
|
||||
@@ -52,7 +52,7 @@ class SchemaTooNewError(FatalError):
|
||||
code: ClassVar[str] = "schema_too_new"
|
||||
|
||||
|
||||
class JobError(CcnError):
|
||||
class JobError(AudioScribeError):
|
||||
"""Scoped to one job; the batch continues."""
|
||||
|
||||
code: ClassVar[str] = "job"
|
||||
@@ -12,7 +12,7 @@ from typing import TYPE_CHECKING
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Iterable, Mapping, Sequence
|
||||
|
||||
from ccn_transcribe.transcript import Segment, TranscriptResult
|
||||
from audio_scribe.transcript import Segment, TranscriptResult
|
||||
|
||||
FORMATS = ("txt", "srt", "vtt", "json")
|
||||
|
||||
@@ -7,18 +7,18 @@ import sys
|
||||
from dataclasses import dataclass, field
|
||||
from typing import TYPE_CHECKING, TextIO
|
||||
|
||||
from ccn_transcribe import errors, logsetup, paths
|
||||
from ccn_transcribe.backends.registry import BackendHolder
|
||||
from ccn_transcribe.jobs import index, store
|
||||
from ccn_transcribe.jobs.index import Target
|
||||
from ccn_transcribe.jobs.runner import JobOutcome, run_job
|
||||
from ccn_transcribe.stages import download as download_stage
|
||||
from audio_scribe import errors, logsetup, paths
|
||||
from audio_scribe.backends.registry import BackendHolder
|
||||
from audio_scribe.jobs import index, store
|
||||
from audio_scribe.jobs.index import Target
|
||||
from audio_scribe.jobs.runner import JobOutcome, run_job
|
||||
from audio_scribe.stages import download as download_stage
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Sequence
|
||||
from pathlib import Path
|
||||
|
||||
from ccn_transcribe.config import RunConfig
|
||||
from audio_scribe.config import RunConfig
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -151,7 +151,7 @@ def _run_one(
|
||||
targets = expand(url, config, workspace, remember=not dry_run)
|
||||
except errors.FatalError:
|
||||
raise
|
||||
except errors.CcnError as exc:
|
||||
except errors.AudioScribeError as exc:
|
||||
log.error("%s: %s", url, exc)
|
||||
result.outcomes.append(JobOutcome(url, url, (), ok=False, error=str(exc)))
|
||||
return
|
||||
@@ -167,7 +167,7 @@ def _run_one(
|
||||
)
|
||||
except errors.FatalError:
|
||||
raise
|
||||
except errors.CcnError as exc:
|
||||
except errors.AudioScribeError as exc:
|
||||
# One bad job must never take the batch down with it.
|
||||
log.error("%s: %s", job.root.name, exc)
|
||||
result.outcomes.append(
|
||||
@@ -13,8 +13,8 @@ import logging
|
||||
from dataclasses import dataclass, field
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
|
||||
from ccn_transcribe import paths
|
||||
from ccn_transcribe.jobs import store
|
||||
from audio_scribe import paths
|
||||
from audio_scribe.jobs import store
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Mapping, Sequence
|
||||
@@ -10,7 +10,7 @@ from __future__ import annotations
|
||||
from dataclasses import dataclass
|
||||
from enum import StrEnum
|
||||
|
||||
from ccn_transcribe.jobs.verify import Verdict
|
||||
from audio_scribe.jobs.verify import Verdict
|
||||
|
||||
|
||||
class Stage(StrEnum):
|
||||
@@ -14,17 +14,17 @@ import json
|
||||
import logging
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from ccn_transcribe import errors, formats
|
||||
from ccn_transcribe.jobs import store
|
||||
from ccn_transcribe.jobs.state import Artifact, ArtifactStatus, JobState, Outputs
|
||||
from ccn_transcribe.jobs.state import TranscriptionRecord as Record
|
||||
from ccn_transcribe.media import ffmpeg
|
||||
from ccn_transcribe.stages import download as download_stage
|
||||
from audio_scribe import errors, formats
|
||||
from audio_scribe.jobs import store
|
||||
from audio_scribe.jobs.state import Artifact, ArtifactStatus, JobState, Outputs
|
||||
from audio_scribe.jobs.state import TranscriptionRecord as Record
|
||||
from audio_scribe.media import ffmpeg
|
||||
from audio_scribe.stages import download as download_stage
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
from ccn_transcribe.paths import JobPaths
|
||||
from audio_scribe.paths import JobPaths
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -7,23 +7,23 @@ from dataclasses import dataclass
|
||||
from datetime import UTC, datetime
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from ccn_transcribe import errors
|
||||
from ccn_transcribe.jobs import recover, store, verify
|
||||
from ccn_transcribe.jobs.plan import Stage, Verdicts, plan_stages
|
||||
from ccn_transcribe.jobs.state import Artifact, ArtifactStatus, JobState, Outputs
|
||||
from ccn_transcribe.jobs.state import TranscriptionRecord as Record
|
||||
from ccn_transcribe.media import ffmpeg
|
||||
from ccn_transcribe.stages import audio as audio_stage
|
||||
from ccn_transcribe.stages import download as download_stage
|
||||
from ccn_transcribe.stages import outputs as outputs_stage
|
||||
from ccn_transcribe.stages import transcribe as transcribe_stage
|
||||
from audio_scribe import errors
|
||||
from audio_scribe.jobs import recover, store, verify
|
||||
from audio_scribe.jobs.plan import Stage, Verdicts, plan_stages
|
||||
from audio_scribe.jobs.state import Artifact, ArtifactStatus, JobState, Outputs
|
||||
from audio_scribe.jobs.state import TranscriptionRecord as Record
|
||||
from audio_scribe.media import ffmpeg
|
||||
from audio_scribe.stages import audio as audio_stage
|
||||
from audio_scribe.stages import download as download_stage
|
||||
from audio_scribe.stages import outputs as outputs_stage
|
||||
from audio_scribe.stages import transcribe as transcribe_stage
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
from ccn_transcribe.backends.registry import BackendHolder
|
||||
from ccn_transcribe.config import RunConfig
|
||||
from ccn_transcribe.paths import JobPaths
|
||||
from audio_scribe.backends.registry import BackendHolder
|
||||
from audio_scribe.config import RunConfig
|
||||
from audio_scribe.paths import JobPaths
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -118,7 +118,7 @@ def run_job(
|
||||
_execute(job, url, config, state, stages=stages, holder=holder)
|
||||
except errors.FatalError:
|
||||
raise
|
||||
except errors.CcnError as exc:
|
||||
except errors.AudioScribeError as exc:
|
||||
state.last_error = {"stage": "unknown", "message": str(exc)}
|
||||
store.save(job, state)
|
||||
return JobOutcome(job.root.name, url, stages, ok=False, error=str(exc))
|
||||
@@ -239,7 +239,7 @@ def _do_transcript(
|
||||
|
||||
def _rerender(job: JobPaths, config: RunConfig, state: JobState) -> dict[str, str]:
|
||||
"""Re-render other formats from the saved segments, no model needed."""
|
||||
from ccn_transcribe.transcript import ( # pylint: disable=import-outside-toplevel
|
||||
from audio_scribe.transcript import ( # pylint: disable=import-outside-toplevel
|
||||
TranscriptResult,
|
||||
)
|
||||
|
||||
@@ -15,7 +15,7 @@ from datetime import UTC, datetime
|
||||
from enum import StrEnum
|
||||
from typing import Any
|
||||
|
||||
from ccn_transcribe import errors
|
||||
from audio_scribe import errors
|
||||
|
||||
SCHEMA_VERSION = 1
|
||||
|
||||
@@ -127,7 +127,7 @@ class JobState:
|
||||
if version > SCHEMA_VERSION:
|
||||
raise errors.SchemaTooNewError(
|
||||
f"state.json is schema v{version}, but this build understands v{SCHEMA_VERSION}",
|
||||
hint="Upgrade ccn-transcribe, or point --workdir somewhere else.",
|
||||
hint="Upgrade audio-scribe, or point --workdir somewhere else.",
|
||||
)
|
||||
artifacts = doc.get("artifacts", {})
|
||||
record = doc.get("transcription")
|
||||
@@ -10,14 +10,14 @@ from contextlib import contextmanager
|
||||
from datetime import UTC, datetime
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from ccn_transcribe import errors
|
||||
from ccn_transcribe.jobs.state import JobState
|
||||
from audio_scribe import errors
|
||||
from audio_scribe.jobs.state import JobState
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Generator
|
||||
from pathlib import Path
|
||||
|
||||
from ccn_transcribe.paths import JobPaths
|
||||
from audio_scribe.paths import JobPaths
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -11,15 +11,15 @@ import logging
|
||||
from enum import StrEnum
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ccn_transcribe import errors
|
||||
from ccn_transcribe.jobs.state import Artifact, ArtifactStatus, Outputs
|
||||
from ccn_transcribe.media import ffmpeg
|
||||
from audio_scribe import errors
|
||||
from audio_scribe.jobs.state import Artifact, ArtifactStatus, Outputs
|
||||
from audio_scribe.media import ffmpeg
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Iterator, Sequence
|
||||
from pathlib import Path
|
||||
|
||||
from ccn_transcribe.paths import JobPaths
|
||||
from audio_scribe.paths import JobPaths
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -10,9 +10,9 @@ from typing import TYPE_CHECKING
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Generator
|
||||
|
||||
from ccn_transcribe.paths import JobPaths
|
||||
from audio_scribe.paths import JobPaths
|
||||
|
||||
ROOT = "ccn_transcribe"
|
||||
ROOT = "audio_scribe"
|
||||
|
||||
|
||||
def configure(verbose: int = 0, quiet: bool = False) -> None:
|
||||
@@ -17,7 +17,7 @@ from typing import TYPE_CHECKING, Literal
|
||||
|
||||
import numpy as np
|
||||
|
||||
from ccn_transcribe import errors
|
||||
from audio_scribe import errors
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
@@ -18,7 +18,7 @@ from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from ccn_transcribe import errors
|
||||
from audio_scribe import errors
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Sequence
|
||||
@@ -9,13 +9,13 @@ from __future__ import annotations
|
||||
import logging
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ccn_transcribe import errors
|
||||
from ccn_transcribe.media import ffmpeg
|
||||
from audio_scribe import errors
|
||||
from audio_scribe.media import ffmpeg
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
from ccn_transcribe.paths import JobPaths
|
||||
from audio_scribe.paths import JobPaths
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -13,14 +13,14 @@ import time
|
||||
from collections.abc import Callable
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from ccn_transcribe import errors, paths
|
||||
from ccn_transcribe.media import ytdlp_opts
|
||||
from audio_scribe import errors, paths
|
||||
from audio_scribe.media import ytdlp_opts
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Iterator, Sequence
|
||||
from pathlib import Path
|
||||
|
||||
from ccn_transcribe.paths import JobPaths
|
||||
from audio_scribe.paths import JobPaths
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -47,7 +47,7 @@ SOURCE_PATTERNS: tuple[tuple[re.Pattern[str], type[errors.SourceError], str], ..
|
||||
re.compile(r"confirm you.{0,5}re not a bot|not a bot", re.I),
|
||||
errors.BotCheckError,
|
||||
"YouTube bot check. Try --cookies-from-browser, or check that a JS runtime "
|
||||
"is available: ccn-transcribe doctor",
|
||||
"is available: audio-scribe doctor",
|
||||
),
|
||||
(
|
||||
re.compile(
|
||||
@@ -92,7 +92,7 @@ ARIA2_EXITS: dict[int, tuple[str, str]] = {
|
||||
}
|
||||
|
||||
|
||||
def classify(message: str, job_id: str | None = None) -> errors.CcnError:
|
||||
def classify(message: str, job_id: str | None = None) -> errors.AudioScribeError:
|
||||
"""Map a yt-dlp message onto an actionable error."""
|
||||
if "no space left" in message.lower():
|
||||
return errors.DiskFullError(message, hint="Free some space and re-run.")
|
||||
@@ -246,7 +246,7 @@ def download(
|
||||
options = download_options(job, config)
|
||||
make = factory or default_factory
|
||||
|
||||
last: errors.CcnError | None = None
|
||||
last: errors.AudioScribeError | None = None
|
||||
for attempt in range(1, attempts + 1):
|
||||
try:
|
||||
with make(options) as ydl:
|
||||
@@ -281,7 +281,7 @@ def download(
|
||||
raise last or errors.DownloadError("download failed", job_id=job.root.name)
|
||||
|
||||
|
||||
def is_retryable(failure: errors.CcnError) -> bool:
|
||||
def is_retryable(failure: errors.AudioScribeError) -> bool:
|
||||
# A private video will still be private on the third try, and continuing past
|
||||
# ENOSPC only makes more corrupt artifacts.
|
||||
if isinstance(failure, errors.FatalError):
|
||||
@@ -7,15 +7,15 @@ import os
|
||||
import shutil
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ccn_transcribe import formats
|
||||
from ccn_transcribe.paths import output_stem
|
||||
from audio_scribe import formats
|
||||
from audio_scribe.paths import output_stem
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Mapping, Sequence
|
||||
from pathlib import Path
|
||||
|
||||
from ccn_transcribe.paths import JobPaths
|
||||
from ccn_transcribe.transcript import TranscriptResult
|
||||
from audio_scribe.paths import JobPaths
|
||||
from audio_scribe.transcript import TranscriptResult
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -6,17 +6,17 @@ import json
|
||||
import logging
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ccn_transcribe.backends import registry
|
||||
from ccn_transcribe.media import ffmpeg
|
||||
from ccn_transcribe.transcript import Segment
|
||||
from audio_scribe.backends import registry
|
||||
from audio_scribe.media import ffmpeg
|
||||
from audio_scribe.transcript import Segment
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
from ccn_transcribe.backends.base import Backend, TranscribeRequest
|
||||
from ccn_transcribe.backends.registry import BackendHolder
|
||||
from ccn_transcribe.paths import JobPaths
|
||||
from ccn_transcribe.transcript import TranscriptResult
|
||||
from audio_scribe.backends.base import Backend, TranscribeRequest
|
||||
from audio_scribe.backends.registry import BackendHolder
|
||||
from audio_scribe.paths import JobPaths
|
||||
from audio_scribe.transcript import TranscriptResult
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@@ -10,14 +10,15 @@ import numpy as np
|
||||
import openvino_genai
|
||||
import pytest
|
||||
|
||||
from ccn_transcribe import errors
|
||||
from ccn_transcribe.backends import openvino_backend as ovb
|
||||
from ccn_transcribe.backends import probe as probe_mod
|
||||
from ccn_transcribe.backends.base import TranscribeRequest
|
||||
from ccn_transcribe.media import ffmpeg
|
||||
from audio_scribe import errors
|
||||
from audio_scribe.backends import openvino_backend as ovb
|
||||
from audio_scribe.backends import probe as probe_mod
|
||||
from audio_scribe.backends.base import TranscribeRequest
|
||||
from audio_scribe.media import ffmpeg
|
||||
|
||||
LIVE = pytest.mark.skipif(
|
||||
not os.environ.get("CCN_LIVE"), reason="set CCN_LIVE=1 to run against the real GPU"
|
||||
not os.environ.get("AUDIO_SCRIBE_LIVE"),
|
||||
reason="set AUDIO_SCRIBE_LIVE=1 to run against the real GPU",
|
||||
)
|
||||
|
||||
|
||||
@@ -65,11 +66,11 @@ class TestSupportedLanguages:
|
||||
class TestCacheRoot:
|
||||
def test_respects_xdg_cache_home(self, monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
|
||||
monkeypatch.setenv("XDG_CACHE_HOME", str(tmp_path))
|
||||
assert ovb.cache_root() == tmp_path / "ccn-transcribe/ov_cache"
|
||||
assert ovb.cache_root() == tmp_path / "audio-scribe/ov_cache"
|
||||
|
||||
def test_falls_back_to_home_cache(self, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.delenv("XDG_CACHE_HOME", raising=False)
|
||||
assert ovb.cache_root() == Path.home() / ".cache/ccn-transcribe/ov_cache"
|
||||
assert ovb.cache_root() == Path.home() / ".cache/audio-scribe/ov_cache"
|
||||
|
||||
def test_is_not_relative_to_the_working_directory(self) -> None:
|
||||
# The benchmark scripts use a relative .ov_cache_* and only work from the
|
||||
|
||||
@@ -4,7 +4,7 @@ from typing import TYPE_CHECKING
|
||||
|
||||
import pytest
|
||||
|
||||
from ccn_transcribe.backends import probe
|
||||
from audio_scribe.backends import probe
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
@@ -6,10 +6,10 @@ from typing import TYPE_CHECKING, ClassVar
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from ccn_transcribe import errors
|
||||
from ccn_transcribe.backends import registry
|
||||
from ccn_transcribe.backends.base import ToolchainStatus, TranscribeRequest
|
||||
from ccn_transcribe.transcript import Segment, TranscriptResult
|
||||
from audio_scribe import errors
|
||||
from audio_scribe.backends import registry
|
||||
from audio_scribe.backends.base import ToolchainStatus, TranscribeRequest
|
||||
from audio_scribe.transcript import Segment, TranscriptResult
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
@@ -3,10 +3,10 @@ from __future__ import annotations
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from ccn_transcribe import errors
|
||||
from ccn_transcribe.backends.amd_backend import AmdBackend
|
||||
from ccn_transcribe.backends.base import TranscribeRequest
|
||||
from ccn_transcribe.backends.nvidia_backend import NvidiaBackend
|
||||
from audio_scribe import errors
|
||||
from audio_scribe.backends.amd_backend import AmdBackend
|
||||
from audio_scribe.backends.base import TranscribeRequest
|
||||
from audio_scribe.backends.nvidia_backend import NvidiaBackend
|
||||
|
||||
STUBS = [NvidiaBackend, AmdBackend]
|
||||
|
||||
|
||||
+14
-14
@@ -8,15 +8,15 @@ from typing import Any
|
||||
import pytest
|
||||
from click.testing import CliRunner
|
||||
|
||||
import ccn_transcribe.__main__ as entry
|
||||
from ccn_transcribe import cli, doctor, errors, logsetup, paths
|
||||
from ccn_transcribe.config import RunConfig
|
||||
from ccn_transcribe.jobs import batch, store
|
||||
from ccn_transcribe.jobs.plan import Stage
|
||||
from ccn_transcribe.jobs.runner import JobOutcome
|
||||
from ccn_transcribe.jobs.state import JobState
|
||||
from ccn_transcribe.media import ytdlp_opts
|
||||
from ccn_transcribe.stages import download as download_stage
|
||||
import audio_scribe.__main__ as entry
|
||||
from audio_scribe import cli, doctor, errors, logsetup, paths
|
||||
from audio_scribe.config import RunConfig
|
||||
from audio_scribe.jobs import batch, store
|
||||
from audio_scribe.jobs.plan import Stage
|
||||
from audio_scribe.jobs.runner import JobOutcome
|
||||
from audio_scribe.jobs.state import JobState
|
||||
from audio_scribe.media import ytdlp_opts
|
||||
from audio_scribe.stages import download as download_stage
|
||||
|
||||
|
||||
class TestReadUrls:
|
||||
@@ -246,7 +246,7 @@ class TestRunBatch:
|
||||
def fake_run(job: Any, url: str, *_a: object, **_k: object) -> JobOutcome:
|
||||
return JobOutcome(job.root.name, url, (), ok=True)
|
||||
|
||||
monkeypatch.setattr("ccn_transcribe.jobs.batch.run_job", fake_run)
|
||||
monkeypatch.setattr("audio_scribe.jobs.batch.run_job", fake_run)
|
||||
result = batch.run_batch(
|
||||
["https://y.test/bad", "https://y.test/good"], self._config(tmp_path)
|
||||
)
|
||||
@@ -274,7 +274,7 @@ class TestRunBatch:
|
||||
raise errors.MediaError("no audio")
|
||||
|
||||
monkeypatch.setattr(download_stage, "extract_info", info)
|
||||
monkeypatch.setattr("ccn_transcribe.jobs.batch.run_job", boom)
|
||||
monkeypatch.setattr("audio_scribe.jobs.batch.run_job", boom)
|
||||
result = batch.run_batch(["u"], self._config(tmp_path))
|
||||
assert result.failed[0].error == "no audio"
|
||||
|
||||
@@ -295,7 +295,7 @@ class TestLogSetup:
|
||||
job.ensure()
|
||||
before = len(logging.getLogger(logsetup.ROOT).handlers)
|
||||
with logsetup.job_log(job):
|
||||
logging.getLogger("ccn_transcribe.test").info("hello")
|
||||
logging.getLogger("audio_scribe.test").info("hello")
|
||||
assert "hello" in (job.logs_dir / "job.log").read_text()
|
||||
# A 200-URL batch must not leak 200 open handlers.
|
||||
assert len(logging.getLogger(logsetup.ROOT).handlers) == before
|
||||
@@ -502,7 +502,7 @@ def test_a_fatal_error_inside_a_job_stops_the_batch(
|
||||
raise errors.DiskFullError("no space")
|
||||
|
||||
monkeypatch.setattr(download_stage, "extract_info", info)
|
||||
monkeypatch.setattr("ccn_transcribe.jobs.batch.run_job", boom)
|
||||
monkeypatch.setattr("audio_scribe.jobs.batch.run_job", boom)
|
||||
with pytest.raises(errors.DiskFullError):
|
||||
batch.run_batch(["u"], RunConfig(workdir=tmp_path / "t"))
|
||||
|
||||
@@ -520,7 +520,7 @@ def test_an_error_without_a_hint_prints_only_the_message(
|
||||
|
||||
|
||||
def test_module_entrypoint_is_the_cli() -> None:
|
||||
# python -m ccn_transcribe must reach the same command group, and the
|
||||
# python -m audio_scribe must reach the same command group, and the
|
||||
# __main__ guard must be present: Python 3.14's forkserver re-imports
|
||||
# __main__, and without the guard the program runs a second copy of itself.
|
||||
assert entry.main is cli.main
|
||||
|
||||
@@ -11,9 +11,9 @@ from typing import TYPE_CHECKING, Any, ClassVar, NamedTuple
|
||||
|
||||
import openvino as ov
|
||||
|
||||
from ccn_transcribe import doctor
|
||||
from ccn_transcribe.backends import probe
|
||||
from ccn_transcribe.media import ffmpeg, ytdlp_opts
|
||||
from audio_scribe import doctor
|
||||
from audio_scribe.backends import probe
|
||||
from audio_scribe.media import ffmpeg, ytdlp_opts
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Callable
|
||||
|
||||
@@ -2,25 +2,25 @@ from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from ccn_transcribe import errors
|
||||
from audio_scribe import errors
|
||||
|
||||
|
||||
def test_base_carries_message_and_hint() -> None:
|
||||
err = errors.CcnError("something broke", hint="try this")
|
||||
err = errors.AudioScribeError("something broke", hint="try this")
|
||||
assert str(err) == "something broke"
|
||||
assert err.hint == "try this"
|
||||
assert err.exit_code == errors.EXIT_JOB_FAILED
|
||||
|
||||
|
||||
def test_hint_defaults_to_none() -> None:
|
||||
assert errors.CcnError("bare").hint is None
|
||||
assert errors.AudioScribeError("bare").hint is None
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"cls",
|
||||
[errors.ConfigError, errors.PreflightError, errors.DiskFullError, errors.SchemaTooNewError],
|
||||
)
|
||||
def test_fatal_errors_abort_the_run(cls: type[errors.CcnError]) -> None:
|
||||
def test_fatal_errors_abort_the_run(cls: type[errors.AudioScribeError]) -> None:
|
||||
err = cls("nope")
|
||||
assert err.exit_code == errors.EXIT_FATAL
|
||||
assert isinstance(err, errors.FatalError)
|
||||
@@ -63,7 +63,9 @@ def test_only_network_errors_are_retryable() -> None:
|
||||
|
||||
def test_every_error_class_declares_a_distinct_code() -> None:
|
||||
classes = [
|
||||
v for v in vars(errors).values() if isinstance(v, type) and issubclass(v, errors.CcnError)
|
||||
v
|
||||
for v in vars(errors).values()
|
||||
if isinstance(v, type) and issubclass(v, errors.AudioScribeError)
|
||||
]
|
||||
codes = [c.code for c in classes]
|
||||
assert len(codes) == len(set(codes)), "duplicate .code values"
|
||||
|
||||
@@ -4,8 +4,8 @@ import json
|
||||
|
||||
import pytest
|
||||
|
||||
from ccn_transcribe import formats
|
||||
from ccn_transcribe.transcript import Segment, TranscriptResult
|
||||
from audio_scribe import formats
|
||||
from audio_scribe.transcript import Segment, TranscriptResult
|
||||
|
||||
SEGMENTS = (Segment(0.0, 1.5, "Hello there."), Segment(1.5, 3.25, "General Kenobi."))
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ from typing import TYPE_CHECKING
|
||||
|
||||
import pytest
|
||||
|
||||
from ccn_transcribe import paths
|
||||
from ccn_transcribe.jobs import index
|
||||
from audio_scribe import paths
|
||||
from audio_scribe.jobs import index
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
@@ -2,8 +2,8 @@ from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from ccn_transcribe.jobs.plan import Stage, Verdicts, plan_stages
|
||||
from ccn_transcribe.jobs.verify import Verdict
|
||||
from audio_scribe.jobs.plan import Stage, Verdicts, plan_stages
|
||||
from audio_scribe.jobs.verify import Verdict
|
||||
|
||||
OK = Verdict.OK
|
||||
GONE = Verdict.SATISFIED_ABSENT
|
||||
|
||||
@@ -5,10 +5,10 @@ from typing import TYPE_CHECKING
|
||||
|
||||
import pytest
|
||||
|
||||
from ccn_transcribe import paths
|
||||
from ccn_transcribe.jobs import recover, store
|
||||
from ccn_transcribe.jobs.state import ArtifactStatus
|
||||
from ccn_transcribe.media import ffmpeg
|
||||
from audio_scribe import paths
|
||||
from audio_scribe.jobs import recover, store
|
||||
from audio_scribe.jobs.state import ArtifactStatus
|
||||
from audio_scribe.media import ffmpeg
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
+10
-10
@@ -6,16 +6,16 @@ from typing import TYPE_CHECKING, ClassVar
|
||||
|
||||
import pytest
|
||||
|
||||
from ccn_transcribe import errors, paths
|
||||
from ccn_transcribe.backends import registry
|
||||
from ccn_transcribe.backends.base import ToolchainStatus, TranscribeRequest
|
||||
from ccn_transcribe.config import RunConfig
|
||||
from ccn_transcribe.jobs import runner, store
|
||||
from ccn_transcribe.jobs.plan import Stage, Verdicts
|
||||
from ccn_transcribe.jobs.state import Artifact, ArtifactStatus, JobState
|
||||
from ccn_transcribe.jobs.verify import Verdict
|
||||
from ccn_transcribe.stages import download as download_stage
|
||||
from ccn_transcribe.transcript import Segment, TranscriptResult
|
||||
from audio_scribe import errors, paths
|
||||
from audio_scribe.backends import registry
|
||||
from audio_scribe.backends.base import ToolchainStatus, TranscribeRequest
|
||||
from audio_scribe.config import RunConfig
|
||||
from audio_scribe.jobs import runner, store
|
||||
from audio_scribe.jobs.plan import Stage, Verdicts
|
||||
from audio_scribe.jobs.state import Artifact, ArtifactStatus, JobState
|
||||
from audio_scribe.jobs.verify import Verdict
|
||||
from audio_scribe.stages import download as download_stage
|
||||
from audio_scribe.transcript import Segment, TranscriptResult
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
@@ -2,8 +2,8 @@ from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from ccn_transcribe import errors
|
||||
from ccn_transcribe.jobs import state as job_state
|
||||
from audio_scribe import errors
|
||||
from audio_scribe.jobs import state as job_state
|
||||
|
||||
|
||||
def make() -> job_state.JobState:
|
||||
|
||||
@@ -6,9 +6,9 @@ from typing import TYPE_CHECKING
|
||||
|
||||
import pytest
|
||||
|
||||
from ccn_transcribe import errors, paths
|
||||
from ccn_transcribe.jobs import state as job_state
|
||||
from ccn_transcribe.jobs import store
|
||||
from audio_scribe import errors, paths
|
||||
from audio_scribe.jobs import state as job_state
|
||||
from audio_scribe.jobs import store
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
@@ -4,10 +4,10 @@ from typing import TYPE_CHECKING
|
||||
|
||||
import pytest
|
||||
|
||||
from ccn_transcribe import paths
|
||||
from ccn_transcribe.jobs import state as job_state
|
||||
from ccn_transcribe.jobs import verify
|
||||
from ccn_transcribe.media import ffmpeg
|
||||
from audio_scribe import paths
|
||||
from audio_scribe.jobs import state as job_state
|
||||
from audio_scribe.jobs import verify
|
||||
from audio_scribe.media import ffmpeg
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
@@ -7,8 +7,8 @@ from typing import TYPE_CHECKING
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from ccn_transcribe import errors
|
||||
from ccn_transcribe.media import ffmpeg
|
||||
from audio_scribe import errors
|
||||
from audio_scribe.media import ffmpeg
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
@@ -6,7 +6,7 @@ from typing import TYPE_CHECKING
|
||||
|
||||
import pytest
|
||||
|
||||
from ccn_transcribe.media import ytdlp_opts as opts
|
||||
from audio_scribe.media import ytdlp_opts as opts
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ from typing import TYPE_CHECKING
|
||||
|
||||
import pytest
|
||||
|
||||
from ccn_transcribe import paths
|
||||
from audio_scribe import paths
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
@@ -4,9 +4,9 @@ from typing import TYPE_CHECKING, Any
|
||||
|
||||
import pytest
|
||||
|
||||
from ccn_transcribe import errors, paths
|
||||
from ccn_transcribe.media import ytdlp_opts
|
||||
from ccn_transcribe.stages import download
|
||||
from audio_scribe import errors, paths
|
||||
from audio_scribe.media import ytdlp_opts
|
||||
from audio_scribe.stages import download
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
@@ -5,13 +5,13 @@ from typing import TYPE_CHECKING, ClassVar
|
||||
|
||||
import pytest
|
||||
|
||||
from ccn_transcribe import errors, paths
|
||||
from ccn_transcribe.backends.base import ToolchainStatus, TranscribeRequest
|
||||
from ccn_transcribe.media import ffmpeg
|
||||
from ccn_transcribe.stages import audio as audio_stage
|
||||
from ccn_transcribe.stages import outputs as outputs_stage
|
||||
from ccn_transcribe.stages import transcribe as transcribe_stage
|
||||
from ccn_transcribe.transcript import Segment, TranscriptResult
|
||||
from audio_scribe import errors, paths
|
||||
from audio_scribe.backends.base import ToolchainStatus, TranscribeRequest
|
||||
from audio_scribe.media import ffmpeg
|
||||
from audio_scribe.stages import audio as audio_stage
|
||||
from audio_scribe.stages import outputs as outputs_stage
|
||||
from audio_scribe.stages import transcribe as transcribe_stage
|
||||
from audio_scribe.transcript import Segment, TranscriptResult
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
@@ -4,7 +4,7 @@ import logging
|
||||
|
||||
import pytest
|
||||
|
||||
from ccn_transcribe.transcript import Segment, TranscriptResult, normalize_segments
|
||||
from audio_scribe.transcript import Segment, TranscriptResult, normalize_segments
|
||||
|
||||
|
||||
def _result(**kw: object) -> TranscriptResult:
|
||||
|
||||
@@ -93,6 +93,53 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/cf/1c5f42b110e57bc5502eb80dbc3b03d256926062519224835ef08134f1f9/astroid-4.0.4-py3-none-any.whl", hash = "sha256:52f39653876c7dec3e3afd4c2696920e05c83832b9737afc21928f2d2eb7a753", size = 276445, upload-time = "2026-02-07T23:35:05.344Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "audio-scribe"
|
||||
version = "0.1.0"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "huggingface-hub" },
|
||||
{ name = "numpy" },
|
||||
{ name = "openvino" },
|
||||
{ name = "openvino-genai" },
|
||||
{ name = "yt-dlp", extra = ["default", "deno"] },
|
||||
{ name = "yt-dlp-ejs" },
|
||||
]
|
||||
|
||||
[package.dev-dependencies]
|
||||
dev = [
|
||||
{ name = "mypy" },
|
||||
{ name = "pre-commit" },
|
||||
{ name = "pylint" },
|
||||
{ name = "pyright" },
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-cov" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "click", specifier = ">=8.1,<9" },
|
||||
{ name = "huggingface-hub", specifier = ">=1.31,<2" },
|
||||
{ name = "numpy", specifier = ">=2.5,<3" },
|
||||
{ name = "openvino", specifier = "==2026.3.1" },
|
||||
{ name = "openvino-genai", specifier = "==2026.3.1.0" },
|
||||
{ name = "yt-dlp", extras = ["default", "deno"], specifier = ">=2026.8.19" },
|
||||
{ name = "yt-dlp-ejs", specifier = ">=0.8" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "mypy", specifier = ">=1.11" },
|
||||
{ name = "pre-commit", specifier = ">=3.8" },
|
||||
{ name = "pylint", specifier = ">=3.2" },
|
||||
{ name = "pyright", specifier = ">=1.1.380" },
|
||||
{ name = "pytest", specifier = ">=8" },
|
||||
{ name = "pytest-cov", specifier = ">=5" },
|
||||
{ name = "ruff", specifier = ">=0.6" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "brotli"
|
||||
version = "1.2.0"
|
||||
@@ -152,53 +199,6 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/95/ae/afd54e744df93b51cc29f6a19beccf9998b25743d7177697390de10479d1/brotlicffi-1.2.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:489ca4da3ee65926d72bf01584b61088a9da6bdd1bb01b2040901e1beaffa8f0", size = 379761, upload-time = "2026-08-21T17:29:10.687Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ccn-transcribe"
|
||||
version = "0.1.0"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "huggingface-hub" },
|
||||
{ name = "numpy" },
|
||||
{ name = "openvino" },
|
||||
{ name = "openvino-genai" },
|
||||
{ name = "yt-dlp", extra = ["default", "deno"] },
|
||||
{ name = "yt-dlp-ejs" },
|
||||
]
|
||||
|
||||
[package.dev-dependencies]
|
||||
dev = [
|
||||
{ name = "mypy" },
|
||||
{ name = "pre-commit" },
|
||||
{ name = "pylint" },
|
||||
{ name = "pyright" },
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-cov" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "click", specifier = ">=8.1,<9" },
|
||||
{ name = "huggingface-hub", specifier = ">=1.31,<2" },
|
||||
{ name = "numpy", specifier = ">=2.5,<3" },
|
||||
{ name = "openvino", specifier = "==2026.3.1" },
|
||||
{ name = "openvino-genai", specifier = "==2026.3.1.0" },
|
||||
{ name = "yt-dlp", extras = ["default", "deno"], specifier = ">=2026.8.19" },
|
||||
{ name = "yt-dlp-ejs", specifier = ">=0.8" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "mypy", specifier = ">=1.11" },
|
||||
{ name = "pre-commit", specifier = ">=3.8" },
|
||||
{ name = "pylint", specifier = ">=3.2" },
|
||||
{ name = "pyright", specifier = ">=1.1.380" },
|
||||
{ name = "pytest", specifier = ">=8" },
|
||||
{ name = "pytest-cov", specifier = ">=5" },
|
||||
{ name = "ruff", specifier = ">=0.6" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2026.7.22"
|
||||
|
||||
Reference in New Issue
Block a user