From 11b22614c2ed7279d2a5b7f31379afb673549dd5 Mon Sep 17 00:00:00 2001 From: hp Date: Tue, 26 May 2026 10:51:43 +0800 Subject: [PATCH 1/3] docs: improve open source readiness --- .github/ISSUE_TEMPLATE/bug_report.yml | 63 +++++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 5 ++ .github/ISSUE_TEMPLATE/feature_request.yml | 53 +++++++++++++++++ AGENT.md | 5 +- CHANGELOG.md | 24 ++++++++ CODE_OF_CONDUCT.md | 25 ++++++++ CONTRIBUTING.md | 66 ++++++++++++++++++++++ LICENSE | 21 +++++++ README.md | 22 ++++++-- ROADMAP.md | 32 +++++++++++ SECURITY.md | 28 +++++++++ pyproject.toml | 38 +++++++++++++ tests/test_package.py | 19 +++++++ 13 files changed, 392 insertions(+), 9 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 CHANGELOG.md create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 LICENSE create mode 100644 ROADMAP.md create mode 100644 SECURITY.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..66e7cd1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,63 @@ +name: Bug report +description: Report a reproducible problem with echoalign-asr-mlx. +title: "[Bug]: " +labels: + - bug +body: + - type: markdown + attributes: + value: | + Thanks for helping improve echoalign-asr-mlx. Please avoid attaching private media, credentials, or copyrighted material unless you have permission to share it. + - type: input + id: version + attributes: + label: Version + description: Package version, Git tag, or commit SHA. + placeholder: "v0.4.0 or commit SHA" + validations: + required: true + - type: input + id: environment + attributes: + label: Environment + description: macOS version, Apple Silicon chip, and Python version. + placeholder: "macOS 15.x, M3 Pro, Python 3.14" + validations: + required: true + - type: textarea + id: command + attributes: + label: Command + description: The exact command you ran. + render: bash + placeholder: "easr ./demo.mp4 --verbose" + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected behavior + description: What did you expect to happen? + validations: + required: true + - type: textarea + id: actual + attributes: + label: Actual behavior + description: What happened instead? + validations: + required: true + - type: textarea + id: logs + attributes: + label: Logs or output + description: Paste relevant terminal output. Remove private paths, tokens, and media names if needed. + render: text + - type: checkboxes + id: checks + attributes: + label: Checks + options: + - label: I confirmed `ffmpeg` and `ffprobe` are on PATH. + - label: I tried a clean shell or fresh virtual environment. + - label: I can reproduce this with a non-private sample or synthetic fixture. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..2a00466 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: true +contact_links: + - name: Security reports + url: https://github.com/morehardy/echoalign-asr-mlx/blob/main/SECURITY.md + about: Read the security policy before reporting sensitive issues. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..8f597f2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,53 @@ +name: Feature request +description: Suggest an improvement or new workflow for echoalign-asr-mlx. +title: "[Feature]: " +labels: + - enhancement +body: + - type: markdown + attributes: + value: | + Thanks for suggesting an improvement. The project is currently focused on local Apple Silicon transcription, subtitle export, and timestamp-aligned JSON. + - type: textarea + id: problem + attributes: + label: Problem + description: What workflow or limitation should this solve? + placeholder: "I want to..." + validations: + required: true + - type: textarea + id: proposal + attributes: + label: Proposed solution + description: What would the ideal behavior look like? + validations: + required: true + - type: dropdown + id: area + attributes: + label: Area + options: + - CLI behavior + - Subtitle export + - JSON contract + - Provider/runtime + - VAD or timing quality + - Documentation + - Packaging or release + - Other + validations: + required: true + - type: textarea + id: alternatives + attributes: + label: Alternatives considered + description: What have you tried already, or what trade-offs should be considered? + - type: checkboxes + id: scope + attributes: + label: Scope checks + options: + - label: This can preserve the existing default output layout. + - label: This can preserve the timestamped JSON contract. + - label: This does not require sharing private or copyrighted media. diff --git a/AGENT.md b/AGENT.md index 308044c..7e76be0 100644 --- a/AGENT.md +++ b/AGENT.md @@ -32,7 +32,7 @@ The current first-phase goal is: ## CLI Contract -- Public command name: `asr` +- Public command name: `easr` - Phase 1 user experience should feel like a single-command CLI. - If no input path is provided, the CLI must default to the current working directory. - The CLI must support: @@ -54,7 +54,7 @@ Phase 1 should explicitly support these formats: ## Output Rules -- Default output formats: `srt`, `vtt`, `json`, `txt`(txt do not have time stamp ) +- Default output formats: `srt`, `vtt`, `json` - Default overwrite behavior: overwrite existing outputs - Default output directory name: `outputs` - The CLI must support overriding the output directory through a flag such as `--output-dir` @@ -71,7 +71,6 @@ Examples: - `/path/media/demo.mp4` -> `/path/media/outputs/demo.srt` - `/path/media/demo.mp4` -> `/path/media/outputs/demo.vtt` -- `/path/media/demo.mp4` -> `/path/media/outputs/demo.txt` - `/path/media/demo.mp4` -> `/path/media/outputs/demo.json` - `/path/media/sub/a.wav` with input root `/path/media` -> `/path/media/outputs/sub/a.srt` diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..6893916 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,24 @@ +# Changelog + +Notable user-facing changes are tracked here. + +This project uses Git tags such as `v0.4.0` and tag-derived package versions. + +## Unreleased + +### Added + +- PyPI discovery metadata: keywords, classifiers, author, and project URLs. +- Community files for contributions, security reporting, conduct expectations, and roadmap planning. +- GitHub issue templates for bug reports and feature requests. +- MIT License. + +### Changed + +- README structure now emphasizes the user-facing CLI value, install path, and search-friendly project positioning. + +## Previous Releases + +See GitHub Releases for published release notes and artifacts: + +- https://github.com/morehardy/echoalign-asr-mlx/releases diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..20fff75 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,25 @@ +# Code of Conduct + +`echoalign-asr-mlx` aims to be a practical, respectful project for people building local speech, subtitle, and alignment workflows. + +## Expected Behavior + +- Be respectful and constructive. +- Assume good intent, but accept corrections when something lands poorly. +- Keep feedback specific to the code, documentation, design, or user workflow. +- Make room for contributors with different experience levels. +- Avoid sharing private media, sensitive logs, credentials, or other personal data. + +## Unacceptable Behavior + +- Harassment, threats, insults, or personal attacks. +- Sexualized language or imagery. +- Publishing private information without permission. +- Repeatedly derailing issues or pull requests after maintainers ask to refocus. +- Any behavior that makes the project unsafe or unwelcoming. + +## Enforcement + +Maintainers may edit, hide, or delete comments; close issues or pull requests; block users; or take other reasonable moderation action when needed. + +If you need to report conduct concerns, contact the maintainer privately when possible. If no private channel is available, open a minimal issue asking for a private contact path without naming people or sharing sensitive details. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..68fb15c --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,66 @@ +# Contributing to echoalign-asr-mlx + +Thanks for taking the time to improve `echoalign-asr-mlx`. + +This project is a local Apple Silicon CLI for extracting subtitles and timestamp-aligned transcription data from audio and video files. Contributions are most useful when they preserve the stable CLI contract, the output layout, and the backend-neutral transcription model. + +## Before You Start + +- Open an issue first for larger behavior changes, new providers, output format changes, or anything that changes the JSON contract. +- Small documentation fixes, typo fixes, and focused test improvements can go straight to a pull request. +- Do not commit large media files, model files, generated output directories, private audio/video, or local environment folders. +- Contributions are accepted under the MIT License. + +## Development Setup + +Install the project dependencies: + +```bash +uv sync +``` + +For the full local transcription runtime, install the MLX extra: + +```bash +uv sync --extra mlx +``` + +Run the unit test suite: + +```bash +PYTHONPATH=src uv run --python 3.14 python -m unittest discover -s tests -p 'test_*.py' +``` + +Dry-check CLI parsing: + +```bash +uv run --python 3.14 easr --help +``` + +## Pull Request Checklist + +- Keep changes focused on one behavior or documentation improvement. +- Add or update tests for code changes. +- Update `README.md`, `docs/development.md`, or `CHANGELOG.md` when user-facing behavior changes. +- Keep default output files stable: `.srt`, `.vtt`, `.json`, and optional `.metrics.json` with `--verbose`. +- Preserve the provider boundary; provider-specific details should not leak into the public CLI contract. +- Confirm generated files and local outputs are not included in the diff. + +## Useful Areas for Contributions + +- Documentation examples and troubleshooting notes. +- Small fixtures or synthetic media-free tests. +- Subtitle segmentation and timing quality checks. +- Better diagnostics for installation and runtime failures. +- Provider-boundary improvements that keep the CLI stable. + +## Reporting Problems + +Use the bug report template and include: + +- macOS version and Apple Silicon chip. +- Python version. +- install method (`pip`, `uv`, source checkout). +- exact `easr` command. +- whether `ffmpeg`, `ffprobe`, and MLX preflight pass. +- a short, non-private sample or reproducible fixture when possible. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..384b485 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 morehardy + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 3c82b7f..b968664 100644 --- a/README.md +++ b/README.md @@ -4,17 +4,23 @@ # echoalign-asr-mlx +[![CI](https://github.com/morehardy/echoalign-asr-mlx/actions/workflows/ci.yml/badge.svg)](https://github.com/morehardy/echoalign-asr-mlx/actions/workflows/ci.yml) +[![PyPI](https://img.shields.io/pypi/v/echoalign-asr-mlx.svg)](https://pypi.org/project/echoalign-asr-mlx/) +[![Python](https://img.shields.io/pypi/pyversions/echoalign-asr-mlx.svg)](https://pypi.org/project/echoalign-asr-mlx/) +[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) + `easr` is a local Apple Silicon CLI that turns audio and video files into subtitle files (`.srt`, `.vtt`) and timestamp-aligned JSON. -Use it when you want local transcription, readable subtitles, and -machine-friendly alignment data without running a server. +Use it when you want local speech recognition, forced alignment, readable +subtitles, and machine-friendly timing data without running a server. Current scope: - runtime target: macOS on Apple Silicon - backend: MLX with Qwen3 ASR and Qwen3 ForcedAligner - output: SRT, WebVTT, and JSON +- license: MIT - not included yet: translation, speaker diarization, Linux/Windows support ## What You Get @@ -51,7 +57,7 @@ Default provider models: ## Installation -Install from a published Python package: +Install from PyPI: ```bash python3.14 -m pip install "echoalign-asr-mlx[mlx]" @@ -283,7 +289,11 @@ is warmed. Later runs should be faster. - Subtitle segmentation quality depends on model and alignment behavior. - The public CLI does not expose provider selection. -## Developer Documentation +## Development and Community -Development setup, test commands, build instructions, and release notes live in -[docs/development.md](docs/development.md). +- [Contributing guide](CONTRIBUTING.md) +- [Development guide](docs/development.md) +- [Roadmap](ROADMAP.md) +- [Changelog](CHANGELOG.md) +- [Security policy](SECURITY.md) +- [Code of conduct](CODE_OF_CONDUCT.md) diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 0000000..6f2bf35 --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,32 @@ +# Roadmap + +This roadmap is directional, not a release commitment. The project should keep its default local CLI simple while improving transcription quality, contribution readiness, and backend flexibility. + +## Current Focus + +- Make the project easier to discover on GitHub and PyPI. +- Improve contributor entry points and issue reporting. +- Keep the Apple Silicon + MLX runtime stable. +- Preserve the existing output contract: `.srt`, `.vtt`, `.json`, and optional `.metrics.json`. + +## Near-Term + +- Add small, safe sample fixtures that do not require large media files. +- Expand troubleshooting docs for MLX, Metal, model downloads, and `ffmpeg` setup. +- Document the JSON output contract with field-level examples. +- Add release-note discipline through `CHANGELOG.md`. + +## Product Direction + +- Improve subtitle segmentation and timing repair. +- Add richer quality diagnostics for failed or low-confidence windows. +- Add plain text export if it can be done without weakening the timestamped JSON contract. +- Expand provider support behind the existing provider boundary. +- Explore speaker metadata and diarization when a provider can support it reliably. + +## Out of Scope for Now + +- Hosted API or service deployment. +- Linux and Windows runtime support. +- Public provider selection flags before the provider contract is ready for that UX. +- Translation output as part of the default transcription flow. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..85e6eea --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,28 @@ +# Security Policy + +## Supported Versions + +Security fixes are handled for the latest published release and the current `main` branch. + +## Reporting a Vulnerability + +Please do not open a public issue with exploit details, private media, credentials, logs containing secrets, or vulnerability proof-of-concept material. + +Preferred reporting path: + +1. Use GitHub private vulnerability reporting if it is enabled for this repository. +2. If private reporting is not available, open a minimal public issue asking for a private maintainer contact path. Do not include sensitive details in that issue. + +Helpful details include: + +- affected version or commit +- operating system and Python version +- install method +- concise impact description +- reproduction steps that do not expose private files + +## Scope + +Reports related to the CLI, package metadata, build and release workflows, or local file handling are in scope. + +Reports for third-party model weights, MLX, `ffmpeg`, `ffprobe`, `silero-vad`, or other upstream dependencies should also be reported to the relevant upstream project. diff --git a/pyproject.toml b/pyproject.toml index a1c8493..bd4c8c0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,6 +8,37 @@ dynamic = ["version"] description = "Local CLI for extracting subtitles and aligned timestamps from audio and video." readme = "README.md" requires-python = ">=3.14,<3.15" +license = "MIT" +authors = [ + { name = "morehardy" }, +] +keywords = [ + "apple-silicon", + "asr", + "automatic-speech-recognition", + "forced-alignment", + "mlx", + "qwen3", + "speech-recognition", + "srt", + "subtitles", + "transcription", + "webvtt", +] +classifiers = [ + "Development Status :: 4 - Beta", + "Environment :: Console", + "Intended Audience :: Developers", + "Intended Audience :: End Users/Desktop", + "License :: OSI Approved :: MIT License", + "Operating System :: MacOS", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.14", + "Topic :: Multimedia :: Sound/Audio :: Speech", + "Topic :: Multimedia :: Video", + "Topic :: Text Processing", + "Topic :: Utilities", +] dependencies = [ "rich>=14.0,<15.0", "typer>=0.16,<1.0", @@ -23,6 +54,13 @@ mlx = [ [project.scripts] easr = "asr.cli:main" +[project.urls] +Homepage = "https://github.com/morehardy/echoalign-asr-mlx" +Repository = "https://github.com/morehardy/echoalign-asr-mlx" +Issues = "https://github.com/morehardy/echoalign-asr-mlx/issues" +Changelog = "https://github.com/morehardy/echoalign-asr-mlx/blob/main/CHANGELOG.md" +Roadmap = "https://github.com/morehardy/echoalign-asr-mlx/blob/main/ROADMAP.md" + [tool.hatch.version] source = "vcs" tag-pattern = "^v(?P.+)$" diff --git a/tests/test_package.py b/tests/test_package.py index dd0f76a..bf07240 100644 --- a/tests/test_package.py +++ b/tests/test_package.py @@ -24,3 +24,22 @@ def test_mlx_extra_includes_torchcodec_for_silero_vad_audio_io(self) -> None: mlx_dependencies = pyproject["project"]["optional-dependencies"]["mlx"] self.assertIn("torchcodec>=0.11.1", mlx_dependencies) + + def test_package_metadata_includes_discovery_fields(self) -> None: + pyproject = tomllib.loads(Path("pyproject.toml").read_text(encoding="utf-8")) + project = pyproject["project"] + + self.assertIn("speech-recognition", project["keywords"]) + self.assertIn("subtitles", project["keywords"]) + self.assertEqual(project["license"], "MIT") + self.assertIn("Operating System :: MacOS", project["classifiers"]) + self.assertIn("License :: OSI Approved :: MIT License", project["classifiers"]) + self.assertIn("Topic :: Multimedia :: Sound/Audio :: Speech", project["classifiers"]) + self.assertEqual( + project["urls"]["Repository"], + "https://github.com/morehardy/echoalign-asr-mlx", + ) + self.assertEqual( + project["urls"]["Issues"], + "https://github.com/morehardy/echoalign-asr-mlx/issues", + ) From 8b5205be377d31dad2dec67214401838a340a040 Mon Sep 17 00:00:00 2001 From: hp Date: Tue, 26 May 2026 11:01:08 +0800 Subject: [PATCH 2/3] test: resolve pyproject path from test file --- tests/test_package.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/test_package.py b/tests/test_package.py index bf07240..3747a2f 100644 --- a/tests/test_package.py +++ b/tests/test_package.py @@ -5,6 +5,12 @@ import asr +PROJECT_ROOT = Path(__file__).resolve().parents[1] + + +def read_pyproject() -> dict: + return tomllib.loads((PROJECT_ROOT / "pyproject.toml").read_text(encoding="utf-8")) + class PackageMetadataTest(unittest.TestCase): def test_version_comes_from_installed_distribution_metadata(self) -> None: @@ -20,13 +26,13 @@ def test_version_is_defined(self) -> None: self.assertTrue(asr.__version__) def test_mlx_extra_includes_torchcodec_for_silero_vad_audio_io(self) -> None: - pyproject = tomllib.loads(Path("pyproject.toml").read_text(encoding="utf-8")) + pyproject = read_pyproject() mlx_dependencies = pyproject["project"]["optional-dependencies"]["mlx"] self.assertIn("torchcodec>=0.11.1", mlx_dependencies) def test_package_metadata_includes_discovery_fields(self) -> None: - pyproject = tomllib.loads(Path("pyproject.toml").read_text(encoding="utf-8")) + pyproject = read_pyproject() project = pyproject["project"] self.assertIn("speech-recognition", project["keywords"]) From 919a04188ed4d6cfc67b085ee32f9eb545529f3e Mon Sep 17 00:00:00 2001 From: hp Date: Tue, 26 May 2026 11:40:29 +0800 Subject: [PATCH 3/3] REAME.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b968664..4703d85 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@

- echoalign-asr-mlx logo + echoalign-asr-mlx logo

# echoalign-asr-mlx