mkv-episode-matcher 0.1.13__py3-none-any.whl → 0.3.0__py3-none-any.whl
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.
Potentially problematic release.
This version of mkv-episode-matcher might be problematic. Click here for more details.
- mkv_episode_matcher/__main__.py +8 -4
- mkv_episode_matcher/episode_identification.py +208 -0
- mkv_episode_matcher/episode_matcher.py +98 -242
- mkv_episode_matcher/libraries/pgs2srt/Libraries/SubZero/SubZero.py +38 -12
- mkv_episode_matcher/libraries/pgs2srt/Libraries/SubZero/dictionaries/data.py +16644 -193
- mkv_episode_matcher/libraries/pgs2srt/Libraries/SubZero/post_processing.py +125 -80
- mkv_episode_matcher/libraries/pgs2srt/imagemaker.py +7 -5
- mkv_episode_matcher/libraries/pgs2srt/pgs2srt.py +49 -20
- mkv_episode_matcher/libraries/pgs2srt/pgsreader.py +53 -49
- mkv_episode_matcher/mkv_to_srt.py +150 -22
- mkv_episode_matcher/speech_to_text.py +90 -0
- mkv_episode_matcher/utils.py +222 -74
- mkv_episode_matcher-0.3.0.dist-info/METADATA +119 -0
- mkv_episode_matcher-0.3.0.dist-info/RECORD +25 -0
- mkv_episode_matcher/notebooks/get_subtitles_test.ipynb +0 -252
- mkv_episode_matcher/notebooks/whisper.ipynb +0 -122
- mkv_episode_matcher-0.1.13.dist-info/METADATA +0 -113
- mkv_episode_matcher-0.1.13.dist-info/RECORD +0 -25
- {mkv_episode_matcher-0.1.13.dist-info → mkv_episode_matcher-0.3.0.dist-info}/WHEEL +0 -0
- {mkv_episode_matcher-0.1.13.dist-info → mkv_episode_matcher-0.3.0.dist-info}/entry_points.txt +0 -0
- {mkv_episode_matcher-0.1.13.dist-info → mkv_episode_matcher-0.3.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: mkv-episode-matcher
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: The MKV Episode Matcher is a tool for identifying TV series episodes from MKV files and renaming the files accordingly.
|
|
5
|
+
Home-page: https://github.com/Jsakkos/mkv-episode-matcher
|
|
6
|
+
Author: Jonathan Sakkos
|
|
7
|
+
Author-email: Jsakkos <jonathansakkos@gmail.com>
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Documentation, https://github.com/Jsakkos/mkv-episode-matcher#readme
|
|
10
|
+
Project-URL: Issues, https://github.com/Jsakkos/mkv-episode-matcher/issues
|
|
11
|
+
Project-URL: Source, https://github.com/Jsakkos/mkv-episode-matcher
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Programming Language :: Python
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
16
|
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
17
|
+
Requires-Python: >=3.9
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
Requires-Dist: configparser>=7.1.0
|
|
20
|
+
Requires-Dist: ffmpeg>=1.4
|
|
21
|
+
Requires-Dist: loguru>=0.7.2
|
|
22
|
+
Requires-Dist: openai-whisper>=20240930
|
|
23
|
+
Requires-Dist: opensubtitlescom>=0.1.5
|
|
24
|
+
Requires-Dist: pytesseract>=0.3.13
|
|
25
|
+
Requires-Dist: rapidfuzz>=3.10.1
|
|
26
|
+
Requires-Dist: requests>=2.32.3
|
|
27
|
+
Requires-Dist: tmdb-client>=0.0.1
|
|
28
|
+
Requires-Dist: wave>=0.0.2
|
|
29
|
+
|
|
30
|
+
# MKV Episode Matcher
|
|
31
|
+
|
|
32
|
+
[](https://jsakkos.github.io/mkv-episode-matcher/)
|
|
33
|
+
[](https://badge.fury.io/py/mkv-episode-matcher)
|
|
34
|
+
[](https://opensource.org/licenses/MIT)
|
|
35
|
+
|
|
36
|
+
Automatically match and rename your MKV TV episodes using The Movie Database (TMDb).
|
|
37
|
+
|
|
38
|
+
## Features
|
|
39
|
+
|
|
40
|
+
- 🎯 **Automatic Episode Matching**: Uses TMDb to accurately identify episodes
|
|
41
|
+
- 📝 **Subtitle Extraction**: Extracts subtitles from MKV files
|
|
42
|
+
- 🔍 **OCR Support**: Handles image-based subtitles
|
|
43
|
+
- 🚀 **Multi-threaded**: Fast processing of multiple files
|
|
44
|
+
- ⬇️ **Subtitle Downloads**: Integration with OpenSubtitles
|
|
45
|
+
- ✨ **Bulk Processing**: Handle entire seasons at once
|
|
46
|
+
- 🧪 **Dry Run Mode**: Test changes before applying
|
|
47
|
+
|
|
48
|
+
## Quick Start
|
|
49
|
+
|
|
50
|
+
1. Install the package:
|
|
51
|
+
```bash
|
|
52
|
+
pip install mkv-episode-matcher
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
2. Run on your show directory:
|
|
56
|
+
```bash
|
|
57
|
+
mkv-match --show-dir "path/to/your/show" --season 1
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Requirements
|
|
61
|
+
|
|
62
|
+
- Python 3.8 or higher
|
|
63
|
+
- TMDb API key
|
|
64
|
+
- OpenSubtitles account (optional, for subtitle downloads)
|
|
65
|
+
|
|
66
|
+
## Documentation
|
|
67
|
+
|
|
68
|
+
Full documentation is available at [https://jsakkos.github.io/mkv-episode-matcher/](https://jsakkos.github.io/mkv-episode-matcher/)
|
|
69
|
+
|
|
70
|
+
## Basic Usage
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
from mkv_episode_matcher import process_show
|
|
74
|
+
|
|
75
|
+
# Process all seasons
|
|
76
|
+
process_show()
|
|
77
|
+
|
|
78
|
+
# Process specific season
|
|
79
|
+
process_show(season=1)
|
|
80
|
+
|
|
81
|
+
# Test run without making changes
|
|
82
|
+
process_show(season=1, dry_run=True)
|
|
83
|
+
|
|
84
|
+
# Process and download subtitles
|
|
85
|
+
process_show(get_subs=True)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Directory Structure
|
|
89
|
+
|
|
90
|
+
MKV Episode Matcher expects your TV shows to be organized as follows:
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
Show Name/
|
|
94
|
+
├── Season 1/
|
|
95
|
+
│ ├── episode1.mkv
|
|
96
|
+
│ ├── episode2.mkv
|
|
97
|
+
├── Season 2/
|
|
98
|
+
│ ├── episode1.mkv
|
|
99
|
+
│ └── episode2.mkv
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Contributing
|
|
103
|
+
|
|
104
|
+
1. Fork the repository
|
|
105
|
+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
106
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
107
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
108
|
+
5. Open a Pull Request
|
|
109
|
+
|
|
110
|
+
## License
|
|
111
|
+
|
|
112
|
+
Distributed under the MIT License. See `LICENSE` for more information.
|
|
113
|
+
|
|
114
|
+
## Acknowledgments
|
|
115
|
+
|
|
116
|
+
- [TMDb](https://www.themoviedb.org/) for their excellent API
|
|
117
|
+
- [OpenSubtitles](https://www.opensubtitles.com/) for subtitle integration
|
|
118
|
+
- All contributors who have helped improve this project
|
|
119
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
mkv_episode_matcher/.gitattributes,sha256=Gh2-F2vCM7SZ01pX23UT8pQcmauXWfF3gwyRSb6ZAFs,66
|
|
2
|
+
mkv_episode_matcher/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
3
|
+
mkv_episode_matcher/__main__.py,sha256=3ZcCUxeI7rUA-4oiCD2WXBiOFJAqLsVVWfZKN446FwQ,6792
|
|
4
|
+
mkv_episode_matcher/config.py,sha256=zDDKBcsDt5fME9BRqiTi7yWKeast1pZh36BNYMvIBYM,2419
|
|
5
|
+
mkv_episode_matcher/episode_identification.py,sha256=nXv9giH7xHysxnfczpsDefb7DmRXzuz8pgmfBemqwBs,8381
|
|
6
|
+
mkv_episode_matcher/episode_matcher.py,sha256=tffbLz35Mpah0yQ6ASz1dg8tz27s8UrdSZunZ-GQLtY,4560
|
|
7
|
+
mkv_episode_matcher/mkv_to_srt.py,sha256=4yxBHRVhgVby0UtQ2aTXGuoQpid8pkgjMIaHU6GCdzc,10857
|
|
8
|
+
mkv_episode_matcher/speech_to_text.py,sha256=-bnGvmtPCKyHFPEaXwIcEYTf_P13rNpAJA-2UFeRFrs,2806
|
|
9
|
+
mkv_episode_matcher/tmdb_client.py,sha256=LbMCgjmp7sCbrQo_CDlpcnryKPz5S7inE24YY9Pyjk4,4172
|
|
10
|
+
mkv_episode_matcher/utils.py,sha256=hQmJNdTogGnN3qbN6sN1JUPvIe6RHU6ml3B41yZB8DQ,14147
|
|
11
|
+
mkv_episode_matcher/libraries/pgs2srt/.gitignore,sha256=mt3uxWYZaFurMw_yGE258gWhtGKPVR7e3Ll4ALJpyj4,23
|
|
12
|
+
mkv_episode_matcher/libraries/pgs2srt/README.md,sha256=olb25G17tj0kxPgp_LcH5I2QWXjgP1m8JFyjYRGz4UU,1374
|
|
13
|
+
mkv_episode_matcher/libraries/pgs2srt/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
+
mkv_episode_matcher/libraries/pgs2srt/imagemaker.py,sha256=mOlUt8eJ4LOqMYerOuWmQPPWcB-Umup2lBJlqzy_pPg,2736
|
|
15
|
+
mkv_episode_matcher/libraries/pgs2srt/pgs2srt.py,sha256=UdCCUUWxKXCxBebiNBsrM95R6-zmJhSUAHcEPxUmbNU,4416
|
|
16
|
+
mkv_episode_matcher/libraries/pgs2srt/pgsreader.py,sha256=h5vZSLPVHir-epuNa-L5MpJYpyyUk0h_13DtmrNG9Xc,7001
|
|
17
|
+
mkv_episode_matcher/libraries/pgs2srt/requirements.txt,sha256=sg87dqWw_qpbwciw-Mc5mRJnV9LaCni2cybnT5ANqnA,59
|
|
18
|
+
mkv_episode_matcher/libraries/pgs2srt/Libraries/SubZero/SubZero.py,sha256=geT1LXdVd8yED9zoJ9K1XfP2JzGcM7u1SslHYrJI09o,10061
|
|
19
|
+
mkv_episode_matcher/libraries/pgs2srt/Libraries/SubZero/post_processing.py,sha256=GKtVy_Lxv-z27mkRG8pJF2znKWXwZTot7jL6kN-zIxM,10503
|
|
20
|
+
mkv_episode_matcher/libraries/pgs2srt/Libraries/SubZero/dictionaries/data.py,sha256=AlJHUYXl85J95OzGRik-AHVfzDd7Q8BJCvD4Nr8kRIk,938598
|
|
21
|
+
mkv_episode_matcher-0.3.0.dist-info/METADATA,sha256=XAnfyhD0sBKRJqR_LwUdLD30wNNijVRj44girWFrl1w,3781
|
|
22
|
+
mkv_episode_matcher-0.3.0.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
23
|
+
mkv_episode_matcher-0.3.0.dist-info/entry_points.txt,sha256=IglJ43SuCZq2eQ3shMFILCkmQASJHnDCI3ogohW2Hn4,64
|
|
24
|
+
mkv_episode_matcher-0.3.0.dist-info/top_level.txt,sha256=XRLbd93HUaedeWLtkyTvQjFcE5QcBRYa3V-CfHrq-OI,20
|
|
25
|
+
mkv_episode_matcher-0.3.0.dist-info/RECORD,,
|
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"cells": [
|
|
3
|
-
{
|
|
4
|
-
"cell_type": "markdown",
|
|
5
|
-
"metadata": {},
|
|
6
|
-
"source": [
|
|
7
|
-
"# Load imports and create config directory"
|
|
8
|
-
]
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
"cell_type": "code",
|
|
12
|
-
"execution_count": null,
|
|
13
|
-
"metadata": {},
|
|
14
|
-
"outputs": [],
|
|
15
|
-
"source": [
|
|
16
|
-
"# __main__.py\n",
|
|
17
|
-
"import argparse\n",
|
|
18
|
-
"import os\n",
|
|
19
|
-
"\n",
|
|
20
|
-
"from loguru import logger\n",
|
|
21
|
-
"\n",
|
|
22
|
-
"from mkv_episode_matcher.config import get_config, set_config\n",
|
|
23
|
-
"from mkv_episode_matcher.utils import check_filename, cleanup_ocr_files, get_subtitles\n",
|
|
24
|
-
"from mkv_episode_matcher.tmdb_client import fetch_show_id,fetch_season_details\n",
|
|
25
|
-
"import os\n",
|
|
26
|
-
"import re\n",
|
|
27
|
-
"import shutil\n",
|
|
28
|
-
"from typing import Set\n",
|
|
29
|
-
"\n",
|
|
30
|
-
"import requests\n",
|
|
31
|
-
"from loguru import logger\n",
|
|
32
|
-
"from opensubtitlescom import OpenSubtitles\n",
|
|
33
|
-
"# Log the start of the application\n",
|
|
34
|
-
"logger.info(\"Starting the application\")\n",
|
|
35
|
-
"\n",
|
|
36
|
-
"\n",
|
|
37
|
-
"\n",
|
|
38
|
-
"# Check if the configuration directory exists, if not create it\n",
|
|
39
|
-
"if not os.path.exists(os.path.join(os.path.expanduser(\"~\"), \".mkv-episode-matcher\")):\n",
|
|
40
|
-
" os.makedirs(os.path.join(os.path.expanduser(\"~\"), \".mkv-episode-matcher\"))\n",
|
|
41
|
-
"\n",
|
|
42
|
-
"# Define the paths for the configuration file and cache directory\n",
|
|
43
|
-
"CONFIG_FILE = os.path.join(\n",
|
|
44
|
-
" os.path.expanduser(\"~\"), \".mkv-episode-matcher\", \"config.ini\"\n",
|
|
45
|
-
")\n",
|
|
46
|
-
"CACHE_DIR = os.path.join(os.path.expanduser(\"~\"), \".mkv-episode-matcher\", \"cache\")"
|
|
47
|
-
]
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
"cell_type": "markdown",
|
|
51
|
-
"metadata": {},
|
|
52
|
-
"source": [
|
|
53
|
-
"# Load configuration settings from config.ini"
|
|
54
|
-
]
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
"cell_type": "code",
|
|
58
|
-
"execution_count": null,
|
|
59
|
-
"metadata": {},
|
|
60
|
-
"outputs": [],
|
|
61
|
-
"source": [
|
|
62
|
-
"config = get_config(CONFIG_FILE)\n",
|
|
63
|
-
"show_dir = config.get(\"show_dir\")\n",
|
|
64
|
-
"show_name = os.path.basename(show_dir)\n",
|
|
65
|
-
"series_name = os.path.basename(show_dir)\n",
|
|
66
|
-
"tmdb_api_key = config.get(\"tmdb_api_key\")\n",
|
|
67
|
-
"open_subtitles_api_key = config.get(\"open_subtitles_api_key\")\n",
|
|
68
|
-
"open_subtitles_user_agent = config.get(\"open_subtitles_user_agent\")\n",
|
|
69
|
-
"open_subtitles_username = config.get(\"open_subtitles_username\")\n",
|
|
70
|
-
"open_subtitles_password = config.get(\"open_subtitles_password\")"
|
|
71
|
-
]
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
"cell_type": "markdown",
|
|
75
|
-
"metadata": {},
|
|
76
|
-
"source": [
|
|
77
|
-
"# Make sure all required info exists in config.ini"
|
|
78
|
-
]
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
"cell_type": "code",
|
|
82
|
-
"execution_count": null,
|
|
83
|
-
"metadata": {},
|
|
84
|
-
"outputs": [],
|
|
85
|
-
"source": [
|
|
86
|
-
"for x in [\n",
|
|
87
|
-
" show_dir,\n",
|
|
88
|
-
" tmdb_api_key,\n",
|
|
89
|
-
" open_subtitles_api_key,\n",
|
|
90
|
-
" open_subtitles_user_agent,\n",
|
|
91
|
-
" open_subtitles_username,\n",
|
|
92
|
-
" open_subtitles_password,\n",
|
|
93
|
-
" ]:\n",
|
|
94
|
-
" try:\n",
|
|
95
|
-
" print(x)\n",
|
|
96
|
-
" except:\n",
|
|
97
|
-
" print('failed')"
|
|
98
|
-
]
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
"cell_type": "code",
|
|
102
|
-
"execution_count": null,
|
|
103
|
-
"metadata": {},
|
|
104
|
-
"outputs": [],
|
|
105
|
-
"source": [
|
|
106
|
-
"if not all(\n",
|
|
107
|
-
" [\n",
|
|
108
|
-
" show_dir,\n",
|
|
109
|
-
" tmdb_api_key,\n",
|
|
110
|
-
" open_subtitles_api_key,\n",
|
|
111
|
-
" open_subtitles_user_agent,\n",
|
|
112
|
-
" open_subtitles_username,\n",
|
|
113
|
-
" open_subtitles_password,\n",
|
|
114
|
-
" ]\n",
|
|
115
|
-
"):\n",
|
|
116
|
-
" logger.error(\"Missing configuration settings. Please run the setup script.\")"
|
|
117
|
-
]
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
"cell_type": "markdown",
|
|
121
|
-
"metadata": {},
|
|
122
|
-
"source": [
|
|
123
|
-
"# Make sure show can be found on TMDb\n",
|
|
124
|
-
"The show id is used to search on opensubtitles"
|
|
125
|
-
]
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
"cell_type": "code",
|
|
129
|
-
"execution_count": null,
|
|
130
|
-
"metadata": {},
|
|
131
|
-
"outputs": [],
|
|
132
|
-
"source": [
|
|
133
|
-
"show_id = fetch_show_id(show_name)\n",
|
|
134
|
-
"if show_id is None:\n",
|
|
135
|
-
" logger.error(f\"Could not find show '{os.path.basename(show_name)}' on TMDb.\")\n",
|
|
136
|
-
"else:\n",
|
|
137
|
-
" print(show_id)"
|
|
138
|
-
]
|
|
139
|
-
},
|
|
140
|
-
{
|
|
141
|
-
"cell_type": "markdown",
|
|
142
|
-
"metadata": {},
|
|
143
|
-
"source": [
|
|
144
|
-
"# Try getting the first season automatically"
|
|
145
|
-
]
|
|
146
|
-
},
|
|
147
|
-
{
|
|
148
|
-
"cell_type": "code",
|
|
149
|
-
"execution_count": null,
|
|
150
|
-
"metadata": {},
|
|
151
|
-
"outputs": [],
|
|
152
|
-
"source": [
|
|
153
|
-
"get_subtitles(show_id, seasons=set([1]))"
|
|
154
|
-
]
|
|
155
|
-
},
|
|
156
|
-
{
|
|
157
|
-
"cell_type": "markdown",
|
|
158
|
-
"metadata": {},
|
|
159
|
-
"source": [
|
|
160
|
-
"# Check if there's an issue in the get_subtitles function"
|
|
161
|
-
]
|
|
162
|
-
},
|
|
163
|
-
{
|
|
164
|
-
"cell_type": "code",
|
|
165
|
-
"execution_count": null,
|
|
166
|
-
"metadata": {},
|
|
167
|
-
"outputs": [],
|
|
168
|
-
"source": [
|
|
169
|
-
"try:\n",
|
|
170
|
-
" # Initialize the OpenSubtitles client\n",
|
|
171
|
-
" subtitles = OpenSubtitles(open_subtitles_user_agent, open_subtitles_api_key)\n",
|
|
172
|
-
"\n",
|
|
173
|
-
" # Log in (retrieve auth token)\n",
|
|
174
|
-
" subtitles.login(open_subtitles_username, open_subtitles_password)\n",
|
|
175
|
-
"except Exception as e:\n",
|
|
176
|
-
" logger.error(f\"Failed to log in to OpenSubtitles: {e}\")\n",
|
|
177
|
-
"\n",
|
|
178
|
-
"for season in [1]:\n",
|
|
179
|
-
" episodes = fetch_season_details(show_id, season)\n",
|
|
180
|
-
" logger.info(f\"Found {episodes} episodes in Season {season}\")\n",
|
|
181
|
-
"\n",
|
|
182
|
-
" for episode in range(1, episodes + 1):\n",
|
|
183
|
-
" logger.info(f\"Processing Season {season}, Episode {episode}...\")\n",
|
|
184
|
-
" series_cache_dir =os.path.join(\n",
|
|
185
|
-
" CACHE_DIR,\n",
|
|
186
|
-
" \"data\",\n",
|
|
187
|
-
" series_name)\n",
|
|
188
|
-
" os.makedirs(series_cache_dir,exist_ok=True)\n",
|
|
189
|
-
" srt_filepath = os.path.join(\n",
|
|
190
|
-
" series_cache_dir,\n",
|
|
191
|
-
" f\"{series_name} - S{season:02d}E{episode:02d}.srt\",\n",
|
|
192
|
-
" )\n",
|
|
193
|
-
" if not os.path.exists(srt_filepath):\n",
|
|
194
|
-
" # get the episode info from TMDB\n",
|
|
195
|
-
" url = f\"https://api.themoviedb.org/3/tv/{show_id}/season/{season}/episode/{episode}?api_key={tmdb_api_key}\"\n",
|
|
196
|
-
" response = requests.get(url)\n",
|
|
197
|
-
" response.raise_for_status()\n",
|
|
198
|
-
" episode_data = response.json()\n",
|
|
199
|
-
" episode_name = episode_data[\"name\"]\n",
|
|
200
|
-
" episode_id = episode_data[\"id\"]\n",
|
|
201
|
-
" # search for the subtitle\n",
|
|
202
|
-
" response = subtitles.search(tmdb_id=episode_id, languages=\"en\")\n",
|
|
203
|
-
" if len(response.data) == 0:\n",
|
|
204
|
-
" logger.warning(\n",
|
|
205
|
-
" f\"No subtitles found for {series_name} - S{season:02d}E{episode:02d}\"\n",
|
|
206
|
-
" )\n",
|
|
207
|
-
"\n",
|
|
208
|
-
" for subtitle in response.data:\n",
|
|
209
|
-
" subtitle_dict = subtitle.to_dict()\n",
|
|
210
|
-
" # Remove special characters and convert to uppercase\n",
|
|
211
|
-
" filename_clean = re.sub(\n",
|
|
212
|
-
" r\"\\W+\", \" \", subtitle_dict[\"file_name\"]\n",
|
|
213
|
-
" ).upper()\n",
|
|
214
|
-
" if f\"E{episode:02d}\" in filename_clean:\n",
|
|
215
|
-
" logger.info(f\"Original filename: {subtitle_dict['file_name']}\")\n",
|
|
216
|
-
" srt_file = subtitles.download_and_save(subtitle)\n",
|
|
217
|
-
" series_name = series_name.replace(\":\", \" -\")\n",
|
|
218
|
-
" shutil.move(os.path.join(os.getcwd(),srt_file), srt_filepath)\n",
|
|
219
|
-
" logger.info(f\"Subtitle saved to {srt_filepath}\")\n",
|
|
220
|
-
" break\n",
|
|
221
|
-
" else:\n",
|
|
222
|
-
" continue\n",
|
|
223
|
-
" else:\n",
|
|
224
|
-
" logger.info(\n",
|
|
225
|
-
" f\"Subtitle already exists for {series_name} - S{season:02d}E{episode:02d}\"\n",
|
|
226
|
-
" )\n",
|
|
227
|
-
" continue"
|
|
228
|
-
]
|
|
229
|
-
}
|
|
230
|
-
],
|
|
231
|
-
"metadata": {
|
|
232
|
-
"kernelspec": {
|
|
233
|
-
"display_name": "mkv",
|
|
234
|
-
"language": "python",
|
|
235
|
-
"name": "python3"
|
|
236
|
-
},
|
|
237
|
-
"language_info": {
|
|
238
|
-
"codemirror_mode": {
|
|
239
|
-
"name": "ipython",
|
|
240
|
-
"version": 3
|
|
241
|
-
},
|
|
242
|
-
"file_extension": ".py",
|
|
243
|
-
"mimetype": "text/x-python",
|
|
244
|
-
"name": "python",
|
|
245
|
-
"nbconvert_exporter": "python",
|
|
246
|
-
"pygments_lexer": "ipython3",
|
|
247
|
-
"version": "3.12.1"
|
|
248
|
-
}
|
|
249
|
-
},
|
|
250
|
-
"nbformat": 4,
|
|
251
|
-
"nbformat_minor": 2
|
|
252
|
-
}
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"cells": [
|
|
3
|
-
{
|
|
4
|
-
"cell_type": "code",
|
|
5
|
-
"execution_count": 1,
|
|
6
|
-
"metadata": {},
|
|
7
|
-
"outputs": [
|
|
8
|
-
{
|
|
9
|
-
"ename": "OSError",
|
|
10
|
-
"evalue": "[WinError 126] The specified module could not be found. Error loading \"c:\\Users\\Jonathan\\anaconda3\\envs\\whisper\\Lib\\site-packages\\torch\\lib\\fbgemm.dll\" or one of its dependencies.",
|
|
11
|
-
"output_type": "error",
|
|
12
|
-
"traceback": [
|
|
13
|
-
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
|
|
14
|
-
"\u001b[1;31mOSError\u001b[0m Traceback (most recent call last)",
|
|
15
|
-
"Cell \u001b[1;32mIn[1], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mwhisper\u001b[39;00m\n\u001b[0;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mos\u001b[39;00m\n",
|
|
16
|
-
"File \u001b[1;32mc:\\Users\\Jonathan\\anaconda3\\envs\\whisper\\Lib\\site-packages\\whisper\\__init__.py:8\u001b[0m\n\u001b[0;32m 5\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mwarnings\u001b[39;00m\n\u001b[0;32m 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtyping\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m List, Optional, Union\n\u001b[1;32m----> 8\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mtorch\u001b[39;00m\n\u001b[0;32m 9\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtqdm\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m tqdm\n\u001b[0;32m 11\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01maudio\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m load_audio, log_mel_spectrogram, pad_or_trim\n",
|
|
17
|
-
"File \u001b[1;32mc:\\Users\\Jonathan\\anaconda3\\envs\\whisper\\Lib\\site-packages\\torch\\__init__.py:148\u001b[0m\n\u001b[0;32m 146\u001b[0m err \u001b[38;5;241m=\u001b[39m ctypes\u001b[38;5;241m.\u001b[39mWinError(ctypes\u001b[38;5;241m.\u001b[39mget_last_error())\n\u001b[0;32m 147\u001b[0m err\u001b[38;5;241m.\u001b[39mstrerror \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m Error loading \u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mdll\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m or one of its dependencies.\u001b[39m\u001b[38;5;124m'\u001b[39m\n\u001b[1;32m--> 148\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m err\n\u001b[0;32m 150\u001b[0m kernel32\u001b[38;5;241m.\u001b[39mSetErrorMode(prev_error_mode)\n\u001b[0;32m 153\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_preload_cuda_deps\u001b[39m(lib_folder, lib_name):\n",
|
|
18
|
-
"\u001b[1;31mOSError\u001b[0m: [WinError 126] The specified module could not be found. Error loading \"c:\\Users\\Jonathan\\anaconda3\\envs\\whisper\\Lib\\site-packages\\torch\\lib\\fbgemm.dll\" or one of its dependencies."
|
|
19
|
-
]
|
|
20
|
-
}
|
|
21
|
-
],
|
|
22
|
-
"source": [
|
|
23
|
-
"import whisper\n",
|
|
24
|
-
"import os\n",
|
|
25
|
-
"\n"
|
|
26
|
-
]
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
"cell_type": "code",
|
|
30
|
-
"execution_count": null,
|
|
31
|
-
"metadata": {},
|
|
32
|
-
"outputs": [
|
|
33
|
-
{
|
|
34
|
-
"ename": "",
|
|
35
|
-
"evalue": "",
|
|
36
|
-
"output_type": "error",
|
|
37
|
-
"traceback": [
|
|
38
|
-
"\u001b[1;31mRunning cells with 'MKV-GPU (Python 3.8.10)' requires the ipykernel package.\n",
|
|
39
|
-
"\u001b[1;31mRun the following command to install 'ipykernel' into the Python environment. \n",
|
|
40
|
-
"\u001b[1;31mCommand: 'conda install -n MKV-GPU ipykernel --update-deps --force-reinstall'"
|
|
41
|
-
]
|
|
42
|
-
}
|
|
43
|
-
],
|
|
44
|
-
"source": [
|
|
45
|
-
"import torch\n",
|
|
46
|
-
"\n",
|
|
47
|
-
"if torch.cuda.is_available():\n",
|
|
48
|
-
" print(f\"CUDA is available. Using GPU: {torch.cuda.get_device_name(0)}\")\n",
|
|
49
|
-
"else:\n",
|
|
50
|
-
" print(\"CUDA is not available. Using CPU.\")\n",
|
|
51
|
-
"\n",
|
|
52
|
-
"# It will print out the GPU that you are using."
|
|
53
|
-
]
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
"cell_type": "code",
|
|
57
|
-
"execution_count": null,
|
|
58
|
-
"metadata": {},
|
|
59
|
-
"outputs": [
|
|
60
|
-
{
|
|
61
|
-
"ename": "",
|
|
62
|
-
"evalue": "",
|
|
63
|
-
"output_type": "error",
|
|
64
|
-
"traceback": [
|
|
65
|
-
"\u001b[1;31mRunning cells with 'MKV-GPU (Python 3.8.10)' requires the ipykernel package.\n",
|
|
66
|
-
"\u001b[1;31mRun the following command to install 'ipykernel' into the Python environment. \n",
|
|
67
|
-
"\u001b[1;31mCommand: 'conda install -n MKV-GPU ipykernel --update-deps --force-reinstall'"
|
|
68
|
-
]
|
|
69
|
-
}
|
|
70
|
-
],
|
|
71
|
-
"source": [
|
|
72
|
-
"model = whisper.load_model(\"base\") # Replace \"base\" with the desired model size\n",
|
|
73
|
-
"result = model.transcribe(r\"C:\\Users\\Jonathan\\output_audio.wav\")\n",
|
|
74
|
-
"\n",
|
|
75
|
-
"# Print or save the transcription\n",
|
|
76
|
-
"print(result[\"text\"])"
|
|
77
|
-
]
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
"cell_type": "code",
|
|
81
|
-
"execution_count": null,
|
|
82
|
-
"metadata": {},
|
|
83
|
-
"outputs": [
|
|
84
|
-
{
|
|
85
|
-
"ename": "",
|
|
86
|
-
"evalue": "",
|
|
87
|
-
"output_type": "error",
|
|
88
|
-
"traceback": [
|
|
89
|
-
"\u001b[1;31mRunning cells with 'MKV-GPU (Python 3.8.10)' requires the ipykernel package.\n",
|
|
90
|
-
"\u001b[1;31mRun the following command to install 'ipykernel' into the Python environment. \n",
|
|
91
|
-
"\u001b[1;31mCommand: 'conda install -n MKV-GPU ipykernel --update-deps --force-reinstall'"
|
|
92
|
-
]
|
|
93
|
-
}
|
|
94
|
-
],
|
|
95
|
-
"source": [
|
|
96
|
-
"# ffmpeg -i \"E:\\Video\\Seinfeld\\Season 5\\Seinfeld - Season 5 (Disc 1)-A1_t02.mkv\" -t 300 -map 0:a:0 -acodec pcm_s16le -ac 1 output_audio.wav\n",
|
|
97
|
-
"# works for make a .wav file of the first 5 mins"
|
|
98
|
-
]
|
|
99
|
-
}
|
|
100
|
-
],
|
|
101
|
-
"metadata": {
|
|
102
|
-
"kernelspec": {
|
|
103
|
-
"display_name": "mkv",
|
|
104
|
-
"language": "python",
|
|
105
|
-
"name": "python3"
|
|
106
|
-
},
|
|
107
|
-
"language_info": {
|
|
108
|
-
"codemirror_mode": {
|
|
109
|
-
"name": "ipython",
|
|
110
|
-
"version": 3
|
|
111
|
-
},
|
|
112
|
-
"file_extension": ".py",
|
|
113
|
-
"mimetype": "text/x-python",
|
|
114
|
-
"name": "python",
|
|
115
|
-
"nbconvert_exporter": "python",
|
|
116
|
-
"pygments_lexer": "ipython3",
|
|
117
|
-
"version": "3.11.9"
|
|
118
|
-
}
|
|
119
|
-
},
|
|
120
|
-
"nbformat": 4,
|
|
121
|
-
"nbformat_minor": 2
|
|
122
|
-
}
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: mkv-episode-matcher
|
|
3
|
-
Version: 0.1.13
|
|
4
|
-
Summary: The MKV Episode Matcher is a tool for identifying TV series episodes from MKV files and renaming the files accordingly.
|
|
5
|
-
Home-page: https://github.com/Jsakkos/mkv-episode-matcher
|
|
6
|
-
Author: Jonathan Sakkos
|
|
7
|
-
Author-email: Jsakkos <jonathansakkos@protonmail.com>
|
|
8
|
-
License: MIT
|
|
9
|
-
Project-URL: Documentation, https://github.com/Jsakkos/mkv-episode-matcher#readme
|
|
10
|
-
Project-URL: Issues, https://github.com/Jsakkos/mkv-episode-matcher/issues
|
|
11
|
-
Project-URL: Source, https://github.com/Jsakkos/mkv-episode-matcher
|
|
12
|
-
Classifier: Development Status :: 4 - Beta
|
|
13
|
-
Classifier: Programming Language :: Python
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
-
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
16
|
-
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
17
|
-
Requires-Python: >=3.12
|
|
18
|
-
Description-Content-Type: text/x-rst
|
|
19
|
-
Requires-Dist: configparser>=7.1.0
|
|
20
|
-
Requires-Dist: ffmpeg>=1.4
|
|
21
|
-
Requires-Dist: loguru>=0.7.2
|
|
22
|
-
Requires-Dist: numpy>=2.1.3
|
|
23
|
-
Requires-Dist: opensubtitlescom>=0.1.5
|
|
24
|
-
Requires-Dist: pytesseract>=0.3.13
|
|
25
|
-
Requires-Dist: requests>=2.32.3
|
|
26
|
-
Requires-Dist: tmdb-client>=0.0.1
|
|
27
|
-
|
|
28
|
-
===================
|
|
29
|
-
MKV Episode Matcher
|
|
30
|
-
===================
|
|
31
|
-
|
|
32
|
-
|docs| |pypi|
|
|
33
|
-
|
|
34
|
-
The MKV Episode Matcher is a tool for identifying TV series episodes from MKV files and renaming the files accordingly.
|
|
35
|
-
|
|
36
|
-
Quick start
|
|
37
|
-
===========
|
|
38
|
-
|
|
39
|
-
To use the MKV Episode Matcher, follow these steps:
|
|
40
|
-
|
|
41
|
-
1. Install ``pip install mkv-episode-matcher``
|
|
42
|
-
2. Obtain an API key from TMDb (https://developers.themoviedb.org/authentication/getting-a-apikey).
|
|
43
|
-
3. (Optional) - Obtain an API key from Opensubtitles.com by creating an API consumer (https://www.opensubtitles.com/en/consumers)
|
|
44
|
-
4. Alternatively, add the .srt files to the cache directory. On Windows: ``C:\Users\YOUR_USER_NAME\.mkv-episode-matcher\cache\data\SHOW_NAME``. The files need to be named with the season and episode, e.g. ``Show Name - S01E01.srt``.
|
|
45
|
-
5. Provide a filepath to your show directory. This is the main directory that contains all of the episodes for a specific show.
|
|
46
|
-
|
|
47
|
-
The directory and subfolders must be arranged in the following structure:
|
|
48
|
-
|
|
49
|
-
- Show name
|
|
50
|
-
- Season 1
|
|
51
|
-
- Season 2
|
|
52
|
-
- ...
|
|
53
|
-
- Season n
|
|
54
|
-
|
|
55
|
-
6. Call ``mkv-match`` with the TMDB_API_KEY and SHOW_DIR as arguments or in environment variables from your command line:
|
|
56
|
-
|
|
57
|
-
.. code-block:: bash
|
|
58
|
-
|
|
59
|
-
python mkv-match --tmdb-api-key your-api-key --show-dir /path/to/show
|
|
60
|
-
|
|
61
|
-
Once TMDB_API_KEY is set, there's no need to enter it again, as it gets stored in the config.ini file.
|
|
62
|
-
|
|
63
|
-
To get subtitles from opensubtitles.com, ensure that the appropriate credentials have been set, either via the CLI or in config.ini (On Windows: ``C:\Users\YOUR_USER_NAME\.mkv-episode-matcher\config.ini``).
|
|
64
|
-
Then add the ``--get-subs True`` flag to the CLI call
|
|
65
|
-
|
|
66
|
-
.. code-block:: bash
|
|
67
|
-
|
|
68
|
-
python mkv-match --show-dir /path/to/show --get-subs True
|
|
69
|
-
|
|
70
|
-
How it works
|
|
71
|
-
============
|
|
72
|
-
|
|
73
|
-
MKV Episode Matcher extracts the subtitle text from each MKV file, then cross-references the text against .srt subtitle files that are either user-provided or downloaded from Opensubtitles.com.
|
|
74
|
-
|
|
75
|
-
License
|
|
76
|
-
=======
|
|
77
|
-
|
|
78
|
-
MIT License
|
|
79
|
-
|
|
80
|
-
Copyright (c) 2024 Jonathan Sakkos
|
|
81
|
-
|
|
82
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
83
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
84
|
-
in the Software without restriction, including without limitation the rights
|
|
85
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
86
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
87
|
-
furnished to do so, subject to the following conditions:
|
|
88
|
-
|
|
89
|
-
The above copyright notice and this permission notice shall be included in all
|
|
90
|
-
copies or substantial portions of the Software.
|
|
91
|
-
|
|
92
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
93
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
94
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
95
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
96
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
97
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
98
|
-
SOFTWARE.
|
|
99
|
-
|
|
100
|
-
Acknowledgments
|
|
101
|
-
===============
|
|
102
|
-
|
|
103
|
-
This product uses the TMDB API but is not endorsed or certified by TMDB.
|
|
104
|
-
|
|
105
|
-
.. image:: https://www.themoviedb.org/assets/2/v4/logos/v2/blue_long_2-9665a76b1ae401a510ec1e0ca40ddcb3b0cfe45f1d51b77a308fea0845885648.svg
|
|
106
|
-
:alt: The Movie Database
|
|
107
|
-
:target: https://www.themoviedb.org/
|
|
108
|
-
|
|
109
|
-
.. |docs| image:: https://readthedocs.org/projects/mkv-episode-matcher/badge/?version=latest
|
|
110
|
-
:target: https://mkv-episode-matcher.readthedocs.io/en/latest/?badge=latest
|
|
111
|
-
:alt: Documentation Status
|
|
112
|
-
.. |pypi| image:: https://badge.fury.io/py/mkv-episode-matcher.svg
|
|
113
|
-
:target: https://badge.fury.io/py/mkv-episode-matcher
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
mkv_episode_matcher/.gitattributes,sha256=Gh2-F2vCM7SZ01pX23UT8pQcmauXWfF3gwyRSb6ZAFs,66
|
|
2
|
-
mkv_episode_matcher/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
3
|
-
mkv_episode_matcher/__main__.py,sha256=lDMYl6SOH9fV_X7fPvMeIXEzT-jAaDg90FbqRUZyUb4,6772
|
|
4
|
-
mkv_episode_matcher/config.py,sha256=zDDKBcsDt5fME9BRqiTi7yWKeast1pZh36BNYMvIBYM,2419
|
|
5
|
-
mkv_episode_matcher/episode_matcher.py,sha256=l56EyLyeJpO4wRavY-VQtVZm7XBwUOCuhyfcORkoKnY,9559
|
|
6
|
-
mkv_episode_matcher/mkv_to_srt.py,sha256=m34nhgiBSBGpymePUt2C-EmGhcjoXnv3S0SLod-DkFo,6092
|
|
7
|
-
mkv_episode_matcher/tmdb_client.py,sha256=LbMCgjmp7sCbrQo_CDlpcnryKPz5S7inE24YY9Pyjk4,4172
|
|
8
|
-
mkv_episode_matcher/utils.py,sha256=nexZbTtP2MR5oWqT9I2lDZg-2cRlw-2mP6kbYmdTNA8,9650
|
|
9
|
-
mkv_episode_matcher/libraries/pgs2srt/.gitignore,sha256=mt3uxWYZaFurMw_yGE258gWhtGKPVR7e3Ll4ALJpyj4,23
|
|
10
|
-
mkv_episode_matcher/libraries/pgs2srt/README.md,sha256=olb25G17tj0kxPgp_LcH5I2QWXjgP1m8JFyjYRGz4UU,1374
|
|
11
|
-
mkv_episode_matcher/libraries/pgs2srt/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
-
mkv_episode_matcher/libraries/pgs2srt/imagemaker.py,sha256=w5YMWU70TPf7bjbVUcXBIagBMR4mz0uXqHdjLO1GQlY,2733
|
|
13
|
-
mkv_episode_matcher/libraries/pgs2srt/pgs2srt.py,sha256=miKviiKRlN7h2tkbV-3twyjUzVnXWbWZPYEaLy-wKdo,4162
|
|
14
|
-
mkv_episode_matcher/libraries/pgs2srt/pgsreader.py,sha256=bFlaPYzUs9H9qZ5JEE53YmP08yma2c59aLQBNzAgz_c,6948
|
|
15
|
-
mkv_episode_matcher/libraries/pgs2srt/requirements.txt,sha256=sg87dqWw_qpbwciw-Mc5mRJnV9LaCni2cybnT5ANqnA,59
|
|
16
|
-
mkv_episode_matcher/libraries/pgs2srt/Libraries/SubZero/SubZero.py,sha256=1ZXUENOTxK4u9dBNTwnjrd-GRE-WHf-yi2LBainSwRw,9869
|
|
17
|
-
mkv_episode_matcher/libraries/pgs2srt/Libraries/SubZero/post_processing.py,sha256=KZgMDCLPSfnDbbC9myvg1znkjapO0iSp7z_mIxf2e5k,9742
|
|
18
|
-
mkv_episode_matcher/libraries/pgs2srt/Libraries/SubZero/dictionaries/data.py,sha256=GpbuAVy8IPX7KRqKUuhToJuUVqhASg_Phw_6j8KJN6g,676580
|
|
19
|
-
mkv_episode_matcher/notebooks/get_subtitles_test.ipynb,sha256=7dku1ttsUB96R_7RVhSKAlbMfuJsOxkXAtFgJUwVqqc,8031
|
|
20
|
-
mkv_episode_matcher/notebooks/whisper.ipynb,sha256=c2IoZxpuBca9oId4KQUAzcCCiv8OogSDGpFE6fdxSJ4,5880
|
|
21
|
-
mkv_episode_matcher-0.1.13.dist-info/METADATA,sha256=PDlYlhGWOlbdeOUNFAbccsFB1clMd2wCbXrHrjItVQo,4841
|
|
22
|
-
mkv_episode_matcher-0.1.13.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
|
23
|
-
mkv_episode_matcher-0.1.13.dist-info/entry_points.txt,sha256=IglJ43SuCZq2eQ3shMFILCkmQASJHnDCI3ogohW2Hn4,64
|
|
24
|
-
mkv_episode_matcher-0.1.13.dist-info/top_level.txt,sha256=XRLbd93HUaedeWLtkyTvQjFcE5QcBRYa3V-CfHrq-OI,20
|
|
25
|
-
mkv_episode_matcher-0.1.13.dist-info/RECORD,,
|
|
File without changes
|
{mkv_episode_matcher-0.1.13.dist-info → mkv_episode_matcher-0.3.0.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|