localcaption 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. localcaption-0.1.0/.github/ISSUE_TEMPLATE/bug_report.yml +63 -0
  2. localcaption-0.1.0/.github/ISSUE_TEMPLATE/config.yml +8 -0
  3. localcaption-0.1.0/.github/ISSUE_TEMPLATE/feature_request.yml +32 -0
  4. localcaption-0.1.0/.github/pull_request_template.md +20 -0
  5. localcaption-0.1.0/.github/workflows/ci.yml +67 -0
  6. localcaption-0.1.0/.github/workflows/release.yml +144 -0
  7. localcaption-0.1.0/.gitignore +24 -0
  8. localcaption-0.1.0/CHANGELOG.md +34 -0
  9. localcaption-0.1.0/CODE_OF_CONDUCT.md +39 -0
  10. localcaption-0.1.0/CONTRIBUTING.md +64 -0
  11. localcaption-0.1.0/LICENSE +21 -0
  12. localcaption-0.1.0/PKG-INFO +333 -0
  13. localcaption-0.1.0/README.md +278 -0
  14. localcaption-0.1.0/SECURITY.md +31 -0
  15. localcaption-0.1.0/docs/RELEASING.md +107 -0
  16. localcaption-0.1.0/docs/diagrams/architecture.mmd +65 -0
  17. localcaption-0.1.0/docs/diagrams/architecture.png +0 -0
  18. localcaption-0.1.0/docs/diagrams/pipeline.mmd +41 -0
  19. localcaption-0.1.0/docs/diagrams/pipeline.png +0 -0
  20. localcaption-0.1.0/docs/diagrams/sequence.mmd +58 -0
  21. localcaption-0.1.0/docs/diagrams/sequence.png +0 -0
  22. localcaption-0.1.0/pyproject.toml +69 -0
  23. localcaption-0.1.0/scripts/install.sh +127 -0
  24. localcaption-0.1.0/scripts/setup.sh +91 -0
  25. localcaption-0.1.0/src/localcaption/__init__.py +14 -0
  26. localcaption-0.1.0/src/localcaption/__main__.py +10 -0
  27. localcaption-0.1.0/src/localcaption/_logging.py +26 -0
  28. localcaption-0.1.0/src/localcaption/audio.py +48 -0
  29. localcaption-0.1.0/src/localcaption/cli.py +260 -0
  30. localcaption-0.1.0/src/localcaption/download.py +79 -0
  31. localcaption-0.1.0/src/localcaption/errors.py +27 -0
  32. localcaption-0.1.0/src/localcaption/pipeline.py +82 -0
  33. localcaption-0.1.0/src/localcaption/whisper.py +103 -0
  34. localcaption-0.1.0/tests/__init__.py +0 -0
  35. localcaption-0.1.0/tests/test_cli_doctor.py +89 -0
  36. localcaption-0.1.0/tests/test_imports.py +34 -0
  37. localcaption-0.1.0/tests/test_whisper_paths.py +46 -0
@@ -0,0 +1,63 @@
1
+ name: πŸ› Bug report
2
+ description: Something is broken or doesn't behave as documented.
3
+ labels: ["bug", "triage"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Thanks for taking the time to file a bug report!
9
+ Please run `pip install -U yt-dlp` and try again first β€” the vast
10
+ majority of "YouTube broke it" issues are upstream extractor regressions.
11
+
12
+ - type: input
13
+ id: command
14
+ attributes:
15
+ label: Exact command you ran
16
+ placeholder: localcaption "https://www.youtube.com/watch?v=..."
17
+ validations:
18
+ required: true
19
+
20
+ - type: textarea
21
+ id: error
22
+ attributes:
23
+ label: Full output (including stack trace)
24
+ render: shell
25
+ validations:
26
+ required: true
27
+
28
+ - type: input
29
+ id: localcaption-version
30
+ attributes:
31
+ label: localcaption version
32
+ description: Output of `localcaption --version`
33
+ validations:
34
+ required: true
35
+
36
+ - type: input
37
+ id: ytdlp-version
38
+ attributes:
39
+ label: yt-dlp version
40
+ description: Output of `yt-dlp --version`
41
+ validations:
42
+ required: true
43
+
44
+ - type: input
45
+ id: env
46
+ attributes:
47
+ label: OS / Python version
48
+ placeholder: "macOS 14.5 / Python 3.12.3"
49
+ validations:
50
+ required: true
51
+
52
+ - type: textarea
53
+ id: doctor
54
+ attributes:
55
+ label: Output of `localcaption doctor`
56
+ description: Paste the full output. This catches 90% of "it doesn't work" causes.
57
+ render: shell
58
+
59
+ - type: textarea
60
+ id: context
61
+ attributes:
62
+ label: Anything else?
63
+ description: Logs, screenshots, model used, etc.
@@ -0,0 +1,8 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: πŸ’¬ Discussion / question
4
+ url: https://github.com/jatinkrmalik/localcaption/discussions
5
+ about: Ask a question or share what you're building.
6
+ - name: πŸ”’ Security report
7
+ url: https://github.com/jatinkrmalik/localcaption/security/advisories/new
8
+ about: Report a security vulnerability privately.
@@ -0,0 +1,32 @@
1
+ name: ✨ Feature request
2
+ description: Suggest an idea for localcaption.
3
+ labels: ["enhancement", "triage"]
4
+ body:
5
+ - type: textarea
6
+ id: problem
7
+ attributes:
8
+ label: What problem are you trying to solve?
9
+ description: A clear and concise description of the use case.
10
+ validations:
11
+ required: true
12
+
13
+ - type: textarea
14
+ id: proposal
15
+ attributes:
16
+ label: Proposed solution
17
+ description: How would you like this to work? CLI flag? Python API? Config?
18
+ validations:
19
+ required: true
20
+
21
+ - type: textarea
22
+ id: alternatives
23
+ attributes:
24
+ label: Alternatives you've considered
25
+
26
+ - type: checkboxes
27
+ id: scope
28
+ attributes:
29
+ label: Scope check
30
+ options:
31
+ - label: This stays within the project's "thin local orchestrator" scope (no cloud APIs, no GUIs).
32
+ required: true
@@ -0,0 +1,20 @@
1
+ ## What changed
2
+
3
+ <!-- A short description of the change. Link any related issues with `Closes #123`. -->
4
+
5
+ ## Why
6
+
7
+ <!-- The motivation. What problem does this solve for users / contributors? -->
8
+
9
+ ## How
10
+
11
+ <!-- Brief implementation notes. Anything reviewers should pay attention to. -->
12
+
13
+ ## Checklist
14
+
15
+ - [ ] Tests added or updated.
16
+ - [ ] `pytest` passes locally.
17
+ - [ ] `ruff check src tests` passes.
18
+ - [ ] `CHANGELOG.md` updated under `## [Unreleased]` (for user-visible changes).
19
+ - [ ] Public APIs have docstrings.
20
+ - [ ] No new external dependencies (or, if added, justified above).
@@ -0,0 +1,67 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ permissions:
10
+ contents: read
11
+
12
+ concurrency:
13
+ group: ci-${{ github.ref }}
14
+ cancel-in-progress: true
15
+
16
+ jobs:
17
+ test:
18
+ name: test (py${{ matrix.python-version }} on ${{ matrix.os }})
19
+ runs-on: ${{ matrix.os }}
20
+ strategy:
21
+ fail-fast: false
22
+ matrix:
23
+ os: [ubuntu-latest, macos-latest]
24
+ python-version: ["3.10", "3.11", "3.12"]
25
+
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+
29
+ - name: Set up Python
30
+ uses: actions/setup-python@v5
31
+ with:
32
+ python-version: ${{ matrix.python-version }}
33
+ cache: pip
34
+
35
+ - name: Install package + dev extras
36
+ run: |
37
+ python -m pip install --upgrade pip
38
+ pip install -e .[dev]
39
+
40
+ - name: Lint
41
+ run: ruff check src tests
42
+
43
+ - name: Run tests
44
+ run: pytest -q
45
+
46
+ build:
47
+ name: build sdist + wheel
48
+ runs-on: ubuntu-latest
49
+ needs: test
50
+ steps:
51
+ - uses: actions/checkout@v4
52
+
53
+ - uses: actions/setup-python@v5
54
+ with:
55
+ python-version: "3.12"
56
+ cache: pip
57
+
58
+ - name: Build distributions
59
+ run: |
60
+ python -m pip install --upgrade pip build
61
+ python -m build
62
+
63
+ - name: Upload artefacts
64
+ uses: actions/upload-artifact@v4
65
+ with:
66
+ name: dist
67
+ path: dist/
@@ -0,0 +1,144 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ # Cancel any in-flight release for the same tag (e.g. if someone re-pushes).
9
+ concurrency:
10
+ group: release-${{ github.ref }}
11
+ cancel-in-progress: false # never abort a real release in flight
12
+
13
+ env:
14
+ PYTHON_VERSION: '3.12'
15
+
16
+ jobs:
17
+ # ─────────────────────────────────────────────────────────────────────
18
+ # 1. Build sdist + wheel, validate metadata, sanity-check version.
19
+ # ─────────────────────────────────────────────────────────────────────
20
+ build:
21
+ name: Build & validate
22
+ runs-on: ubuntu-latest
23
+ permissions:
24
+ contents: read
25
+ outputs:
26
+ version: ${{ steps.tag.outputs.version }}
27
+ steps:
28
+ - uses: actions/checkout@v4
29
+ with:
30
+ fetch-depth: 0
31
+
32
+ - uses: actions/setup-python@v5
33
+ with:
34
+ python-version: ${{ env.PYTHON_VERSION }}
35
+ cache: pip
36
+
37
+ - name: Install build tooling
38
+ run: |
39
+ python -m pip install --upgrade pip
40
+ pip install build twine
41
+
42
+ - name: Extract version from git tag
43
+ id: tag
44
+ run: |
45
+ VERSION=${GITHUB_REF#refs/tags/v}
46
+ echo "version=$VERSION" >> "$GITHUB_OUTPUT"
47
+ echo "Tag version: $VERSION"
48
+
49
+ - name: Verify pyproject.toml version matches tag
50
+ run: |
51
+ PKG_VERSION=$(python -c "import tomllib,sys; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
52
+ TAG_VERSION="${{ steps.tag.outputs.version }}"
53
+ echo "pyproject.toml version: $PKG_VERSION"
54
+ echo "git tag version: $TAG_VERSION"
55
+ if [ "$PKG_VERSION" != "$TAG_VERSION" ]; then
56
+ echo "::error::pyproject.toml version ($PKG_VERSION) does not match git tag ($TAG_VERSION)."
57
+ echo "::error::Bump pyproject.toml or re-tag, then push."
58
+ exit 1
59
+ fi
60
+
61
+ - name: Build sdist + wheel
62
+ run: |
63
+ python -m build
64
+ ls -la dist/
65
+
66
+ - name: Validate distributions
67
+ run: twine check --strict dist/*
68
+
69
+ - name: Upload artefacts
70
+ uses: actions/upload-artifact@v4
71
+ with:
72
+ name: dist
73
+ path: dist/
74
+ if-no-files-found: error
75
+ retention-days: 7
76
+
77
+ # ─────────────────────────────────────────────────────────────────────
78
+ # 2. Publish to PyPI via Trusted Publishing (OIDC, no API token).
79
+ # ─────────────────────────────────────────────────────────────────────
80
+ publish-pypi:
81
+ name: Publish to PyPI
82
+ needs: build
83
+ runs-on: ubuntu-latest
84
+ environment:
85
+ name: pypi
86
+ url: https://pypi.org/project/localcaption/
87
+ permissions:
88
+ id-token: write # required for Trusted Publishing (OIDC)
89
+ steps:
90
+ - name: Download dist artefacts
91
+ uses: actions/download-artifact@v4
92
+ with:
93
+ name: dist
94
+ path: dist/
95
+
96
+ - name: Publish to PyPI
97
+ uses: pypa/gh-action-pypi-publish@release/v1
98
+
99
+ # ─────────────────────────────────────────────────────────────────────
100
+ # 3. Create the GitHub Release with auto-generated notes + dist files.
101
+ # Runs in parallel with publish-pypi (no dependency between them).
102
+ # ─────────────────────────────────────────────────────────────────────
103
+ github-release:
104
+ name: Create GitHub Release
105
+ needs: build
106
+ runs-on: ubuntu-latest
107
+ permissions:
108
+ contents: write # required to create a release
109
+ steps:
110
+ - uses: actions/checkout@v4
111
+ with:
112
+ fetch-depth: 0
113
+
114
+ - name: Download dist artefacts
115
+ uses: actions/download-artifact@v4
116
+ with:
117
+ name: dist
118
+ path: dist/
119
+
120
+ - name: Create release
121
+ uses: softprops/action-gh-release@v2
122
+ with:
123
+ files: |
124
+ dist/*.whl
125
+ dist/*.tar.gz
126
+ generate_release_notes: true
127
+ draft: false
128
+ prerelease: ${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') || contains(github.ref_name, 'rc') }}
129
+ body: |
130
+ ## Install
131
+
132
+ ### One-line install (recommended)
133
+ ```bash
134
+ curl -fsSL https://raw.githubusercontent.com/jatinkrmalik/localcaption/${{ github.ref_name }}/scripts/install.sh | bash
135
+ ```
136
+
137
+ ### From PyPI
138
+ ```bash
139
+ pipx install localcaption
140
+ ```
141
+
142
+ ---
143
+ See [CHANGELOG.md](https://github.com/jatinkrmalik/localcaption/blob/${{ github.ref_name }}/CHANGELOG.md)
144
+ for the full list of changes.
@@ -0,0 +1,24 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+ build/
7
+ dist/
8
+ .venv/
9
+ venv/
10
+ .pytest_cache/
11
+ .coverage
12
+ htmlcov/
13
+ .ruff_cache/
14
+
15
+ # Project-specific
16
+ whisper.cpp/
17
+ transcripts/
18
+ transcripts_*/
19
+
20
+ # OS / editor
21
+ .DS_Store
22
+ .idea/
23
+ .vscode/
24
+ *.swp
@@ -0,0 +1,34 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Added
11
+ - `scripts/install.sh` β€” one-line end-user installer that uses `pipx` for an
12
+ isolated install and bootstraps `whisper.cpp` + a default model into
13
+ `~/.local/share/localcaption/whisper.cpp` (XDG-compliant). After install,
14
+ `localcaption` is callable from any directory.
15
+ - New `localcaption doctor` subcommand that diagnoses prerequisites,
16
+ whisper.cpp build, and available models. Used by the bug-report template.
17
+ - The CLI now searches a third location for whisper.cpp:
18
+ `$XDG_DATA_HOME/localcaption/whisper.cpp` (after the explicit flag, env var,
19
+ and `./whisper.cpp` dev path).
20
+
21
+ ### Changed
22
+ - `localcaption` invoked with no arguments now prints top-level help and
23
+ exits with code 2 (was: argparse error). Existing `localcaption <url>`
24
+ usage is unchanged.
25
+
26
+ ## [0.1.0] - 2026-04-21
27
+
28
+ ### Added
29
+ - Initial public release as `localcaption`.
30
+ - Modular package layout: `download` (yt-dlp), `audio` (ffmpeg), `whisper`
31
+ (whisper.cpp), orchestrated by `pipeline.transcribe_url`.
32
+ - `localcaption` console script and `python -m localcaption` entry point.
33
+ - One-shot `scripts/setup.sh` that builds whisper.cpp and downloads a model.
34
+ - MIT license, contributor docs, security policy, GitHub Actions CI.
@@ -0,0 +1,39 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behaviour that contributes to a positive environment:
15
+
16
+ - Demonstrating empathy and kindness toward other people
17
+ - Being respectful of differing opinions, viewpoints, and experiences
18
+ - Giving and gracefully accepting constructive feedback
19
+ - Accepting responsibility and apologising to those affected by our mistakes
20
+ - Focusing on what is best for the overall community
21
+
22
+ Unacceptable behaviour includes:
23
+
24
+ - The use of sexualised language or imagery, and sexual attention or advances
25
+ - Trolling, insulting or derogatory comments, and personal or political attacks
26
+ - Public or private harassment
27
+ - Publishing others’ private information without explicit permission
28
+
29
+ ## Enforcement
30
+
31
+ Instances of abusive, harassing, or otherwise unacceptable behaviour may be
32
+ reported to the project maintainers via a private GitHub Security Advisory or
33
+ the contact listed in `SECURITY.md`. All complaints will be reviewed and
34
+ investigated promptly and fairly.
35
+
36
+ ## Attribution
37
+
38
+ This Code of Conduct is adapted from the
39
+ [Contributor Covenant](https://www.contributor-covenant.org), version 2.1.
@@ -0,0 +1,64 @@
1
+ # Contributing to localcaption
2
+
3
+ Thanks for considering a contribution! This project is intentionally small β€”
4
+ the goal is to stay a thin, dependable orchestrator over `yt-dlp`, `ffmpeg`,
5
+ and `whisper.cpp`. PRs that keep that surface tidy are very welcome.
6
+
7
+ ## Quick start
8
+
9
+ ```bash
10
+ git clone https://github.com/jatinkrmalik/localcaption
11
+ cd localcaption
12
+ ./scripts/setup.sh # builds whisper.cpp, sets up venv
13
+ source .venv/bin/activate
14
+ pip install -e .[dev] # if not already done by setup.sh
15
+ pytest # run the test suite
16
+ ruff check src tests # lint
17
+ ```
18
+
19
+ ## Project layout
20
+
21
+ ```
22
+ src/localcaption/
23
+ β”œβ”€β”€ __init__.py
24
+ β”œβ”€β”€ __main__.py # python -m localcaption
25
+ β”œβ”€β”€ _logging.py # tiny stdout logger (no logging-module config)
26
+ β”œβ”€β”€ audio.py # ffmpeg β†’ 16 kHz mono WAV (stage 2)
27
+ β”œβ”€β”€ cli.py # argparse entry point (the `localcaption` script)
28
+ β”œβ”€β”€ download.py # yt-dlp Python API wrapper (stage 1)
29
+ β”œβ”€β”€ errors.py # exception hierarchy
30
+ β”œβ”€β”€ pipeline.py # public Python API: transcribe_url(...)
31
+ └── whisper.py # whisper.cpp invocation (stage 3)
32
+ scripts/
33
+ └── setup.sh # bootstraps whisper.cpp + venv + model
34
+ tests/ # pytest suite
35
+ ```
36
+
37
+ Each pipeline stage is its own module so you can swap one out (e.g. replace
38
+ the `whisper.cpp` backend with `faster-whisper`) without touching the others.
39
+
40
+ ## Pull request checklist
41
+
42
+ - [ ] `pytest` passes.
43
+ - [ ] `ruff check src tests` passes (the CI runs both).
44
+ - [ ] New behaviour is covered by a test.
45
+ - [ ] User-visible changes are noted in `CHANGELOG.md` under `## [Unreleased]`.
46
+ - [ ] Public APIs have docstrings.
47
+
48
+ ## Reporting bugs
49
+
50
+ Please include:
51
+
52
+ - The exact command you ran.
53
+ - The output of `localcaption --version` and `yt-dlp --version`.
54
+ - Your OS + Python version (`python --version`).
55
+ - Whether `whisper.cpp` was built with CMake or `make`.
56
+
57
+ For YouTube-side issues (HTTP 4xx, "Sign in to confirm…"), try
58
+ `pip install -U yt-dlp` first β€” those are usually upstream extractor breakage,
59
+ not bugs in this project.
60
+
61
+ ## Code of Conduct
62
+
63
+ This project follows the [Contributor Covenant](CODE_OF_CONDUCT.md).
64
+ By participating you agree to abide by its terms.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jatin Kumar Malik
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.