StreamingCommunity 2.0.5__py3-none-any.whl → 2.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 StreamingCommunity might be problematic. Click here for more details.
- StreamingCommunity/Api/Player/Helper/Vixcloud/util.py +15 -24
- StreamingCommunity/Api/Site/1337xx/site.py +9 -6
- StreamingCommunity/Api/Site/1337xx/title.py +2 -2
- StreamingCommunity/Api/Site/altadefinizione/costant.py +6 -2
- StreamingCommunity/Api/Site/altadefinizione/film.py +2 -2
- StreamingCommunity/Api/Site/altadefinizione/site.py +28 -22
- StreamingCommunity/Api/Site/animeunity/costant.py +6 -2
- StreamingCommunity/Api/Site/animeunity/film_serie.py +3 -3
- StreamingCommunity/Api/Site/animeunity/site.py +27 -19
- StreamingCommunity/Api/Site/cb01new/costant.py +6 -2
- StreamingCommunity/Api/Site/cb01new/film.py +2 -2
- StreamingCommunity/Api/Site/cb01new/site.py +20 -13
- StreamingCommunity/Api/Site/ddlstreamitaly/costant.py +6 -2
- StreamingCommunity/Api/Site/ddlstreamitaly/series.py +2 -2
- StreamingCommunity/Api/Site/ddlstreamitaly/site.py +9 -5
- StreamingCommunity/Api/Site/guardaserie/costant.py +6 -2
- StreamingCommunity/Api/Site/guardaserie/series.py +2 -3
- StreamingCommunity/Api/Site/guardaserie/site.py +10 -6
- StreamingCommunity/Api/Site/ilcorsaronero/costant.py +6 -2
- StreamingCommunity/Api/Site/ilcorsaronero/site.py +22 -13
- StreamingCommunity/Api/Site/ilcorsaronero/title.py +3 -3
- StreamingCommunity/Api/Site/mostraguarda/costant.py +6 -2
- StreamingCommunity/Api/Site/mostraguarda/film.py +2 -2
- StreamingCommunity/Api/Site/streamingcommunity/costant.py +7 -3
- StreamingCommunity/Api/Site/streamingcommunity/film.py +3 -3
- StreamingCommunity/Api/Site/streamingcommunity/series.py +2 -2
- StreamingCommunity/Api/Site/streamingcommunity/site.py +29 -28
- StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py +24 -24
- StreamingCommunity/Api/Template/Util/get_domain.py +100 -137
- StreamingCommunity/Lib/Downloader/HLS/downloader.py +3 -2
- StreamingCommunity/Lib/Downloader/HLS/segments.py +21 -17
- StreamingCommunity/Lib/M3U8/estimator.py +131 -106
- StreamingCommunity/Upload/version.py +1 -1
- StreamingCommunity/Util/ffmpeg_installer.py +8 -5
- {StreamingCommunity-2.0.5.dist-info → StreamingCommunity-2.3.0.dist-info}/METADATA +36 -19
- {StreamingCommunity-2.0.5.dist-info → StreamingCommunity-2.3.0.dist-info}/RECORD +40 -40
- {StreamingCommunity-2.0.5.dist-info → StreamingCommunity-2.3.0.dist-info}/LICENSE +0 -0
- {StreamingCommunity-2.0.5.dist-info → StreamingCommunity-2.3.0.dist-info}/WHEEL +0 -0
- {StreamingCommunity-2.0.5.dist-info → StreamingCommunity-2.3.0.dist-info}/entry_points.txt +0 -0
- {StreamingCommunity-2.0.5.dist-info → StreamingCommunity-2.3.0.dist-info}/top_level.txt +0 -0
|
@@ -194,23 +194,28 @@ class M3U8_Segments:
|
|
|
194
194
|
"""
|
|
195
195
|
if self.is_index_url:
|
|
196
196
|
|
|
197
|
-
|
|
198
|
-
response = httpx.get(
|
|
199
|
-
self.url,
|
|
200
|
-
headers={'User-Agent': get_headers()},
|
|
201
|
-
timeout=max_timeout
|
|
202
|
-
)
|
|
203
|
-
response.raise_for_status()
|
|
197
|
+
try:
|
|
204
198
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
199
|
+
# Send a GET request to retrieve the index M3U8 file
|
|
200
|
+
response = httpx.get(
|
|
201
|
+
self.url,
|
|
202
|
+
headers={'User-Agent': get_headers()},
|
|
203
|
+
timeout=max_timeout,
|
|
204
|
+
follow_redirects=True
|
|
205
|
+
)
|
|
206
|
+
response.raise_for_status()
|
|
208
207
|
|
|
209
|
-
|
|
210
|
-
|
|
208
|
+
# Save the M3U8 file to the temporary folder
|
|
209
|
+
path_m3u8_file = os.path.join(self.tmp_folder, "playlist.m3u8")
|
|
210
|
+
open(path_m3u8_file, "w+").write(response.text)
|
|
211
211
|
|
|
212
|
-
|
|
212
|
+
# Parse the text from the M3U8 index file
|
|
213
|
+
self.parse_data(response.text)
|
|
213
214
|
|
|
215
|
+
except Exception as e:
|
|
216
|
+
print(f"Error during M3U8 index request: {e}")
|
|
217
|
+
|
|
218
|
+
else:
|
|
214
219
|
# Parser data of content of index pass in input to class
|
|
215
220
|
self.parse_data(self.url)
|
|
216
221
|
|
|
@@ -385,7 +390,7 @@ class M3U8_Segments:
|
|
|
385
390
|
buffer[index] = segment_content
|
|
386
391
|
|
|
387
392
|
except queue.Empty:
|
|
388
|
-
self.current_timeout = min(self.max_timeout, self.current_timeout * 1.
|
|
393
|
+
self.current_timeout = min(self.max_timeout, self.current_timeout * 1.25)
|
|
389
394
|
|
|
390
395
|
if self.stop_event.is_set():
|
|
391
396
|
break
|
|
@@ -545,15 +550,14 @@ class M3U8_Segments:
|
|
|
545
550
|
if file_size == 0:
|
|
546
551
|
raise Exception("Output file is empty")
|
|
547
552
|
|
|
548
|
-
# Display additional
|
|
549
|
-
if self.
|
|
553
|
+
# Display additional
|
|
554
|
+
if self.info_nRetry >= len(self.segments) * 0.3:
|
|
550
555
|
|
|
551
556
|
# Get expected time
|
|
552
557
|
ex_hours, ex_minutes, ex_seconds = format_duration(self.expected_real_time_s)
|
|
553
558
|
ex_formatted_duration = f"[yellow]{int(ex_hours)}[red]h [yellow]{int(ex_minutes)}[red]m [yellow]{int(ex_seconds)}[red]s"
|
|
554
559
|
console.print(f"[cyan]Max retry per URL[white]: [green]{self.info_maxRetry}[green] [white]| [cyan]Total retry done[white]: [green]{self.info_nRetry}[green] [white]| [cyan]Missing TS: [red]{self.info_nFailed} [white]| [cyan]Duration: {print_duration_table(self.tmp_file_path, None, True)} [white]| [cyan]Expected duation: {ex_formatted_duration} \n")
|
|
555
560
|
|
|
556
|
-
if self.info_nRetry >= len(self.segments) * (1/3.33):
|
|
557
561
|
console.print("[yellow]⚠ Warning:[/yellow] Too many retries detected! Consider reducing the number of [cyan]workers[/cyan] in the [magenta]config.json[/magenta] file. This will impact [bold]performance[/bold]. \n")
|
|
558
562
|
|
|
559
563
|
# Info to return
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# 21.04.25
|
|
2
|
+
|
|
1
3
|
import os
|
|
2
4
|
import time
|
|
3
5
|
import logging
|
|
@@ -24,7 +26,7 @@ class M3U8_Ts_Estimator:
|
|
|
24
26
|
def __init__(self, total_segments: int):
|
|
25
27
|
"""
|
|
26
28
|
Initialize the M3U8_Ts_Estimator object.
|
|
27
|
-
|
|
29
|
+
|
|
28
30
|
Parameters:
|
|
29
31
|
- total_segments (int): Length of total segments to download.
|
|
30
32
|
"""
|
|
@@ -33,103 +35,119 @@ class M3U8_Ts_Estimator:
|
|
|
33
35
|
self.total_segments = total_segments
|
|
34
36
|
self.lock = threading.Lock()
|
|
35
37
|
self.speed = {"upload": "N/A", "download": "N/A"}
|
|
38
|
+
self.process_pid = os.getpid() # Get current process PID
|
|
39
|
+
logging.debug(f"Initializing M3U8_Ts_Estimator with PID: {self.process_pid}")
|
|
36
40
|
|
|
37
|
-
#
|
|
38
|
-
if
|
|
39
|
-
|
|
41
|
+
# Start the speed capture thread if TQDM_USE_LARGE_BAR is True
|
|
42
|
+
if TQDM_USE_LARGE_BAR:
|
|
43
|
+
logging.debug("TQDM_USE_LARGE_BAR is True, starting speed capture thread")
|
|
44
|
+
self.speed_thread = threading.Thread(target=self.capture_speed, args=(1, self.process_pid))
|
|
40
45
|
self.speed_thread.daemon = True
|
|
41
46
|
self.speed_thread.start()
|
|
42
47
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
Add a file size to the list of file sizes.
|
|
48
|
+
else:
|
|
49
|
+
logging.debug("TQDM_USE_LARGE_BAR is False, speed capture thread not started")
|
|
46
50
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"""
|
|
51
|
+
def add_ts_file(self, size: int, size_download: int, duration: float):
|
|
52
|
+
"""Add a file size to the list of file sizes."""
|
|
53
|
+
logging.debug(f"Adding ts file - size: {size}, download size: {size_download}, duration: {duration}")
|
|
54
|
+
|
|
52
55
|
if size <= 0 or size_download <= 0 or duration <= 0:
|
|
53
|
-
logging.error("Invalid input values: size
|
|
56
|
+
logging.error(f"Invalid input values: size={size}, size_download={size_download}, duration={duration}")
|
|
54
57
|
return
|
|
55
58
|
|
|
56
|
-
# Add total size bytes
|
|
57
59
|
self.ts_file_sizes.append(size)
|
|
58
60
|
self.now_downloaded_size += size_download
|
|
61
|
+
logging.debug(f"Current total downloaded size: {self.now_downloaded_size}")
|
|
59
62
|
|
|
60
63
|
def capture_speed(self, interval: float = 1, pid: int = None):
|
|
61
|
-
"""
|
|
62
|
-
|
|
63
|
-
or the entire system if no PID is provided.
|
|
64
|
-
"""
|
|
64
|
+
"""Capture the internet speed periodically."""
|
|
65
|
+
logging.debug(f"Starting speed capture with interval {interval}s for PID: {pid}")
|
|
65
66
|
|
|
66
67
|
def get_network_io(process=None):
|
|
67
|
-
"""
|
|
68
|
-
Get network I/O counters for a specific process or system-wide if no process is specified.
|
|
69
|
-
"""
|
|
70
68
|
try:
|
|
71
69
|
if process:
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
|
|
71
|
+
# For process-specific monitoring
|
|
72
|
+
connections = process.connections(kind='inet')
|
|
73
|
+
if connections:
|
|
74
|
+
io_counters = process.io_counters()
|
|
75
|
+
logging.debug(f"Process IO counters: {io_counters}")
|
|
76
|
+
return io_counters
|
|
77
|
+
|
|
78
|
+
else:
|
|
79
|
+
logging.debug("No active internet connections found for process")
|
|
80
|
+
return None
|
|
74
81
|
else:
|
|
82
|
+
|
|
83
|
+
# For system-wide monitoring
|
|
75
84
|
io_counters = psutil.net_io_counters()
|
|
85
|
+
logging.debug(f"System IO counters: {io_counters}")
|
|
76
86
|
return io_counters
|
|
87
|
+
|
|
77
88
|
except Exception as e:
|
|
78
|
-
logging.
|
|
89
|
+
logging.error(f"Error getting network IO: {str(e)}")
|
|
79
90
|
return None
|
|
80
91
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
try:
|
|
85
|
-
process = psutil.Process(pid)
|
|
86
|
-
except psutil.NoSuchProcess:
|
|
87
|
-
logging.error(f"Process with PID {pid} does not exist.")
|
|
88
|
-
return
|
|
89
|
-
except Exception as e:
|
|
90
|
-
logging.error(f"Failed to attach to process with PID {pid}: {e}")
|
|
91
|
-
return
|
|
92
|
-
|
|
93
|
-
while True:
|
|
94
|
-
old_value = get_network_io(process)
|
|
95
|
-
|
|
96
|
-
if old_value is None: # If psutil fails, continue with the next interval
|
|
97
|
-
time.sleep(interval)
|
|
98
|
-
continue
|
|
99
|
-
|
|
100
|
-
time.sleep(interval)
|
|
101
|
-
new_value = get_network_io(process)
|
|
92
|
+
try:
|
|
93
|
+
process = psutil.Process(pid) if pid else None
|
|
94
|
+
logging.debug(f"Monitoring process: {process}")
|
|
102
95
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
96
|
+
except Exception as e:
|
|
97
|
+
logging.error(f"Failed to get process with PID {pid}: {str(e)}")
|
|
98
|
+
process = None
|
|
106
99
|
|
|
107
|
-
|
|
100
|
+
last_upload = None
|
|
101
|
+
last_download = None
|
|
102
|
+
first_run = True
|
|
103
|
+
|
|
104
|
+
# Buffer circolare per le ultime N misurazioni
|
|
105
|
+
speed_buffer_size = 3
|
|
106
|
+
speed_buffer = deque(maxlen=speed_buffer_size)
|
|
108
107
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
108
|
+
while True:
|
|
109
|
+
try:
|
|
110
|
+
io_counters = get_network_io()
|
|
111
|
+
|
|
112
|
+
if io_counters:
|
|
113
|
+
current_upload = io_counters.bytes_sent
|
|
114
|
+
current_download = io_counters.bytes_recv
|
|
113
115
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
116
|
+
if not first_run and last_upload is not None and last_download is not None:
|
|
117
|
+
|
|
118
|
+
# Calcola la velocità istantanea
|
|
119
|
+
upload_speed = max(0, (current_upload - last_upload) / interval)
|
|
120
|
+
download_speed = max(0, (current_download - last_download) / interval)
|
|
121
|
+
|
|
122
|
+
# Aggiungi al buffer
|
|
123
|
+
speed_buffer.append(download_speed)
|
|
124
|
+
|
|
125
|
+
# Calcola la media mobile delle velocità
|
|
126
|
+
if len(speed_buffer) > 0:
|
|
127
|
+
avg_download_speed = sum(speed_buffer) / len(speed_buffer)
|
|
128
|
+
|
|
129
|
+
if avg_download_speed > 0:
|
|
130
|
+
with self.lock:
|
|
131
|
+
self.speed = {
|
|
132
|
+
"upload": internet_manager.format_transfer_speed(upload_speed),
|
|
133
|
+
"download": internet_manager.format_transfer_speed(avg_download_speed)
|
|
134
|
+
}
|
|
135
|
+
logging.debug(f"Updated speeds - Upload: {self.speed['upload']}, Download: {self.speed['download']}")
|
|
136
|
+
|
|
137
|
+
last_upload = current_upload
|
|
138
|
+
last_download = current_download
|
|
139
|
+
first_run = False
|
|
140
|
+
|
|
141
|
+
time.sleep(interval)
|
|
142
|
+
except Exception as e:
|
|
143
|
+
logging.error(f"Error in speed capture loop: {str(e)}")
|
|
144
|
+
logging.exception("Full traceback:")
|
|
145
|
+
logging.sleep(interval)
|
|
128
146
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
"""
|
|
147
|
+
def get_average_speed(self) -> list:
|
|
148
|
+
"""Calculate the average internet speed."""
|
|
132
149
|
with self.lock:
|
|
150
|
+
logging.debug(f"Current speed data: {self.speed}")
|
|
133
151
|
return self.speed['download'].split(" ")
|
|
134
152
|
|
|
135
153
|
def calculate_total_size(self) -> str:
|
|
@@ -156,7 +174,7 @@ class M3U8_Ts_Estimator:
|
|
|
156
174
|
except Exception as e:
|
|
157
175
|
logging.error("An unexpected error occurred: %s", e)
|
|
158
176
|
return "Error"
|
|
159
|
-
|
|
177
|
+
|
|
160
178
|
def get_downloaded_size(self) -> str:
|
|
161
179
|
"""
|
|
162
180
|
Get the total downloaded size formatted as a human-readable string.
|
|
@@ -165,40 +183,47 @@ class M3U8_Ts_Estimator:
|
|
|
165
183
|
str: The total downloaded size as a human-readable string.
|
|
166
184
|
"""
|
|
167
185
|
return internet_manager.format_file_size(self.now_downloaded_size)
|
|
168
|
-
|
|
186
|
+
|
|
169
187
|
def update_progress_bar(self, total_downloaded: int, duration: float, progress_counter: tqdm) -> None:
|
|
170
|
-
"""
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
units_file_total_size = file_total_size.split(' ')[1]
|
|
190
|
-
|
|
191
|
-
# Update the progress bar's postfix
|
|
192
|
-
if TQDM_USE_LARGE_BAR:
|
|
193
|
-
average_internet_speed = self.get_average_speed()[0]
|
|
194
|
-
average_internet_unit = self.get_average_speed()[1]
|
|
195
|
-
progress_counter.set_postfix_str(
|
|
196
|
-
f"{Colors.WHITE}[ {Colors.GREEN}{number_file_downloaded} {Colors.WHITE}< {Colors.GREEN}{number_file_total_size} {Colors.RED}{units_file_total_size} "
|
|
197
|
-
f"{Colors.WHITE}| {Colors.CYAN}{average_internet_speed} {Colors.RED}{average_internet_unit}"
|
|
198
|
-
)
|
|
188
|
+
"""Updates the progress bar with download information."""
|
|
189
|
+
try:
|
|
190
|
+
self.add_ts_file(total_downloaded * self.total_segments, total_downloaded, duration)
|
|
191
|
+
|
|
192
|
+
downloaded_file_size_str = self.get_downloaded_size()
|
|
193
|
+
file_total_size = self.calculate_total_size()
|
|
194
|
+
|
|
195
|
+
number_file_downloaded = downloaded_file_size_str.split(' ')[0]
|
|
196
|
+
number_file_total_size = file_total_size.split(' ')[0]
|
|
197
|
+
units_file_downloaded = downloaded_file_size_str.split(' ')[1]
|
|
198
|
+
units_file_total_size = file_total_size.split(' ')[1]
|
|
199
|
+
|
|
200
|
+
if TQDM_USE_LARGE_BAR:
|
|
201
|
+
speed_data = self.get_average_speed()
|
|
202
|
+
logging.debug(f"Speed data for progress bar: {speed_data}")
|
|
203
|
+
|
|
204
|
+
if len(speed_data) >= 2:
|
|
205
|
+
average_internet_speed = speed_data[0]
|
|
206
|
+
average_internet_unit = speed_data[1]
|
|
199
207
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
208
|
+
else:
|
|
209
|
+
logging.warning(f"Invalid speed data format: {speed_data}")
|
|
210
|
+
average_internet_speed = "N/A"
|
|
211
|
+
average_internet_unit = ""
|
|
212
|
+
|
|
213
|
+
progress_str = (
|
|
214
|
+
f"{Colors.WHITE}[ {Colors.GREEN}{number_file_downloaded} {Colors.WHITE}< "
|
|
215
|
+
f"{Colors.GREEN}{number_file_total_size} {Colors.RED}{units_file_total_size} "
|
|
216
|
+
f"{Colors.WHITE}| {Colors.CYAN}{average_internet_speed} {Colors.RED}{average_internet_unit}"
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
else:
|
|
220
|
+
progress_str = (
|
|
221
|
+
f"{Colors.WHITE}[ {Colors.GREEN}{number_file_downloaded} {Colors.WHITE}< "
|
|
222
|
+
f"{Colors.GREEN}{number_file_total_size} {Colors.RED}{units_file_total_size}"
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
progress_counter.set_postfix_str(progress_str)
|
|
226
|
+
logging.debug(f"Updated progress bar: {progress_str}")
|
|
227
|
+
|
|
228
|
+
except Exception as e:
|
|
229
|
+
logging.error(f"Error updating progress bar: {str(e)}")
|
|
@@ -140,6 +140,7 @@ class FFMPEGDownloader:
|
|
|
140
140
|
break
|
|
141
141
|
found_executables.append(found)
|
|
142
142
|
else:
|
|
143
|
+
|
|
143
144
|
# Original behavior for other operating systems
|
|
144
145
|
for executable in executables:
|
|
145
146
|
exe_paths = glob.glob(os.path.join(self.base_dir, executable))
|
|
@@ -298,13 +299,14 @@ def check_ffmpeg() -> Tuple[Optional[str], Optional[str], Optional[str]]:
|
|
|
298
299
|
|
|
299
300
|
# Special handling for macOS
|
|
300
301
|
if system_platform == 'darwin':
|
|
302
|
+
|
|
301
303
|
# Common installation paths on macOS
|
|
302
304
|
potential_paths = [
|
|
303
|
-
'/usr/local/bin',
|
|
304
|
-
'/opt/homebrew/bin',
|
|
305
|
-
'/usr/bin',
|
|
306
|
-
os.path.expanduser('~/Applications/binary'),
|
|
307
|
-
'/Applications/binary'
|
|
305
|
+
'/usr/local/bin', # Homebrew default
|
|
306
|
+
'/opt/homebrew/bin', # Apple Silicon Homebrew
|
|
307
|
+
'/usr/bin', # System default
|
|
308
|
+
os.path.expanduser('~/Applications/binary'), # Custom installation
|
|
309
|
+
'/Applications/binary' # Custom installation
|
|
308
310
|
]
|
|
309
311
|
|
|
310
312
|
for path in potential_paths:
|
|
@@ -314,6 +316,7 @@ def check_ffmpeg() -> Tuple[Optional[str], Optional[str], Optional[str]]:
|
|
|
314
316
|
|
|
315
317
|
if (os.path.exists(ffmpeg_path) and os.path.exists(ffprobe_path) and
|
|
316
318
|
os.access(ffmpeg_path, os.X_OK) and os.access(ffprobe_path, os.X_OK)):
|
|
319
|
+
|
|
317
320
|
# Return found executables, with ffplay being optional
|
|
318
321
|
ffplay_path = ffplay_path if os.path.exists(ffplay_path) else None
|
|
319
322
|
return ffmpeg_path, ffprobe_path, ffplay_path
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: StreamingCommunity
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.3.0
|
|
4
4
|
Summary: UNKNOWN
|
|
5
5
|
Home-page: https://github.com/Lovi-0/StreamingCommunity
|
|
6
6
|
Author: Lovi-0
|
|
@@ -34,9 +34,6 @@ Requires-Dist: googlesearch-python
|
|
|
34
34
|
<a href="https://pypi.org/project/streamingcommunity">
|
|
35
35
|
<img src="https://img.shields.io/pypi/v/streamingcommunity?logo=pypi&labelColor=555555&style=for-the-badge" alt="PyPI"/>
|
|
36
36
|
</a>
|
|
37
|
-
<a href="https://www.python.org">
|
|
38
|
-
<img src="https://img.shields.io/badge/Python->=3.8-3776AB?style=for-the-badge&logo=python&logoColor=white" alt="Python"/>
|
|
39
|
-
</a>
|
|
40
37
|
<a href="https://www.paypal.com/donate/?hosted_button_id=UXTWMT8P6HE2C">
|
|
41
38
|
<img src="https://img.shields.io/badge/_-Donate-red.svg?logo=githubsponsors&labelColor=555555&style=for-the-badge" alt="Donate"/>
|
|
42
39
|
</a>
|
|
@@ -90,6 +87,22 @@ Requires-Dist: googlesearch-python
|
|
|
90
87
|
|
|
91
88
|
# Installation
|
|
92
89
|
|
|
90
|
+
<p align="center">
|
|
91
|
+
<a href="https://github.com/Lovi-0/StreamingCommunity/releases/latest/download/StreamingCommunity.exe">
|
|
92
|
+
<img src="https://img.shields.io/badge/-Windows_x64-blue.svg?style=for-the-badge&logo=windows" alt="Windows">
|
|
93
|
+
</a>
|
|
94
|
+
<a href="https://pypi.org/project/StreamingCommunity">
|
|
95
|
+
<img src="https://img.shields.io/badge/-PyPI-blue.svg?logo=pypi&labelColor=555555&style=for-the-badge" alt="PyPI">
|
|
96
|
+
</a>
|
|
97
|
+
<a href="https://github.com/Lovi-0/StreamingCommunity/releases/latest/download/StreamingCommunity.zip">
|
|
98
|
+
<img src="https://img.shields.io/badge/-Source_tar-green.svg?style=for-the-badge" alt="Source Tarball">
|
|
99
|
+
</a>
|
|
100
|
+
<a href="https://github.com/Lovi-0/StreamingCommunity/releases">
|
|
101
|
+
<img src="https://img.shields.io/badge/-All_Versions-lightgrey.svg?style=for-the-badge" alt="All Versions">
|
|
102
|
+
</a>
|
|
103
|
+
</p>
|
|
104
|
+
|
|
105
|
+
|
|
93
106
|
## 1. PyPI Installation
|
|
94
107
|
|
|
95
108
|
Install directly from PyPI:
|
|
@@ -229,6 +242,8 @@ The configuration file is divided into several main sections:
|
|
|
229
242
|
"movie_folder_name": "Movie",
|
|
230
243
|
"serie_folder_name": "TV",
|
|
231
244
|
"map_episode_name": "%(tv_name)_S%(season)E%(episode)_%(episode_name)",
|
|
245
|
+
"add_siteName": false,
|
|
246
|
+
"disable_searchDomain": false,
|
|
232
247
|
"not_close": false
|
|
233
248
|
}
|
|
234
249
|
```
|
|
@@ -256,7 +271,10 @@ The configuration file is divided into several main sections:
|
|
|
256
271
|
* `%(episode_name)` : Is the name of the episode
|
|
257
272
|
`<br/><br/>`
|
|
258
273
|
|
|
259
|
-
- `
|
|
274
|
+
- `add_siteName`: If set to true, appends the site_name to the root path before the movie and serie folders.
|
|
275
|
+
- `disable_searchDomain`: If set to true, disables the search for a new domain for all sites.
|
|
276
|
+
- `not_close`: If set to true, keeps the program running after the download is complete.
|
|
277
|
+
|
|
260
278
|
|
|
261
279
|
### qBittorrent Configuration
|
|
262
280
|
|
|
@@ -273,7 +291,6 @@ The configuration file is divided into several main sections:
|
|
|
273
291
|
|
|
274
292
|
To enable qBittorrent integration, follow the setup guide [here](https://github.com/lgallard/qBittorrent-Controller/wiki/How-to-enable-the-qBittorrent-Web-UI).
|
|
275
293
|
|
|
276
|
-
<br>
|
|
277
294
|
|
|
278
295
|
## REQUESTS Settings
|
|
279
296
|
|
|
@@ -287,7 +304,6 @@ The configuration file is divided into several main sections:
|
|
|
287
304
|
- `timeout`: Maximum timeout (in seconds) for each request
|
|
288
305
|
- `max_retry`: Number of retry attempts per segment during M3U8 index download
|
|
289
306
|
|
|
290
|
-
<br>
|
|
291
307
|
|
|
292
308
|
## M3U8_DOWNLOAD Settings
|
|
293
309
|
|
|
@@ -307,8 +323,10 @@ The configuration file is divided into several main sections:
|
|
|
307
323
|
- `default_audio_workser`: Number of threads for audio download
|
|
308
324
|
- `cleanup_tmp_folder`: Remove temporary .ts files after download
|
|
309
325
|
|
|
326
|
+
> [!IMPORTANT]
|
|
327
|
+
> Set `tqdm_use_large_bar` to `false` when using Termux or terminals with limited width to prevent network monitoring issues
|
|
328
|
+
|
|
310
329
|
|
|
311
|
-
<br>
|
|
312
330
|
|
|
313
331
|
### Language Settings
|
|
314
332
|
|
|
@@ -357,7 +375,6 @@ forced-ita hin - Hindi pol - Polish tur - Turkish
|
|
|
357
375
|
- `force_resolution`: Force specific resolution (-1 for best available, or specify 1080, 720, 360)
|
|
358
376
|
- `get_only_link`: Return M3U8 playlist/index URL instead of downloading
|
|
359
377
|
|
|
360
|
-
<br>
|
|
361
378
|
|
|
362
379
|
# COMMAND
|
|
363
380
|
|
|
@@ -373,7 +390,6 @@ forced-ita hin - Hindi pol - Polish tur - Turkish
|
|
|
373
390
|
- Enter a season number followed by `-*` to download from that season to the end.
|
|
374
391
|
* **Example:** `3-*` will download from *Season 3* to the final season.
|
|
375
392
|
|
|
376
|
-
<br>
|
|
377
393
|
|
|
378
394
|
# Docker
|
|
379
395
|
|
|
@@ -412,15 +428,16 @@ The `run-container` command mounts also the `config.json` file, so any change to
|
|
|
412
428
|
|
|
413
429
|
| Website | Status |
|
|
414
430
|
|:-------------------|:------:|
|
|
415
|
-
| 1337xx
|
|
416
|
-
| Altadefinizione
|
|
417
|
-
| AnimeUnity
|
|
418
|
-
| Ilcorsaronero
|
|
419
|
-
| CB01New
|
|
420
|
-
| DDLStreamItaly
|
|
421
|
-
| GuardaSerie
|
|
422
|
-
| MostraGuarda
|
|
423
|
-
| StreamingCommunity | ✅ |
|
|
431
|
+
| [1337xx](https://1337xx.to/) | ✅ |
|
|
432
|
+
| [Altadefinizione](https://altadefinizione.prof/) | ✅ |
|
|
433
|
+
| [AnimeUnity](https://animeunity.so/) | ✅ |
|
|
434
|
+
| [Ilcorsaronero](https://ilcorsaronero.link/) | ✅ |
|
|
435
|
+
| [CB01New](https://cb01new.pics/) | ✅ |
|
|
436
|
+
| [DDLStreamItaly](https://ddlstreamitaly.co/) | ✅ |
|
|
437
|
+
| [GuardaSerie](https://guardaserie.academy/) | ✅ |
|
|
438
|
+
| [MostraGuarda](https://mostraguarda.stream/) | ✅ |
|
|
439
|
+
| [StreamingCommunity](https://streamingcommunity.prof/) | ✅ |
|
|
440
|
+
|
|
424
441
|
|
|
425
442
|
# Tutorials
|
|
426
443
|
|