StreamingCommunity 2.0.0__py3-none-any.whl → 2.2.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.

Files changed (33) hide show
  1. StreamingCommunity/Api/Site/1337xx/__init__.py +1 -1
  2. StreamingCommunity/Api/Site/altadefinizione/__init__.py +1 -1
  3. StreamingCommunity/Api/Site/animeunity/__init__.py +1 -1
  4. StreamingCommunity/Api/Site/cb01new/__init__.py +1 -1
  5. StreamingCommunity/Api/Site/ddlstreamitaly/__init__.py +1 -3
  6. StreamingCommunity/Api/Site/ddlstreamitaly/series.py +1 -1
  7. StreamingCommunity/Api/Site/guardaserie/__init__.py +1 -3
  8. StreamingCommunity/Api/Site/guardaserie/series.py +2 -2
  9. StreamingCommunity/Api/Site/ilcorsaronero/__init__.py +1 -1
  10. StreamingCommunity/Api/Site/ilcorsaronero/util/ilCorsarScraper.py +14 -6
  11. StreamingCommunity/Api/Site/mostraguarda/__init__.py +1 -1
  12. StreamingCommunity/Api/Site/mostraguarda/film.py +1 -3
  13. StreamingCommunity/Api/Site/streamingcommunity/__init__.py +1 -1
  14. StreamingCommunity/Api/Site/streamingcommunity/film.py +1 -1
  15. StreamingCommunity/Api/Site/streamingcommunity/series.py +1 -1
  16. StreamingCommunity/Api/Template/Util/get_domain.py +12 -11
  17. StreamingCommunity/Lib/Downloader/HLS/downloader.py +42 -34
  18. StreamingCommunity/Lib/Downloader/HLS/segments.py +9 -11
  19. StreamingCommunity/Lib/FFmpeg/capture.py +1 -1
  20. StreamingCommunity/Lib/FFmpeg/util.py +1 -1
  21. StreamingCommunity/Lib/M3U8/decryptor.py +2 -2
  22. StreamingCommunity/Lib/M3U8/estimator.py +143 -90
  23. StreamingCommunity/Upload/update.py +2 -3
  24. StreamingCommunity/Upload/version.py +1 -1
  25. StreamingCommunity/Util/ffmpeg_installer.py +68 -28
  26. StreamingCommunity/Util/os.py +16 -25
  27. StreamingCommunity/run.py +0 -1
  28. {StreamingCommunity-2.0.0.dist-info → StreamingCommunity-2.2.0.dist-info}/METADATA +12 -9
  29. {StreamingCommunity-2.0.0.dist-info → StreamingCommunity-2.2.0.dist-info}/RECORD +33 -33
  30. {StreamingCommunity-2.0.0.dist-info → StreamingCommunity-2.2.0.dist-info}/WHEEL +1 -1
  31. {StreamingCommunity-2.0.0.dist-info → StreamingCommunity-2.2.0.dist-info}/entry_points.txt +1 -0
  32. {StreamingCommunity-2.0.0.dist-info → StreamingCommunity-2.2.0.dist-info}/LICENSE +0 -0
  33. {StreamingCommunity-2.0.0.dist-info → StreamingCommunity-2.2.0.dist-info}/top_level.txt +0 -0
@@ -27,7 +27,7 @@ def search(string_to_search: str = None, get_onylDatabase: bool = False):
27
27
  """
28
28
 
29
29
  if string_to_search is None:
30
- string_to_search = msg.ask(f"\n[purple]Insert word to search in [red]{SITE_NAME}").strip()
30
+ string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{SITE_NAME}").strip()
31
31
 
32
32
  # Search on database
33
33
  len_database = title_search(quote_plus(string_to_search))
@@ -27,7 +27,7 @@ def search(string_to_search: str = None, get_onylDatabase: bool = False):
27
27
  """
28
28
 
29
29
  if string_to_search is None:
30
- string_to_search = msg.ask(f"\n[purple]Insert word to search in [red]{SITE_NAME}").strip()
30
+ string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{SITE_NAME}").strip()
31
31
 
32
32
  # Search on database
33
33
  len_database = title_search(quote_plus(string_to_search))
@@ -24,7 +24,7 @@ from .costant import SITE_NAME
24
24
  def search(string_to_search: str = None, get_onylDatabase: bool = False):
25
25
 
26
26
  if string_to_search is None:
27
- string_to_search = msg.ask(f"\n[purple]Insert word to search in [red]{SITE_NAME}").strip()
27
+ string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{SITE_NAME}").strip()
28
28
 
29
29
  # Search on database
30
30
  len_database = title_search(quote_plus(string_to_search))
@@ -27,7 +27,7 @@ def search(string_to_search: str = None, get_onylDatabase: bool = False):
27
27
  """
28
28
 
29
29
  if string_to_search is None:
30
- string_to_search = msg.ask(f"\n[purple]Insert word to search in [red]{SITE_NAME}").strip()
30
+ string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{SITE_NAME}").strip()
31
31
 
32
32
  # Search on database
33
33
  len_database = title_search(quote_plus(string_to_search))
@@ -28,9 +28,7 @@ def search(string_to_search: str = None, get_onylDatabase: bool = False):
28
28
  """
29
29
 
30
30
  if string_to_search is None:
31
-
32
- # Make request to site to get content that corrsisponde to that string
33
- string_to_search = msg.ask(f"\n[purple]Insert word to search in [red]{SITE_NAME}").strip()
31
+ string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{SITE_NAME}").strip()
34
32
 
35
33
  # Search on database
36
34
  len_database = title_search(quote_plus(string_to_search))
@@ -25,7 +25,6 @@ from StreamingCommunity.Api.Player.ddl import VideoSource
25
25
 
26
26
  # Variable
27
27
  from .costant import ROOT_PATH, SERIES_FOLDER
28
- table_show_manager = TVShowManager()
29
28
 
30
29
 
31
30
 
@@ -120,6 +119,7 @@ def display_episodes_list(obj_episode_manager) -> str:
120
119
  """
121
120
 
122
121
  # Set up table for displaying episodes
122
+ table_show_manager = TVShowManager()
123
123
  table_show_manager.set_slice_end(10)
124
124
 
125
125
  # Add columns to the table
@@ -27,9 +27,7 @@ def search(string_to_search: str = None, get_onylDatabase: bool = False):
27
27
  """
28
28
 
29
29
  if string_to_search is None:
30
-
31
- # Make request to site to get content that corrsisponde to that string
32
- string_to_search = msg.ask(f"\n[purple]Insert word to search in [red]{SITE_NAME}").strip()
30
+ string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{SITE_NAME}").strip()
33
31
 
34
32
  # Search on database
35
33
  len_database = title_search(quote_plus(string_to_search))
@@ -25,7 +25,6 @@ from StreamingCommunity.Api.Player.supervideo import VideoSource
25
25
 
26
26
  # Variable
27
27
  from .costant import ROOT_PATH, SERIES_FOLDER
28
- table_show_manager = TVShowManager()
29
28
 
30
29
 
31
30
 
@@ -171,8 +170,9 @@ def display_episodes_list(obj_episode_manager) -> str:
171
170
  Returns:
172
171
  last_command (str): Last command entered by the user.
173
172
  """
174
-
173
+
175
174
  # Set up table for displaying episodes
175
+ table_show_manager = TVShowManager()
176
176
  table_show_manager.set_slice_end(10)
177
177
 
178
178
  # Add columns to the table
@@ -28,7 +28,7 @@ def search(string_to_search: str = None, get_onylDatabase: bool = False):
28
28
  """
29
29
 
30
30
  if string_to_search is None:
31
- string_to_search = msg.ask(f"\n[purple]Insert word to search in [red]{SITE_NAME}").strip()
31
+ string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{SITE_NAME}").strip()
32
32
 
33
33
  # Search on database
34
34
  len_database = asyncio.run(title_search(quote_plus(string_to_search)))
@@ -25,13 +25,21 @@ class IlCorsaroNeroScraper:
25
25
  self.base_url = base_url
26
26
  self.max_page = max_page
27
27
  self.headers = {
28
- 'User-Agent': get_headers(),
29
- 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
30
- 'Accept-Language': 'en-US,en;q=0.5',
31
- 'Connection': 'keep-alive',
32
- 'Upgrade-Insecure-Requests': '1'
28
+ 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
29
+ 'accept-language': 'it-IT,it;q=0.9,en-US;q=0.8,en;q=0.7',
30
+ 'cache-control': 'max-age=0',
31
+ 'priority': 'u=0, i',
32
+ 'sec-ch-ua': '"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
33
+ 'sec-ch-ua-mobile': '?0',
34
+ 'sec-ch-ua-platform': '"Windows"',
35
+ 'sec-fetch-dest': 'document',
36
+ 'sec-fetch-mode': 'navigate',
37
+ 'sec-fetch-site': 'same-origin',
38
+ 'sec-fetch-user': '?1',
39
+ 'upgrade-insecure-requests': '1',
40
+ 'user-agent': get_headers()
33
41
  }
34
-
42
+
35
43
  async def fetch_url(self, url: str) -> Optional[str]:
36
44
  """
37
45
  Fetch the HTML content of a given URL.
@@ -27,7 +27,7 @@ def search(string_to_search: str = None, get_onylDatabase: bool = False):
27
27
  """
28
28
 
29
29
  if string_to_search is None:
30
- string_to_search = msg.ask(f"\n[purple]Insert word to search in [red]{SITE_NAME}").strip()
30
+ string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{SITE_NAME}").strip()
31
31
 
32
32
  # Not available for the moment
33
33
  if get_onylDatabase:
@@ -70,10 +70,8 @@ def download_film(movie_details: Json_film) -> str:
70
70
  player_links = soup.find("ul", class_ = "_player-mirrors").find_all("li")
71
71
  supervideo_url = "https:" + player_links[0].get("data-link")
72
72
 
73
-
74
73
  # Set domain and media ID for the video source
75
- video_source = VideoSource()
76
- video_source.setup(supervideo_url)
74
+ video_source = VideoSource(url=supervideo_url)
77
75
 
78
76
  # Define output path
79
77
  title_name = os_manager.get_sanitize_file(movie_details.title) + ".mp4"
@@ -28,7 +28,7 @@ def search(string_to_search: str = None, get_onylDatabase: bool = False):
28
28
  """
29
29
 
30
30
  if string_to_search is None:
31
- string_to_search = msg.ask(f"\n[purple]Insert word to search in [red]{SITE_NAME}").strip()
31
+ string_to_search = msg.ask(f"\n[purple]Insert word to search in [green]{SITE_NAME}").strip()
32
32
 
33
33
  # Get site domain and version and get result of the search
34
34
  site_version, domain = get_version_and_domain()
@@ -39,7 +39,7 @@ def download_film(select_title: MediaItem) -> str:
39
39
 
40
40
  # Start message and display film information
41
41
  start_message()
42
- console.print(f"[yellow]Download: [red]{select_title.slug} \n")
42
+ console.print(f"[yellow]Download: [red]{select_title.name} \n")
43
43
 
44
44
  # Init class
45
45
  video_source = VideoSource(SITE_NAME, False)
@@ -25,7 +25,6 @@ from StreamingCommunity.Api.Player.vixcloud import VideoSource
25
25
 
26
26
  # Variable
27
27
  from .costant import ROOT_PATH, SITE_NAME, SERIES_FOLDER
28
- table_show_manager = TVShowManager()
29
28
 
30
29
 
31
30
 
@@ -178,6 +177,7 @@ def display_episodes_list(scrape_serie) -> str:
178
177
  """
179
178
 
180
179
  # Set up table for displaying episodes
180
+ table_show_manager = TVShowManager()
181
181
  table_show_manager.set_slice_end(10)
182
182
 
183
183
  # Add columns to the table
@@ -76,17 +76,19 @@ def get_final_redirect_url(initial_url, max_timeout):
76
76
  console.print(f"\n[cyan]Test url[white]: [red]{initial_url}, [cyan]error[white]: [red]{e}")
77
77
  return None
78
78
 
79
- def search_domain(site_name: str, base_url: str):
79
+ def search_domain(site_name: str, base_url: str, get_first: bool = False):
80
80
  """
81
81
  Search for a valid domain for the given site name and base URL.
82
82
 
83
83
  Parameters:
84
84
  - site_name (str): The name of the site to search the domain for.
85
85
  - base_url (str): The base URL to construct complete URLs.
86
+ - get_first (bool): If True, automatically update to the first valid match without user confirmation.
86
87
 
87
88
  Returns:
88
89
  tuple: The found domain and the complete URL.
89
90
  """
91
+
90
92
  # Extract config domain
91
93
  max_timeout = config_manager.get_int("REQUESTS", "timeout")
92
94
  domain = str(config_manager.get_dict("SITE", site_name)['domain'])
@@ -107,10 +109,10 @@ def search_domain(site_name: str, base_url: str):
107
109
 
108
110
  except Exception as e:
109
111
  query = base_url.split("/")[-1]
110
-
112
+
111
113
  # Perform a Google search with multiple results
112
114
  search_results = list(search(query, num_results=10, lang="it"))
113
- console.print(f"\nGoogle search results: {search_results}")
115
+ #console.print(f"\nGoogle search results: {search_results}")
114
116
 
115
117
  def normalize_for_comparison(url):
116
118
  """Normalize URL by removing protocol, www, and trailing slashes"""
@@ -121,15 +123,15 @@ def search_domain(site_name: str, base_url: str):
121
123
 
122
124
  # Normalize the base_url we're looking for
123
125
  target_url = normalize_for_comparison(base_url)
124
-
126
+
125
127
  # Iterate through search results
126
128
  for first_url in search_results:
127
129
  console.print(f"[green]Checking url[white]: [red]{first_url}")
128
-
130
+
129
131
  # Get just the domain part of the search result
130
132
  parsed_result = urlparse(first_url)
131
133
  result_domain = normalize_for_comparison(parsed_result.netloc)
132
-
134
+
133
135
  # Compare with our target URL (without the protocol part)
134
136
  if result_domain.startswith(target_url.split("/")[-1]):
135
137
  try:
@@ -143,21 +145,20 @@ def search_domain(site_name: str, base_url: str):
143
145
 
144
146
  new_domain_extract = extract_domain(str(final_url))
145
147
 
146
- if msg.ask(f"\n[cyan]Do you want to auto update site[white] [red]'{site_name}'[cyan] with domain[white] [red]'{new_domain_extract}'.", choices=["y", "n"], default="y").lower() == "y":
147
-
148
+ if get_first or msg.ask(f"\n[cyan]Do you want to auto update site[white] [red]'{site_name}'[cyan] with domain[white] [red]'{new_domain_extract}'.", choices=["y", "n"], default="y").lower() == "y":
148
149
  # Update domain in config.json
149
150
  config_manager.config['SITE'][site_name]['domain'] = new_domain_extract
150
151
  config_manager.write_config()
151
152
 
152
153
  return new_domain_extract, f"{base_url}.{new_domain_extract}"
153
-
154
+
154
155
  except Exception as redirect_error:
155
156
  console.print(f"[red]Error following redirect for {first_url}: {redirect_error}")
156
157
  continue
157
158
 
158
- # If no matching URL is found
159
+ # If no matching URL is found return base domain
159
160
  console.print("[bold red]No valid URL found matching the base URL.[/bold red]")
160
- raise Exception("No matching domain found")
161
+ return domain, f"{base_url}.{domain}"
161
162
 
162
163
  # Handle successful initial domain check
163
164
  parsed_url = urlparse(str(response_follow.url))
@@ -176,9 +176,11 @@ class ContentExtractor:
176
176
  set_language = DOWNLOAD_SPECIFIC_AUDIO
177
177
  downloadable_languages = list(set(available_languages) & set(set_language))
178
178
 
179
- console.print(f"[cyan bold]Audio:[/cyan bold] [green]Available:[/green] [purple]{', '.join(available_languages)}[/purple] | "
180
- f"[red]Set:[/red] [purple]{', '.join(set_language)}[/purple] | "
181
- f"[yellow]Downloadable:[/yellow] [purple]{', '.join(downloadable_languages)}[/purple]")
179
+ # Only show if there is something available
180
+ if len(available_languages) > 0:
181
+ console.print(f"[cyan bold]Audio →[/cyan bold] [green]Available:[/green] [purple]{', '.join(available_languages)}[/purple] | "
182
+ f"[red]Set:[/red] [purple]{', '.join(set_language)}[/purple] | "
183
+ f"[yellow]Downloadable:[/yellow] [purple]{', '.join(downloadable_languages)}[/purple]")
182
184
 
183
185
  else:
184
186
  console.log("[red]Can't find a list of audios")
@@ -200,9 +202,11 @@ class ContentExtractor:
200
202
  set_language = DOWNLOAD_SPECIFIC_SUBTITLE
201
203
  downloadable_languages = list(set(available_languages) & set(set_language))
202
204
 
203
- console.print(f"[cyan bold]Subtitle:[/cyan bold] [green]Available:[/green] [purple]{', '.join(available_languages)}[/purple] | "
204
- f"[red]Set:[/red] [purple]{', '.join(set_language)}[/purple] | "
205
- f"[yellow]Downloadable:[/yellow] [purple]{', '.join(downloadable_languages)}[/purple]")
205
+ # Only show if there is something available
206
+ if len(available_languages) > 0:
207
+ console.print(f"[cyan bold]Subtitle →[/cyan bold] [green]Available:[/green] [purple]{', '.join(available_languages)}[/purple] | "
208
+ f"[red]Set:[/red] [purple]{', '.join(set_language)}[/purple] | "
209
+ f"[yellow]Downloadable:[/yellow] [purple]{', '.join(downloadable_languages)}[/purple]")
206
210
 
207
211
  else:
208
212
  console.log("[red]Can't find a list of subtitles")
@@ -212,13 +216,18 @@ class ContentExtractor:
212
216
  It identifies the best video quality and displays relevant information to the user.
213
217
  """
214
218
  logging.info(f"class 'ContentExtractor'; call _collect_video()")
219
+ set_resolution = "Best"
215
220
 
216
221
  # Collect custom quality video if a specific resolution is set
217
222
  if FILTER_CUSTOM_REOLUTION != -1:
218
223
  self.m3u8_index, video_res = self.obj_parse._video.get_custom_uri(y_resolution=FILTER_CUSTOM_REOLUTION)
224
+ set_resolution = f"{FILTER_CUSTOM_REOLUTION}p"
219
225
 
220
- # Otherwise, get the best available video quality
221
- self.m3u8_index, video_res = self.obj_parse._video.get_best_uri()
226
+ else:
227
+
228
+ # Otherwise, get the best available video quality
229
+ self.m3u8_index, video_res = self.obj_parse._video.get_best_uri()
230
+
222
231
  self.codec: M3U8_Codec = self.obj_parse.codec
223
232
 
224
233
  # List all available resolutions
@@ -227,18 +236,34 @@ class ContentExtractor:
227
236
  logging.info(f"M3U8 index selected: {self.m3u8_index}, with resolution: {video_res}")
228
237
 
229
238
  # Create a formatted table to display video info
230
- console.print(f"[cyan bold]Video:[/cyan bold] [green]Available resolutions:[/green] [purple]{', '.join(list_available_resolution)}[/purple] | "
231
- f"[yellow]Downloadable:[/yellow] [purple]{video_res[0]}x{video_res[1]}[/purple]")
239
+ console.print(f"[cyan bold]Video[/cyan bold] [green]Available:[/green] [purple]{', '.join(list_available_resolution)}[/purple] | "
240
+ f"[red]Set:[/red] [purple]{set_resolution}[/purple] | "
241
+ f"[yellow]Downloadable:[/yellow] [purple]{video_res[0]}x{video_res[1]}[/purple]")
232
242
 
233
243
  if self.codec is not None:
244
+
245
+ # Generate the string for available codec information
246
+ available_codec_info = (
247
+ f"[green]v[/green]: [yellow]{self.codec.video_codec_name}[/yellow] "
248
+ f"([green]b[/green]: [yellow]{self.codec.video_bitrate // 1000}k[/yellow]), "
249
+ f"[green]a[/green]: [yellow]{self.codec.audio_codec_name}[/yellow] "
250
+ f"([green]b[/green]: [yellow]{self.codec.audio_bitrate // 1000}k[/yellow])"
251
+ )
252
+
253
+ # Determine what to display for "Set"
254
+ # If the codec usage is enabled in the configuration, use the detailed codec info
255
+ # Otherwise, display "copy"
234
256
  if config_manager.get_bool("M3U8_CONVERSION", "use_codec"):
235
- codec_info = (f"[green]v[/green]: [yellow]{self.codec.video_codec_name}[/yellow] "
236
- f"([green]b[/green]: [yellow]{self.codec.video_bitrate // 1000}k[/yellow]), "
237
- f"[green]a[/green]: [yellow]{self.codec.audio_codec_name}[/yellow] "
238
- f"([green]b[/green]: [yellow]{self.codec.audio_bitrate // 1000}k[/yellow])")
257
+ set_codec_info = available_codec_info
239
258
  else:
240
- codec_info = "[cyan]copy[/cyan]"
241
- console.print(f"[bold green]Codec:[/bold green] {codec_info}")
259
+ set_codec_info = "[purple]copy[/purple]"
260
+
261
+ # Print the formatted result with "Available" and "Set" information
262
+ console.print(
263
+ f"[bold cyan]Codec →[/bold cyan] [green]Available:[/green] {available_codec_info} | "
264
+ f"[red]Set:[/red] {set_codec_info}"
265
+ )
266
+
242
267
 
243
268
  # Fix the URL if it does not include the full protocol
244
269
  if "http" not in self.m3u8_index:
@@ -486,19 +511,6 @@ class ContentJoiner:
486
511
  self.there_is_audio = len(downloaded_audio) > 0
487
512
  self.there_is_subtitle = len(downloaded_subtitle) > 0
488
513
 
489
- if self.there_is_audio or self.there_is_subtitle:
490
-
491
- # Display the status of available media
492
- table = Table(show_header=False, box=None)
493
-
494
- table.add_row(f"[green]Video - audio", f"[yellow]{self.there_is_audio}")
495
- table.add_row(f"[green]Video - Subtitle", f"[yellow]{self.there_is_subtitle}")
496
-
497
- print("")
498
- console.rule("[bold green] JOIN ", style="bold red")
499
- console.print(table)
500
- print("")
501
-
502
514
  # Start the joining process
503
515
  self.conversione()
504
516
 
@@ -584,10 +596,6 @@ class ContentJoiner:
584
596
  # Check if the joined video file already exists
585
597
  if not os.path.exists(path_join_video):
586
598
 
587
- # Set codec to None if not defined in class
588
- #if not hasattr(self, 'codec'):
589
- # self.codec = None
590
-
591
599
  # Join the video segments into a single video file
592
600
  join_video(
593
601
  video_path=self.downloaded_video[0].get('path'),
@@ -844,7 +852,7 @@ class HLS_Downloader:
844
852
  f"[bold green]Download completed![/bold green]\n"
845
853
  f"[cyan]File size: [bold red]{formatted_size}[/bold red]\n"
846
854
  f"[cyan]Duration: [bold]{formatted_duration}[/bold]\n"
847
- f"[cyan]Output: [bold]{self.output_filename}[/bold]"
855
+ f"[cyan]Output: [bold]{os.path.abspath(self.output_filename)}[/bold]"
848
856
  )
849
857
 
850
858
  if missing_ts:
@@ -432,7 +432,7 @@ class M3U8_Segments:
432
432
  if "audio" in str(type):
433
433
  TQDM_MAX_WORKER = AUDIO_WORKERS
434
434
 
435
- console.print(f"[cyan]Video workers[white]: [green]{VIDEO_WORKERS} [white]| [cyan]Audio workers[white]: [green]{AUDIO_WORKERS}")
435
+ #console.print(f"[cyan]Video workers[white]: [green]{VIDEO_WORKERS} [white]| [cyan]Audio workers[white]: [green]{AUDIO_WORKERS}")
436
436
 
437
437
  # Custom bar for mobile and pc
438
438
  if TQDM_USE_LARGE_BAR:
@@ -544,18 +544,16 @@ class M3U8_Segments:
544
544
  file_size = os.path.getsize(self.tmp_file_path)
545
545
  if file_size == 0:
546
546
  raise Exception("Output file is empty")
547
-
548
- # Get expected time
549
- ex_hours, ex_minutes, ex_seconds = format_duration(self.expected_real_time_s)
550
- ex_formatted_duration = f"[yellow]{int(ex_hours)}[red]h [yellow]{int(ex_minutes)}[red]m [yellow]{int(ex_seconds)}[red]s"
551
- 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")
552
547
 
548
+ # Display additional
553
549
  if self.info_nRetry >= len(self.segments) * (1/3.33):
554
- console.print(
555
- "[yellow]⚠ Warning:[/yellow] Too many retries detected! "
556
- "Consider reducing the number of [cyan]workers[/cyan] in the [magenta]config.json[/magenta] file. "
557
- "This will impact [bold]performance[/bold]. \n"
558
- )
550
+
551
+ # Get expected time
552
+ ex_hours, ex_minutes, ex_seconds = format_duration(self.expected_real_time_s)
553
+ ex_formatted_duration = f"[yellow]{int(ex_hours)}[red]h [yellow]{int(ex_minutes)}[red]m [yellow]{int(ex_seconds)}[red]s"
554
+ 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
+
556
+ 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")
559
557
 
560
558
  # Info to return
561
559
  return {'type': type, 'nFailed': self.info_nFailed}
@@ -59,7 +59,7 @@ def capture_output(process: subprocess.Popen, description: str) -> None:
59
59
 
60
60
 
61
61
  # Construct the progress string with formatted output information
62
- progress_string = (f"[yellow][FFmpeg] [white][{description}[white]]: "
62
+ progress_string = (f" {description}[white]: "
63
63
  f"([green]'speed': [yellow]{data.get('speed', 'N/A')}[white], "
64
64
  f"[green]'size': [yellow]{internet_manager.format_file_size(byte_size)}[white])")
65
65
  max_length = max(max_length, len(progress_string))
@@ -208,7 +208,7 @@ def is_png_format_or_codec(file_info):
208
208
  if not file_info:
209
209
  return False
210
210
 
211
- console.print(f"[yellow][FFmpeg] [cyan]Avaiable codec[white]: [red]{file_info['codec_names']}")
211
+ #console.print(f"[yellow][FFmpeg] [cyan]Avaiable codec[white]: [red]{file_info['codec_names']}")
212
212
  return file_info['format_name'] == 'png_pipe' or 'png' in file_info['codec_names']
213
213
 
214
214
 
@@ -17,7 +17,7 @@ crypto_installed = crypto_spec is not None
17
17
 
18
18
 
19
19
  if crypto_installed:
20
- console.print("[cyan]Decrypy use: Cryptodomex")
20
+ logging.info("[cyan]Decrypy use: Cryptodomex")
21
21
  from Cryptodome.Cipher import AES
22
22
  from Cryptodome.Util.Padding import unpad
23
23
 
@@ -93,7 +93,7 @@ else:
93
93
  # Check if openssl command is available
94
94
  try:
95
95
  openssl_available = subprocess.run(["openssl", "version"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode == 0
96
- console.print("[cyan]Decrypy use: OPENSSL")
96
+ logging.info("[cyan]Decrypy use: OPENSSL")
97
97
  except:
98
98
  openssl_available = False
99
99