ytxt 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.
ytxt-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,67 @@
1
+ Metadata-Version: 2.4
2
+ Name: ytxt
3
+ Version: 0.1.0
4
+ Summary: Local audio and YouTube transcription CLI
5
+ Author: Rayan Rane
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/rayanrane/ytxt
8
+ Project-URL: Bug Tracker, https://github.com/rayanrane/ytxt/issues
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.7
12
+ Description-Content-Type: text/markdown
13
+ Requires-Dist: yt-dlp
14
+ Requires-Dist: faster-whisper
15
+
16
+ # ytxt
17
+
18
+ `ytxt` is a local, private CLI tool for transcribing audio from YouTube, web URLs, or local files using `faster-whisper`. All processing happens securely on your machine—no external APIs or cloud services required.
19
+
20
+ ## Installation
21
+
22
+ Ensure you have `ffmpeg` installed on your system. Then, install the project:
23
+
24
+ ```bash
25
+ pip install .
26
+ ```
27
+
28
+ Alternatively, if you are running from the source:
29
+
30
+ ```bash
31
+ pip install -r requirements.txt
32
+ ```
33
+
34
+ ## Usage
35
+
36
+ Basic usage:
37
+ ```bash
38
+ ytxt <url_or_local_file_path>
39
+ ```
40
+
41
+ ### Options
42
+
43
+ - `--format [text|markdown|srt|json]`: Specify output format.
44
+ - `--model [base|small|medium|large]`: Choose the Whisper model size.
45
+ - `--timestamps`: Include start and end times in text/markdown output.
46
+ - `--output <path>`: Save the transcript to a file.
47
+ - `--no-cache`: Force a re-transcription by ignoring existing cache.
48
+
49
+ ### Examples
50
+
51
+ **Transcribe a web URL (YouTube or other):**
52
+ ```bash
53
+ ytxt https://www.example.com/audio.mp3 --format markdown --timestamps --output transcript.md
54
+ ```
55
+
56
+ **Transcribe a local audio file:**
57
+ ```bash
58
+ ytxt path/to/audio.mp3 --model medium --output transcript.txt
59
+ ```
60
+
61
+ ## Features
62
+
63
+ - **Local-Only:** Privacy-first; no data leaves your machine.
64
+ - **Universal Support:** Transcribe YouTube videos, web audio URLs, and local files.
65
+ - **Caching:** Efficiently caches results to avoid redundant work.
66
+ - **Formats:** Supports text, Markdown, SRT, and JSON.
67
+ - **Model Selection:** Flexibility to balance accuracy and performance by choosing your desired Whisper model size.
ytxt-0.1.0/README.md ADDED
@@ -0,0 +1,52 @@
1
+ # ytxt
2
+
3
+ `ytxt` is a local, private CLI tool for transcribing audio from YouTube, web URLs, or local files using `faster-whisper`. All processing happens securely on your machine—no external APIs or cloud services required.
4
+
5
+ ## Installation
6
+
7
+ Ensure you have `ffmpeg` installed on your system. Then, install the project:
8
+
9
+ ```bash
10
+ pip install .
11
+ ```
12
+
13
+ Alternatively, if you are running from the source:
14
+
15
+ ```bash
16
+ pip install -r requirements.txt
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ Basic usage:
22
+ ```bash
23
+ ytxt <url_or_local_file_path>
24
+ ```
25
+
26
+ ### Options
27
+
28
+ - `--format [text|markdown|srt|json]`: Specify output format.
29
+ - `--model [base|small|medium|large]`: Choose the Whisper model size.
30
+ - `--timestamps`: Include start and end times in text/markdown output.
31
+ - `--output <path>`: Save the transcript to a file.
32
+ - `--no-cache`: Force a re-transcription by ignoring existing cache.
33
+
34
+ ### Examples
35
+
36
+ **Transcribe a web URL (YouTube or other):**
37
+ ```bash
38
+ ytxt https://www.example.com/audio.mp3 --format markdown --timestamps --output transcript.md
39
+ ```
40
+
41
+ **Transcribe a local audio file:**
42
+ ```bash
43
+ ytxt path/to/audio.mp3 --model medium --output transcript.txt
44
+ ```
45
+
46
+ ## Features
47
+
48
+ - **Local-Only:** Privacy-first; no data leaves your machine.
49
+ - **Universal Support:** Transcribe YouTube videos, web audio URLs, and local files.
50
+ - **Caching:** Efficiently caches results to avoid redundant work.
51
+ - **Formats:** Supports text, Markdown, SRT, and JSON.
52
+ - **Model Selection:** Flexibility to balance accuracy and performance by choosing your desired Whisper model size.
@@ -0,0 +1,32 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "ytxt"
7
+ version = "0.1.0"
8
+ authors = [
9
+ { name="Rayan Rane" },
10
+ ]
11
+ description = "Local audio and YouTube transcription CLI"
12
+ readme = "README.md"
13
+ requires-python = ">=3.7"
14
+ license = {text = "MIT"}
15
+ classifiers = [
16
+ "Programming Language :: Python :: 3",
17
+ "Operating System :: OS Independent",
18
+ ]
19
+ dependencies = [
20
+ "yt-dlp",
21
+ "faster-whisper",
22
+ ]
23
+
24
+ [project.urls]
25
+ "Homepage" = "https://github.com/rayanrane/ytxt"
26
+ "Bug Tracker" = "https://github.com/rayanrane/ytxt/issues"
27
+
28
+ [project.scripts]
29
+ ytxt = "ytxt.cli:main"
30
+
31
+ [tool.setuptools.packages.find]
32
+ where = ["src"]
ytxt-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,12 @@
1
+ from .downloader import download_audio
2
+ from .transcriber import transcribe_audio
3
+ from .formatter import format_transcript
4
+ from .cache import read_cache, write_cache
5
+
6
+ __all__ = [
7
+ "download_audio",
8
+ "transcribe_audio",
9
+ "format_transcript",
10
+ "read_cache",
11
+ "write_cache",
12
+ ]
@@ -0,0 +1,21 @@
1
+ import json
2
+ import hashlib
3
+ from pathlib import Path
4
+ from typing import Optional, List, Dict
5
+
6
+ CACHE_DIR = Path("cache")
7
+
8
+ def get_cache_path(video_id: str) -> Path:
9
+ CACHE_DIR.mkdir(exist_ok=True)
10
+ return CACHE_DIR / f"{video_id}.json"
11
+
12
+ def read_cache(video_id: str) -> Optional[List[Dict]]:
13
+ path = get_cache_path(video_id)
14
+ if path.exists():
15
+ with open(path, "r") as f:
16
+ return json.load(f)
17
+ return None
18
+
19
+ def write_cache(video_id: str, transcript: List[Dict]):
20
+ with open(get_cache_path(video_id), "w") as f:
21
+ json.dump(transcript, f)
@@ -0,0 +1,72 @@
1
+ import argparse
2
+ import sys
3
+ import hashlib
4
+ import re
5
+ from pathlib import Path
6
+ from .downloader import download_audio
7
+ from .transcriber import transcribe_audio
8
+ from .formatter import format_transcript
9
+ from .cache import read_cache, write_cache
10
+
11
+ def parse_args():
12
+ parser = argparse.ArgumentParser(description="ytxt: Local YouTube transcript CLI")
13
+ parser.add_argument("url", help="YouTube/Audio URL or local file path to transcribe")
14
+ parser.add_argument("--output", help="Output file path")
15
+ parser.add_argument("--format", choices=["text", "markdown", "srt", "json"], default="text", help="Output format")
16
+ parser.add_argument("--model", default="base", help="Whisper model to use")
17
+ parser.add_argument("--timestamps", action="store_true", help="Include timestamps in output")
18
+ parser.add_argument("--no-cache", action="store_true", help="Skip cache usage")
19
+
20
+ return parser.parse_args()
21
+
22
+ def main():
23
+ args = parse_args()
24
+
25
+ input_path = Path(args.url)
26
+
27
+ # Check if local file
28
+ if input_path.exists() and input_path.is_file():
29
+ audio_file = input_path
30
+ # Use absolute path for consistent cache key
31
+ cache_key = hashlib.md5(str(input_path.absolute()).encode()).hexdigest()
32
+ print(f"Using local file: {input_path}")
33
+ else:
34
+ # It's a URL
35
+ # Use URL as cache key for web sources
36
+ cache_key = hashlib.md5(args.url.encode()).hexdigest()
37
+
38
+ # Check cache first
39
+ transcript = None
40
+ if not args.no_cache:
41
+ transcript = read_cache(cache_key)
42
+ if transcript:
43
+ print("Using cached transcript...")
44
+
45
+ if not transcript:
46
+ print(f"Downloading audio from {args.url}...")
47
+ audio_file = download_audio(args.url)
48
+ print("Transcribing...")
49
+ transcript = transcribe_audio(audio_file, args.model)
50
+ write_cache(cache_key, transcript)
51
+ # Cleanup temp file
52
+ if audio_file.exists():
53
+ audio_file.unlink()
54
+ else:
55
+ # We already have the transcript from cache
56
+ pass
57
+
58
+ # Ensure transcript is loaded (from file transcription or cached/downloaded)
59
+ if 'transcript' not in locals():
60
+ print("Transcribing...")
61
+ transcript = transcribe_audio(audio_file, args.model)
62
+
63
+ output = format_transcript(transcript, args.format, args.timestamps)
64
+
65
+ if args.output:
66
+ out_path = Path(args.output)
67
+ out_path.parent.mkdir(parents=True, exist_ok=True)
68
+ out_path.write_text(output)
69
+ print(f"Transcript saved to {out_path}")
70
+ else:
71
+ print(output)
72
+
@@ -0,0 +1,33 @@
1
+ import yt_dlp
2
+ import uuid
3
+ from pathlib import Path
4
+
5
+ def download_audio(url: str, output_dir: Path = Path("temp")) -> Path:
6
+ """Downloads audio from any yt-dlp supported site."""
7
+ output_dir.mkdir(exist_ok=True)
8
+
9
+ # Use a unique ID for the filename to prevent collisions
10
+ unique_id = str(uuid.uuid4())
11
+
12
+ ydl_opts = {
13
+ 'format': 'bestaudio/best',
14
+ 'outtmpl': str(output_dir / f"{unique_id}.%(ext)s"),
15
+ 'postprocessors': [{
16
+ 'key': 'FFmpegExtractAudio',
17
+ 'preferredcodec': 'mp3',
18
+ 'preferredquality': '192',
19
+ }],
20
+ }
21
+
22
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
23
+ info = ydl.extract_info(url, download=True)
24
+
25
+ # yt-dlp returns info about the download.
26
+ # If it was a playlist, we might need to handle multiple files,
27
+ # but for now we assume a single download.
28
+ if 'entries' in info:
29
+ # Handle playlist: get the first item
30
+ info = info['entries'][0]
31
+
32
+ audio_file = output_dir / f"{unique_id}.mp3"
33
+ return audio_file
@@ -0,0 +1,28 @@
1
+ import json
2
+ from pathlib import Path
3
+ from typing import List, Dict
4
+
5
+ def format_transcript(transcript: List[Dict], format_type: str, include_timestamps: bool = False) -> str:
6
+ """Formats transcript data into requested format."""
7
+ if format_type == "json":
8
+ return json.dumps(transcript, indent=2)
9
+
10
+ output = []
11
+ for segment in transcript:
12
+ line = ""
13
+ if include_timestamps:
14
+ line += f"[{segment['start']:.2f} - {segment['end']:.2f}] "
15
+ line += segment['text']
16
+ output.append(line)
17
+
18
+ if format_type == "markdown":
19
+ return "\n\n".join(output)
20
+ elif format_type == "srt":
21
+ srt_output = []
22
+ for i, segment in enumerate(transcript, 1):
23
+ start = f"{int(segment['start']//3600):02}:{int((segment['start']%3600)//60):02}:{int(segment['start']%60):02},{int((segment['start']*1000)%1000):03}"
24
+ end = f"{int(segment['end']//3600):02}:{int((segment['end']%3600)//60):02}:{int(segment['end']%60):02},{int((segment['end']*1000)%1000):03}"
25
+ srt_output.append(f"{i}\n{start} --> {end}\n{segment['text']}\n")
26
+ return "\n".join(srt_output)
27
+
28
+ return "\n".join(output)
@@ -0,0 +1,17 @@
1
+ from faster_whisper import WhisperModel
2
+ from pathlib import Path
3
+ from typing import List, Dict
4
+
5
+ def transcribe_audio(audio_path: Path, model_size: str = "base") -> List[Dict]:
6
+ """Transcribes audio using faster-whisper on CPU."""
7
+ model = WhisperModel(model_size, device="cpu", compute_type="int8")
8
+ segments, info = model.transcribe(str(audio_path), beam_size=5)
9
+
10
+ transcript = []
11
+ for segment in segments:
12
+ transcript.append({
13
+ "start": segment.start,
14
+ "end": segment.end,
15
+ "text": segment.text.strip()
16
+ })
17
+ return transcript
@@ -0,0 +1,67 @@
1
+ Metadata-Version: 2.4
2
+ Name: ytxt
3
+ Version: 0.1.0
4
+ Summary: Local audio and YouTube transcription CLI
5
+ Author: Rayan Rane
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/rayanrane/ytxt
8
+ Project-URL: Bug Tracker, https://github.com/rayanrane/ytxt/issues
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.7
12
+ Description-Content-Type: text/markdown
13
+ Requires-Dist: yt-dlp
14
+ Requires-Dist: faster-whisper
15
+
16
+ # ytxt
17
+
18
+ `ytxt` is a local, private CLI tool for transcribing audio from YouTube, web URLs, or local files using `faster-whisper`. All processing happens securely on your machine—no external APIs or cloud services required.
19
+
20
+ ## Installation
21
+
22
+ Ensure you have `ffmpeg` installed on your system. Then, install the project:
23
+
24
+ ```bash
25
+ pip install .
26
+ ```
27
+
28
+ Alternatively, if you are running from the source:
29
+
30
+ ```bash
31
+ pip install -r requirements.txt
32
+ ```
33
+
34
+ ## Usage
35
+
36
+ Basic usage:
37
+ ```bash
38
+ ytxt <url_or_local_file_path>
39
+ ```
40
+
41
+ ### Options
42
+
43
+ - `--format [text|markdown|srt|json]`: Specify output format.
44
+ - `--model [base|small|medium|large]`: Choose the Whisper model size.
45
+ - `--timestamps`: Include start and end times in text/markdown output.
46
+ - `--output <path>`: Save the transcript to a file.
47
+ - `--no-cache`: Force a re-transcription by ignoring existing cache.
48
+
49
+ ### Examples
50
+
51
+ **Transcribe a web URL (YouTube or other):**
52
+ ```bash
53
+ ytxt https://www.example.com/audio.mp3 --format markdown --timestamps --output transcript.md
54
+ ```
55
+
56
+ **Transcribe a local audio file:**
57
+ ```bash
58
+ ytxt path/to/audio.mp3 --model medium --output transcript.txt
59
+ ```
60
+
61
+ ## Features
62
+
63
+ - **Local-Only:** Privacy-first; no data leaves your machine.
64
+ - **Universal Support:** Transcribe YouTube videos, web audio URLs, and local files.
65
+ - **Caching:** Efficiently caches results to avoid redundant work.
66
+ - **Formats:** Supports text, Markdown, SRT, and JSON.
67
+ - **Model Selection:** Flexibility to balance accuracy and performance by choosing your desired Whisper model size.
@@ -0,0 +1,14 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/ytxt/__init__.py
4
+ src/ytxt/cache.py
5
+ src/ytxt/cli.py
6
+ src/ytxt/downloader.py
7
+ src/ytxt/formatter.py
8
+ src/ytxt/transcriber.py
9
+ src/ytxt.egg-info/PKG-INFO
10
+ src/ytxt.egg-info/SOURCES.txt
11
+ src/ytxt.egg-info/dependency_links.txt
12
+ src/ytxt.egg-info/entry_points.txt
13
+ src/ytxt.egg-info/requires.txt
14
+ src/ytxt.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ ytxt = ytxt.cli:main
@@ -0,0 +1,2 @@
1
+ yt-dlp
2
+ faster-whisper
@@ -0,0 +1 @@
1
+ ytxt