extra-whisper 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.
- extra_whisper-0.1.0/LICENSE +21 -0
- extra_whisper-0.1.0/PKG-INFO +55 -0
- extra_whisper-0.1.0/README.md +39 -0
- extra_whisper-0.1.0/extra_whisper/__init__.py +0 -0
- extra_whisper-0.1.0/extra_whisper/downloader.py +33 -0
- extra_whisper-0.1.0/extra_whisper/transcribe.py +96 -0
- extra_whisper-0.1.0/pyproject.toml +17 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-present, Mohammad Abdul-Tawab.
|
|
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.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: extra-whisper
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Extended faster-whisper with yt-dlp remote media transcription
|
|
5
|
+
Author: mohammadmansour200
|
|
6
|
+
Author-email: mohammadamansour03@gmail.com
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Requires-Dist: faster-whisper (>=1.2.1)
|
|
13
|
+
Requires-Dist: validators (>=0.35.0,<0.36.0)
|
|
14
|
+
Requires-Dist: yt-dlp (>=2025.10.22)
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
<div align="center">
|
|
18
|
+
<a href="https://pypi.org/project/extra-whisper" target="_blank"><img src="https://img.shields.io/pypi/v/extra-whisper?label=PyPI%20Version&color=limegreen" /></a>
|
|
19
|
+
<a href="https://pypi.org/project/extra-whisper" target="_blank"><img src="https://img.shields.io/pypi/pyversions/extra-whisper?color=limegreen" /></a>
|
|
20
|
+
<a href="https://github.com/mohammadmansour200/extra-whisper/blob/master/LICENSE" target="_blank"><img src="https://img.shields.io/pypi/l/extra-whisper?color=limegreen" /></a>
|
|
21
|
+
<a href="https://pepy.tech/project/extra-whisper" target="_blank"><img src="https://static.pepy.tech/badge/extra-whisper" /></a>
|
|
22
|
+
<a href="https://baseet.netlify.app/ai" target="_blank"><img src="https://colab.research.google.com/assets/colab-badge.svg" /></a>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
`extra_whisper`: Extended [faster-whisper](https://github.com/SYSTRAN/faster-whisper) with remote media transcription
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
- 🎧 **Transcription** using faster-whisper
|
|
30
|
+
- 📥 **Media download** from URLs (e.g., YouTube) using `yt-dlp`
|
|
31
|
+
- ✅ Local + remote (URL) input support
|
|
32
|
+
|
|
33
|
+
## Get started
|
|
34
|
+
|
|
35
|
+
Download package:
|
|
36
|
+
> Requires Python 3.9+
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pip install extra-whisper
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Usage
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
from extra_whisper.transcribe import extra_transcribe
|
|
46
|
+
|
|
47
|
+
extra_transcribe(
|
|
48
|
+
files=[
|
|
49
|
+
"https://www.youtube.com/watch?v=123",
|
|
50
|
+
"local_audio.mp3"
|
|
51
|
+
],
|
|
52
|
+
output_dir="outputs"
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<a href="https://pypi.org/project/extra-whisper" target="_blank"><img src="https://img.shields.io/pypi/v/extra-whisper?label=PyPI%20Version&color=limegreen" /></a>
|
|
3
|
+
<a href="https://pypi.org/project/extra-whisper" target="_blank"><img src="https://img.shields.io/pypi/pyversions/extra-whisper?color=limegreen" /></a>
|
|
4
|
+
<a href="https://github.com/mohammadmansour200/extra-whisper/blob/master/LICENSE" target="_blank"><img src="https://img.shields.io/pypi/l/extra-whisper?color=limegreen" /></a>
|
|
5
|
+
<a href="https://pepy.tech/project/extra-whisper" target="_blank"><img src="https://static.pepy.tech/badge/extra-whisper" /></a>
|
|
6
|
+
<a href="https://baseet.netlify.app/ai" target="_blank"><img src="https://colab.research.google.com/assets/colab-badge.svg" /></a>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
`extra_whisper`: Extended [faster-whisper](https://github.com/SYSTRAN/faster-whisper) with remote media transcription
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- 🎧 **Transcription** using faster-whisper
|
|
14
|
+
- 📥 **Media download** from URLs (e.g., YouTube) using `yt-dlp`
|
|
15
|
+
- ✅ Local + remote (URL) input support
|
|
16
|
+
|
|
17
|
+
## Get started
|
|
18
|
+
|
|
19
|
+
Download package:
|
|
20
|
+
> Requires Python 3.9+
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install extra-whisper
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
from extra_whisper.transcribe import extra_transcribe
|
|
30
|
+
|
|
31
|
+
extra_transcribe(
|
|
32
|
+
files=[
|
|
33
|
+
"https://www.youtube.com/watch?v=123",
|
|
34
|
+
"local_audio.mp3"
|
|
35
|
+
],
|
|
36
|
+
output_dir="outputs"
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
```
|
|
File without changes
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
import yt_dlp
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Downloader:
|
|
8
|
+
def __init__(self, output_dir: str):
|
|
9
|
+
self.output_dir = output_dir
|
|
10
|
+
|
|
11
|
+
def download(self, url: str) -> str:
|
|
12
|
+
self._initialize_youtube_dl()
|
|
13
|
+
|
|
14
|
+
self.youtube_dl.download(url)
|
|
15
|
+
url_data = self.youtube_dl.extract_info(url, download=False)
|
|
16
|
+
|
|
17
|
+
filename = f"{url_data['id']}.{url_data['ext']}"
|
|
18
|
+
return filename
|
|
19
|
+
|
|
20
|
+
def _initialize_youtube_dl(self) -> None:
|
|
21
|
+
self.youtube_dl = yt_dlp.YoutubeDL(self._config())
|
|
22
|
+
|
|
23
|
+
def _config(self) -> dict[str, Any]:
|
|
24
|
+
config = {
|
|
25
|
+
'ignoreerrors': True,
|
|
26
|
+
'noplaylist': True,
|
|
27
|
+
'outtmpl': os.path.join(self.output_dir, '%(id)s.%(ext)s'),
|
|
28
|
+
'quiet': True,
|
|
29
|
+
'verbose': False,
|
|
30
|
+
'format': "bestaudio"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return config
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
import validators
|
|
6
|
+
from faster_whisper import WhisperModel, BatchedInferencePipeline, format_timestamp
|
|
7
|
+
|
|
8
|
+
from extra_whisper.downloader import Downloader
|
|
9
|
+
|
|
10
|
+
def extra_transcribe(
|
|
11
|
+
files: list[str],
|
|
12
|
+
output_dir: str,
|
|
13
|
+
model: str = "large-v3",
|
|
14
|
+
language: Optional[str] = None
|
|
15
|
+
):
|
|
16
|
+
"""
|
|
17
|
+
Transcripts the list of media files (audio/video), using faster-whisper.
|
|
18
|
+
|
|
19
|
+
This function supports both local files and remote URLs (e.g., YouTube links). It handles:
|
|
20
|
+
- Downloading remote media using yt-dlp
|
|
21
|
+
- Performing transcription
|
|
22
|
+
- Cleaning up intermediate files and keeping only the final output
|
|
23
|
+
|
|
24
|
+
Parameters:
|
|
25
|
+
files (list[str]): List of file paths or URLs pointing to audio/video files.
|
|
26
|
+
output_dir (str): Path to directory where final results will be saved.
|
|
27
|
+
model (str): Model to be used
|
|
28
|
+
language (str): Speech language
|
|
29
|
+
|
|
30
|
+
Example:
|
|
31
|
+
extra_transcribe(
|
|
32
|
+
files=["https://www.youtube.com/watch?v=123", "local_song.mp3"],
|
|
33
|
+
media_type="audio",
|
|
34
|
+
quality="medium",
|
|
35
|
+
output_dir="output"
|
|
36
|
+
)
|
|
37
|
+
"""
|
|
38
|
+
abs_output_dir = os.path.abspath(output_dir)
|
|
39
|
+
temp_output_dir = os.path.join(abs_output_dir, 'tmp')
|
|
40
|
+
|
|
41
|
+
processing_files_path = []
|
|
42
|
+
|
|
43
|
+
# --- Preparing files for processing ---
|
|
44
|
+
print("Preparing files...")
|
|
45
|
+
|
|
46
|
+
if not files:
|
|
47
|
+
raise Exception("Please provide files for processing")
|
|
48
|
+
|
|
49
|
+
downloader = Downloader(
|
|
50
|
+
output_dir=temp_output_dir,
|
|
51
|
+
)
|
|
52
|
+
for index, url in enumerate(files):
|
|
53
|
+
is_url = validators.url(url)
|
|
54
|
+
if is_url:
|
|
55
|
+
downloaded_file_name = downloader.download(url=url)
|
|
56
|
+
downloaded_file_path = os.path.join(temp_output_dir, downloaded_file_name)
|
|
57
|
+
|
|
58
|
+
processing_files_path.append(downloaded_file_path)
|
|
59
|
+
else:
|
|
60
|
+
processing_files_path.append(os.path.abspath(url))
|
|
61
|
+
|
|
62
|
+
# --- model inference ---
|
|
63
|
+
whisper_model = WhisperModel(model, device="cuda", compute_type="float16")
|
|
64
|
+
batched_model = BatchedInferencePipeline(model=whisper_model)
|
|
65
|
+
|
|
66
|
+
# Process each file with batching
|
|
67
|
+
for file_path in processing_files_path:
|
|
68
|
+
print(f"Transcribing {file_path}...")
|
|
69
|
+
|
|
70
|
+
segments, info = batched_model.transcribe(
|
|
71
|
+
file_path,
|
|
72
|
+
batch_size=8,
|
|
73
|
+
beam_size=5,
|
|
74
|
+
language=language
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
base_name = os.path.splitext(os.path.basename(file_path))[0]
|
|
78
|
+
output_file = os.path.join(abs_output_dir, f"{base_name}.srt")
|
|
79
|
+
|
|
80
|
+
with open(output_file, 'w', encoding='utf-8') as f:
|
|
81
|
+
for idx, segment in enumerate(segments, start=1):
|
|
82
|
+
f.write(f"{idx}\n")
|
|
83
|
+
|
|
84
|
+
start_time = format_timestamp(segment.start, always_include_hours=True, decimal_marker=",")
|
|
85
|
+
end_time = format_timestamp(segment.end, always_include_hours=True, decimal_marker=",")
|
|
86
|
+
f.write(f"{start_time} --> {end_time}\n")
|
|
87
|
+
|
|
88
|
+
f.write(f"{segment.text.strip()}\n")
|
|
89
|
+
f.write("\n")
|
|
90
|
+
|
|
91
|
+
print(f"Saved transcription to {output_file}")
|
|
92
|
+
|
|
93
|
+
# --- Cleanup ---
|
|
94
|
+
if os.path.exists(temp_output_dir):
|
|
95
|
+
shutil.rmtree(temp_output_dir)
|
|
96
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "extra-whisper"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Extended faster-whisper with yt-dlp remote media transcription"
|
|
5
|
+
authors = ["mohammadmansour200 <mohammadamansour03@gmail.com>"]
|
|
6
|
+
readme = "README.md"
|
|
7
|
+
packages = [{include = "extra_whisper"}]
|
|
8
|
+
|
|
9
|
+
[tool.poetry.dependencies]
|
|
10
|
+
python = ">=3.10"
|
|
11
|
+
yt-dlp = ">=2025.10.22"
|
|
12
|
+
faster-whisper = ">=1.2.1"
|
|
13
|
+
validators = ">=0.35.0,<0.36.0"
|
|
14
|
+
|
|
15
|
+
[build-system]
|
|
16
|
+
requires = ["poetry-core"]
|
|
17
|
+
build-backend = "poetry.core.masonry.api"
|