StreamingCommunity 3.2.5__py3-none-any.whl → 3.2.7__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/Site/altadefinizione/film.py +2 -2
- StreamingCommunity/Api/Site/altadefinizione/series.py +1 -1
- StreamingCommunity/Api/Site/animeunity/serie.py +1 -1
- StreamingCommunity/Api/Site/animeworld/film.py +1 -1
- StreamingCommunity/Api/Site/animeworld/serie.py +1 -2
- StreamingCommunity/Api/Site/cb01new/film.py +1 -1
- StreamingCommunity/Api/Site/crunchyroll/film.py +3 -4
- StreamingCommunity/Api/Site/crunchyroll/series.py +10 -6
- StreamingCommunity/Api/Site/crunchyroll/util/ScrapeSerie.py +20 -0
- StreamingCommunity/Api/Site/guardaserie/series.py +1 -2
- StreamingCommunity/Api/Site/mediasetinfinity/film.py +12 -3
- StreamingCommunity/Api/Site/mediasetinfinity/series.py +14 -6
- StreamingCommunity/Api/Site/mediasetinfinity/util/get_license.py +1 -4
- StreamingCommunity/Api/Site/raiplay/film.py +2 -2
- StreamingCommunity/Api/Site/raiplay/series.py +2 -1
- StreamingCommunity/Api/Site/streamingcommunity/film.py +1 -1
- StreamingCommunity/Api/Site/streamingcommunity/series.py +2 -2
- StreamingCommunity/Api/Site/streamingwatch/film.py +1 -1
- StreamingCommunity/Lib/Downloader/DASH/downloader.py +13 -15
- StreamingCommunity/Lib/Downloader/DASH/parser.py +1 -1
- StreamingCommunity/Lib/Downloader/HLS/downloader.py +9 -16
- StreamingCommunity/Lib/Downloader/HLS/segments.py +143 -260
- StreamingCommunity/TelegramHelp/config.json +0 -2
- StreamingCommunity/Upload/version.py +1 -1
- StreamingCommunity/Util/bento4_installer.py +191 -0
- StreamingCommunity/Util/config_json.py +1 -1
- StreamingCommunity/Util/headers.py +0 -3
- StreamingCommunity/Util/os.py +15 -46
- StreamingCommunity/__init__.py +2 -1
- StreamingCommunity/run.py +11 -10
- {streamingcommunity-3.2.5.dist-info → streamingcommunity-3.2.7.dist-info}/METADATA +4 -8
- {streamingcommunity-3.2.5.dist-info → streamingcommunity-3.2.7.dist-info}/RECORD +36 -35
- {streamingcommunity-3.2.5.dist-info → streamingcommunity-3.2.7.dist-info}/WHEEL +0 -0
- {streamingcommunity-3.2.5.dist-info → streamingcommunity-3.2.7.dist-info}/entry_points.txt +0 -0
- {streamingcommunity-3.2.5.dist-info → streamingcommunity-3.2.7.dist-info}/licenses/LICENSE +0 -0
- {streamingcommunity-3.2.5.dist-info → streamingcommunity-3.2.7.dist-info}/top_level.txt +0 -0
|
@@ -12,10 +12,9 @@ from rich.console import Console
|
|
|
12
12
|
|
|
13
13
|
# Internal utilities
|
|
14
14
|
from StreamingCommunity.Util.os import os_manager
|
|
15
|
-
from StreamingCommunity.Util.message import start_message
|
|
16
15
|
from StreamingCommunity.Util.headers import get_headers
|
|
16
|
+
from StreamingCommunity.Util.message import start_message
|
|
17
17
|
from StreamingCommunity.Util.config_json import config_manager
|
|
18
|
-
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
|
19
18
|
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance, TelegramSession
|
|
20
19
|
|
|
21
20
|
|
|
@@ -25,6 +24,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
25
24
|
|
|
26
25
|
|
|
27
26
|
# Player
|
|
27
|
+
from StreamingCommunity import HLS_Downloader
|
|
28
28
|
from StreamingCommunity.Api.Player.supervideo import VideoSource
|
|
29
29
|
|
|
30
30
|
|
|
@@ -11,7 +11,6 @@ from rich.prompt import Prompt
|
|
|
11
11
|
|
|
12
12
|
# Internal utilities
|
|
13
13
|
from StreamingCommunity.Util.message import start_message
|
|
14
|
-
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
|
15
14
|
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance, TelegramSession
|
|
16
15
|
|
|
17
16
|
|
|
@@ -29,6 +28,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
29
28
|
|
|
30
29
|
|
|
31
30
|
# Player
|
|
31
|
+
from StreamingCommunity import HLS_Downloader
|
|
32
32
|
from StreamingCommunity.Api.Player.supervideo import VideoSource
|
|
33
33
|
|
|
34
34
|
|
|
@@ -12,7 +12,6 @@ from rich.prompt import Prompt
|
|
|
12
12
|
# Internal utilities
|
|
13
13
|
from StreamingCommunity.Util.os import os_manager
|
|
14
14
|
from StreamingCommunity.Util.message import start_message
|
|
15
|
-
from StreamingCommunity.Lib.Downloader import MP4_downloader
|
|
16
15
|
from StreamingCommunity.TelegramHelp.telegram_bot import TelegramSession, get_bot_instance
|
|
17
16
|
|
|
18
17
|
|
|
@@ -24,6 +23,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
24
23
|
|
|
25
24
|
|
|
26
25
|
# Player
|
|
26
|
+
from StreamingCommunity import MP4_downloader
|
|
27
27
|
from StreamingCommunity.Api.Player.vixcloud import VideoSourceAnime
|
|
28
28
|
|
|
29
29
|
|
|
@@ -9,7 +9,6 @@ from rich.console import Console
|
|
|
9
9
|
# Internal utilities
|
|
10
10
|
from StreamingCommunity.Util.os import os_manager
|
|
11
11
|
from StreamingCommunity.Util.message import start_message
|
|
12
|
-
from StreamingCommunity.Lib.Downloader import MP4_downloader
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
# Logic class
|
|
@@ -19,6 +18,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
19
18
|
|
|
20
19
|
|
|
21
20
|
# Player
|
|
21
|
+
from StreamingCommunity import MP4_downloader
|
|
22
22
|
from StreamingCommunity.Api.Player.sweetpixel import VideoSource
|
|
23
23
|
|
|
24
24
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# 11.03.24
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
-
import logging
|
|
5
4
|
from typing import Tuple
|
|
6
5
|
|
|
7
6
|
|
|
@@ -13,7 +12,6 @@ from rich.prompt import Prompt
|
|
|
13
12
|
# Internal utilities
|
|
14
13
|
from StreamingCommunity.Util.os import os_manager
|
|
15
14
|
from StreamingCommunity.Util.message import start_message
|
|
16
|
-
from StreamingCommunity.Lib.Downloader import MP4_downloader
|
|
17
15
|
|
|
18
16
|
|
|
19
17
|
# Logic class
|
|
@@ -24,6 +22,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
24
22
|
|
|
25
23
|
|
|
26
24
|
# Player
|
|
25
|
+
from StreamingCommunity import MP4_downloader
|
|
27
26
|
from StreamingCommunity.Api.Player.sweetpixel import VideoSource
|
|
28
27
|
|
|
29
28
|
|
|
@@ -10,7 +10,6 @@ from rich.console import Console
|
|
|
10
10
|
# Internal utilities
|
|
11
11
|
from StreamingCommunity.Util.os import os_manager
|
|
12
12
|
from StreamingCommunity.Util.message import start_message
|
|
13
|
-
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
|
14
13
|
|
|
15
14
|
|
|
16
15
|
# Logic class
|
|
@@ -19,6 +18,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
19
18
|
|
|
20
19
|
|
|
21
20
|
# Player
|
|
21
|
+
from StreamingCommunity import HLS_Downloader
|
|
22
22
|
from StreamingCommunity.Api.Player.maxstream import VideoSource
|
|
23
23
|
|
|
24
24
|
|
|
@@ -9,11 +9,9 @@ from rich.console import Console
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
# Internal utilities
|
|
12
|
-
from StreamingCommunity.Util.os import os_manager
|
|
13
12
|
from StreamingCommunity.Util.message import start_message
|
|
14
13
|
from StreamingCommunity.Util.config_json import config_manager
|
|
15
|
-
from StreamingCommunity.Util.os import get_wvd_path
|
|
16
|
-
from StreamingCommunity.Lib.Downloader.DASH.downloader import DASH_Download
|
|
14
|
+
from StreamingCommunity.Util.os import os_manager, get_wvd_path
|
|
17
15
|
|
|
18
16
|
|
|
19
17
|
# Logic class
|
|
@@ -22,6 +20,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
22
20
|
|
|
23
21
|
|
|
24
22
|
# Player
|
|
23
|
+
from StreamingCommunity import DASH_Downloader
|
|
25
24
|
from .util.get_license import get_playback_session, get_auth_token, generate_device_id
|
|
26
25
|
|
|
27
26
|
|
|
@@ -55,7 +54,7 @@ def download_film(select_title: MediaItem) -> str:
|
|
|
55
54
|
query_params = parse_qs(parsed_url.query)
|
|
56
55
|
|
|
57
56
|
# Download the episode
|
|
58
|
-
r_proc =
|
|
57
|
+
r_proc = DASH_Downloader(
|
|
59
58
|
cdm_device=get_wvd_path(),
|
|
60
59
|
license_url='https://www.crunchyroll.com/license/v1/license/widevine',
|
|
61
60
|
mpd_url=mpd_url,
|
|
@@ -12,13 +12,11 @@ from rich.prompt import Prompt
|
|
|
12
12
|
|
|
13
13
|
# Internal utilities
|
|
14
14
|
from StreamingCommunity.Util.message import start_message
|
|
15
|
-
from StreamingCommunity.Util.os import os_manager
|
|
16
|
-
from StreamingCommunity.Util.os import get_wvd_path
|
|
17
|
-
from StreamingCommunity.Lib.Downloader.DASH.downloader import DASH_Download
|
|
15
|
+
from StreamingCommunity.Util.os import os_manager, get_wvd_path
|
|
18
16
|
|
|
19
17
|
|
|
20
18
|
# Logic class
|
|
21
|
-
from .util.ScrapeSerie import GetSerieInfo
|
|
19
|
+
from .util.ScrapeSerie import GetSerieInfo, delete_stream_episode
|
|
22
20
|
from StreamingCommunity.Api.Template.Util import (
|
|
23
21
|
manage_selection,
|
|
24
22
|
map_episode_title,
|
|
@@ -31,6 +29,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
31
29
|
|
|
32
30
|
|
|
33
31
|
# Player
|
|
32
|
+
from StreamingCommunity import DASH_Downloader
|
|
34
33
|
from .util.get_license import get_playback_session, get_auth_token, generate_device_id
|
|
35
34
|
|
|
36
35
|
|
|
@@ -65,12 +64,14 @@ def download_video(index_season_selected: int, index_episode_selected: int, scra
|
|
|
65
64
|
# Generate mpd and license URLs
|
|
66
65
|
url_id = obj_episode.get('url').split('/')[-1]
|
|
67
66
|
device_id = generate_device_id()
|
|
68
|
-
|
|
67
|
+
token_mpd = get_auth_token(device_id)
|
|
68
|
+
|
|
69
|
+
mpd_url, mpd_headers = get_playback_session(token_mpd, device_id, url_id)
|
|
69
70
|
parsed_url = urlparse(mpd_url)
|
|
70
71
|
query_params = parse_qs(parsed_url.query)
|
|
71
72
|
|
|
72
73
|
# Download the episode
|
|
73
|
-
r_proc =
|
|
74
|
+
r_proc = DASH_Downloader(
|
|
74
75
|
cdm_device=get_wvd_path(),
|
|
75
76
|
license_url='https://www.crunchyroll.com/license/v1/license/widevine',
|
|
76
77
|
mpd_url=mpd_url,
|
|
@@ -95,6 +96,9 @@ def download_video(index_season_selected: int, index_episode_selected: int, scra
|
|
|
95
96
|
try: os.remove(status['path'])
|
|
96
97
|
except Exception: pass
|
|
97
98
|
|
|
99
|
+
# Delete episode stream
|
|
100
|
+
delete_stream_episode(url_id, query_params['playbackGuid'][0], mpd_headers)
|
|
101
|
+
|
|
98
102
|
return status['path'], status['stopped']
|
|
99
103
|
|
|
100
104
|
def download_episode(index_season_selected: int, scrape_serie: GetSerieInfo, download_all: bool = False, episode_selection: str = None) -> None:
|
|
@@ -45,6 +45,26 @@ def get_season_episodes(season_id, headers, params):
|
|
|
45
45
|
)
|
|
46
46
|
return response
|
|
47
47
|
|
|
48
|
+
def delete_stream_episode(episode_id, stream_id, headers):
|
|
49
|
+
"""
|
|
50
|
+
Deletes a specific stream episode by episode ID and stream ID.
|
|
51
|
+
"""
|
|
52
|
+
url = f'https://www.crunchyroll.com/playback/v1/token/{episode_id}/{stream_id}'
|
|
53
|
+
headers = get_headers()
|
|
54
|
+
|
|
55
|
+
response = requests.delete(
|
|
56
|
+
url,
|
|
57
|
+
headers=headers,
|
|
58
|
+
impersonate="chrome110"
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
if response.status_code == 204:
|
|
62
|
+
return True
|
|
63
|
+
|
|
64
|
+
else:
|
|
65
|
+
logging.error(f"Failed to delete stream episode: {response.status_code} - {response.text}")
|
|
66
|
+
return False
|
|
67
|
+
|
|
48
68
|
|
|
49
69
|
class GetSerieInfo:
|
|
50
70
|
def __init__(self, series_id):
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# 13.06.24
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
-
import logging
|
|
5
4
|
from typing import Tuple
|
|
6
5
|
|
|
7
6
|
|
|
@@ -12,7 +11,6 @@ from rich.prompt import Prompt
|
|
|
12
11
|
|
|
13
12
|
# Internal utilities
|
|
14
13
|
from StreamingCommunity.Util.message import start_message
|
|
15
|
-
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
|
16
14
|
|
|
17
15
|
|
|
18
16
|
# Logic class
|
|
@@ -30,6 +28,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
30
28
|
|
|
31
29
|
# Player
|
|
32
30
|
from .util.ScrapeSerie import GetSerieInfo
|
|
31
|
+
from StreamingCommunity import HLS_Downloader
|
|
33
32
|
from StreamingCommunity.Api.Player.supervideo import VideoSource
|
|
34
33
|
|
|
35
34
|
|
|
@@ -12,7 +12,6 @@ from rich.console import Console
|
|
|
12
12
|
from StreamingCommunity.Util.os import os_manager, get_wvd_path
|
|
13
13
|
from StreamingCommunity.Util.message import start_message
|
|
14
14
|
from StreamingCommunity.Util.headers import get_headers
|
|
15
|
-
from StreamingCommunity.Lib.Downloader.DASH.downloader import DASH_Download
|
|
16
15
|
|
|
17
16
|
|
|
18
17
|
# Logic class
|
|
@@ -22,6 +21,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
22
21
|
|
|
23
22
|
# Player
|
|
24
23
|
from .util.fix_mpd import get_manifest
|
|
24
|
+
from StreamingCommunity import DASH_Downloader
|
|
25
25
|
from .util.get_license import get_bearer_token, get_playback_url, get_tracking_info, generate_license_url
|
|
26
26
|
|
|
27
27
|
|
|
@@ -48,14 +48,23 @@ def download_film(select_title: MediaItem) -> Tuple[str, bool]:
|
|
|
48
48
|
|
|
49
49
|
# Generate mpd and license URLs
|
|
50
50
|
bearer = get_bearer_token()
|
|
51
|
-
|
|
51
|
+
|
|
52
|
+
# Extract ID from the episode URL
|
|
53
|
+
episode_id = select_title.url.split('_')[-1]
|
|
54
|
+
if "http" in episode_id:
|
|
55
|
+
try: episode_id = select_title.url.split('/')[-1]
|
|
56
|
+
except Exception:
|
|
57
|
+
console.print(f"[red]Error:[/red] Failed to parse episode ID from URL: {select_title.url}")
|
|
58
|
+
return None, True
|
|
59
|
+
|
|
60
|
+
playback_json = get_playback_url(bearer, episode_id)
|
|
52
61
|
tracking_info = get_tracking_info(bearer, playback_json)[0]
|
|
53
62
|
|
|
54
63
|
license_url = generate_license_url(bearer, tracking_info)
|
|
55
64
|
mpd_url = get_manifest(tracking_info['video_src'])
|
|
56
65
|
|
|
57
66
|
# Download the episode
|
|
58
|
-
r_proc =
|
|
67
|
+
r_proc = DASH_Downloader(
|
|
59
68
|
cdm_device=get_wvd_path(),
|
|
60
69
|
license_url=license_url,
|
|
61
70
|
mpd_url=mpd_url,
|
|
@@ -10,11 +10,9 @@ from rich.prompt import Prompt
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
# Internal utilities
|
|
13
|
-
from StreamingCommunity.Util.message import start_message
|
|
14
|
-
from StreamingCommunity.Util.os import os_manager
|
|
15
13
|
from StreamingCommunity.Util.headers import get_headers
|
|
16
|
-
from StreamingCommunity.Util.
|
|
17
|
-
from StreamingCommunity.
|
|
14
|
+
from StreamingCommunity.Util.message import start_message
|
|
15
|
+
from StreamingCommunity.Util.os import os_manager, get_wvd_path
|
|
18
16
|
|
|
19
17
|
|
|
20
18
|
# Logic class
|
|
@@ -32,6 +30,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
32
30
|
|
|
33
31
|
# Player
|
|
34
32
|
from .util.fix_mpd import get_manifest
|
|
33
|
+
from StreamingCommunity import DASH_Downloader
|
|
35
34
|
from .util.get_license import get_bearer_token, get_playback_url, get_tracking_info, generate_license_url
|
|
36
35
|
|
|
37
36
|
|
|
@@ -65,14 +64,23 @@ def download_video(index_season_selected: int, index_episode_selected: int, scra
|
|
|
65
64
|
|
|
66
65
|
# Generate mpd and license URLs
|
|
67
66
|
bearer = get_bearer_token()
|
|
68
|
-
|
|
67
|
+
|
|
68
|
+
# Extract ID from the episode URL
|
|
69
|
+
episode_id = obj_episode.url.split('_')[-1]
|
|
70
|
+
if "http" in episode_id:
|
|
71
|
+
try: episode_id = obj_episode.url.split('/')[-1]
|
|
72
|
+
except Exception:
|
|
73
|
+
console.print(f"[red]Error:[/red] Failed to parse episode ID from URL: {obj_episode.url}")
|
|
74
|
+
return None, True
|
|
75
|
+
|
|
76
|
+
playback_json = get_playback_url(bearer, episode_id)
|
|
69
77
|
tracking_info = get_tracking_info(bearer, playback_json)[0]
|
|
70
78
|
|
|
71
79
|
license_url = generate_license_url(bearer, tracking_info)
|
|
72
80
|
mpd_url = get_manifest(tracking_info['video_src'])
|
|
73
81
|
|
|
74
82
|
# Download the episode
|
|
75
|
-
r_proc =
|
|
83
|
+
r_proc = DASH_Downloader(
|
|
76
84
|
cdm_device=get_wvd_path(),
|
|
77
85
|
license_url=license_url,
|
|
78
86
|
mpd_url=mpd_url,
|
|
@@ -71,10 +71,7 @@ def get_playback_url(BEARER_TOKEN, CONTENT_ID):
|
|
|
71
71
|
|
|
72
72
|
json_data = {
|
|
73
73
|
'contentId': CONTENT_ID,
|
|
74
|
-
'streamType': 'VOD'
|
|
75
|
-
'delivery': 'Streaming',
|
|
76
|
-
'createDevice': True,
|
|
77
|
-
'overrideAppName': 'web//mediasetplay-web/5.11.8-f16d93c',
|
|
74
|
+
'streamType': 'VOD'
|
|
78
75
|
}
|
|
79
76
|
|
|
80
77
|
try:
|
|
@@ -11,9 +11,8 @@ from rich.console import Console
|
|
|
11
11
|
|
|
12
12
|
# Internal utilities
|
|
13
13
|
from StreamingCommunity.Util.os import os_manager
|
|
14
|
-
from StreamingCommunity.Util.message import start_message
|
|
15
|
-
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
|
16
14
|
from StreamingCommunity.Util.headers import get_headers
|
|
15
|
+
from StreamingCommunity.Util.message import start_message
|
|
17
16
|
|
|
18
17
|
|
|
19
18
|
# Logic class
|
|
@@ -22,6 +21,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
22
21
|
|
|
23
22
|
|
|
24
23
|
# Player
|
|
24
|
+
from StreamingCommunity import HLS_Downloader
|
|
25
25
|
from StreamingCommunity.Api.Player.mediapolisvod import VideoSource
|
|
26
26
|
|
|
27
27
|
|
|
@@ -11,7 +11,7 @@ from rich.prompt import Prompt
|
|
|
11
11
|
|
|
12
12
|
# Internal utilities
|
|
13
13
|
from StreamingCommunity.Util.message import start_message
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
|
|
16
16
|
# Logic class
|
|
17
17
|
from .util.ScrapeSerie import GetSerieInfo
|
|
@@ -27,6 +27,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
# Player
|
|
30
|
+
from StreamingCommunity import HLS_Downloader
|
|
30
31
|
from StreamingCommunity.Api.Player.mediapolisvod import VideoSource
|
|
31
32
|
|
|
32
33
|
|
|
@@ -10,7 +10,6 @@ from rich.console import Console
|
|
|
10
10
|
# Internal utilities
|
|
11
11
|
from StreamingCommunity.Util.os import os_manager
|
|
12
12
|
from StreamingCommunity.Util.message import start_message
|
|
13
|
-
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
|
14
13
|
from StreamingCommunity.TelegramHelp.telegram_bot import TelegramSession, get_bot_instance
|
|
15
14
|
|
|
16
15
|
|
|
@@ -20,6 +19,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
20
19
|
|
|
21
20
|
|
|
22
21
|
# Player
|
|
22
|
+
from StreamingCommunity import HLS_Downloader
|
|
23
23
|
from StreamingCommunity.Api.Player.vixcloud import VideoSource
|
|
24
24
|
|
|
25
25
|
|
|
@@ -11,15 +11,14 @@ from rich.prompt import Prompt
|
|
|
11
11
|
|
|
12
12
|
# Internal utilities
|
|
13
13
|
from StreamingCommunity.Util.message import start_message
|
|
14
|
-
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
|
15
14
|
from StreamingCommunity.TelegramHelp.telegram_bot import TelegramSession, get_bot_instance
|
|
16
15
|
|
|
16
|
+
|
|
17
17
|
# Logic class
|
|
18
18
|
from .util.ScrapeSerie import GetSerieInfo
|
|
19
19
|
from StreamingCommunity.Api.Template.Util import (
|
|
20
20
|
manage_selection,
|
|
21
21
|
map_episode_title,
|
|
22
|
-
dynamic_format_number,
|
|
23
22
|
validate_selection,
|
|
24
23
|
validate_episode_selection,
|
|
25
24
|
display_episodes_list
|
|
@@ -29,6 +28,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
29
28
|
|
|
30
29
|
|
|
31
30
|
# Player
|
|
31
|
+
from StreamingCommunity import HLS_Downloader
|
|
32
32
|
from StreamingCommunity.Api.Player.vixcloud import VideoSource
|
|
33
33
|
|
|
34
34
|
|
|
@@ -10,7 +10,6 @@ from rich.console import Console
|
|
|
10
10
|
# Internal utilities
|
|
11
11
|
from StreamingCommunity.Util.os import os_manager
|
|
12
12
|
from StreamingCommunity.Util.message import start_message
|
|
13
|
-
from StreamingCommunity.Lib.Downloader import HLS_Downloader
|
|
14
13
|
|
|
15
14
|
|
|
16
15
|
# Logic class
|
|
@@ -19,6 +18,7 @@ from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
|
19
18
|
|
|
20
19
|
|
|
21
20
|
# Player
|
|
21
|
+
from StreamingCommunity import HLS_Downloader
|
|
22
22
|
from StreamingCommunity.Api.Player.hdplayer import VideoSource
|
|
23
23
|
|
|
24
24
|
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
import shutil
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# External libraries
|
|
5
8
|
from rich.console import Console
|
|
6
9
|
|
|
7
10
|
|
|
8
11
|
# Internal utilities
|
|
9
12
|
from StreamingCommunity.Util.config_json import config_manager
|
|
10
|
-
from StreamingCommunity.Util.os import os_manager
|
|
11
13
|
from StreamingCommunity.Lib.FFmpeg.command import join_audios, join_video
|
|
12
14
|
|
|
13
15
|
|
|
@@ -19,17 +21,16 @@ from .cdm_helpher import get_widevine_keys
|
|
|
19
21
|
|
|
20
22
|
|
|
21
23
|
# Config
|
|
22
|
-
ENABLE_AUDIO = config_manager.get_bool('M3U8_DOWNLOAD', 'download_audio')
|
|
23
24
|
DOWNLOAD_SPECIFIC_AUDIO = config_manager.get_list('M3U8_DOWNLOAD', 'specific_list_audio')
|
|
24
|
-
CLEANUP_TMP = config_manager.get_bool('M3U8_DOWNLOAD', 'cleanup_tmp_folder')
|
|
25
25
|
FILTER_CUSTOM_REOLUTION = str(config_manager.get('M3U8_PARSER', 'force_resolution')).strip().lower()
|
|
26
|
+
CLEANUP_TMP = config_manager.get_bool('M3U8_DOWNLOAD', 'cleanup_tmp_folder')
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
# Variable
|
|
29
30
|
console = Console()
|
|
30
31
|
|
|
31
32
|
|
|
32
|
-
class
|
|
33
|
+
class DASH_Downloader:
|
|
33
34
|
def __init__(self, cdm_device, license_url, mpd_url, output_path):
|
|
34
35
|
self.cdm_device = cdm_device
|
|
35
36
|
self.license_url = license_url
|
|
@@ -69,17 +70,14 @@ class DASH_Download:
|
|
|
69
70
|
)
|
|
70
71
|
self.selected_video = selected_video
|
|
71
72
|
|
|
72
|
-
# Audio info
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
self.selected_audio = selected_audio
|
|
81
|
-
else:
|
|
82
|
-
self.selected_audio = None
|
|
73
|
+
# Audio info
|
|
74
|
+
selected_audio, list_available_audio_langs, filter_custom_audio, downloadable_audio = self.parser.select_audio(DOWNLOAD_SPECIFIC_AUDIO)
|
|
75
|
+
console.print(
|
|
76
|
+
f"[cyan bold]Audio [/cyan bold] [green]Available:[/green] [purple]{', '.join(list_available_audio_langs)}[/purple] | "
|
|
77
|
+
f"[red]Set:[/red] [purple]{filter_custom_audio}[/purple] | "
|
|
78
|
+
f"[yellow]Downloadable:[/yellow] [purple]{downloadable_audio}[/purple]"
|
|
79
|
+
)
|
|
80
|
+
self.selected_audio = selected_audio
|
|
83
81
|
|
|
84
82
|
def get_representation_by_type(self, typ):
|
|
85
83
|
if typ == "video":
|
|
@@ -61,7 +61,7 @@ class MPDParser:
|
|
|
61
61
|
self.base_url = mpd_url.rsplit('/', 1)[0] + '/'
|
|
62
62
|
|
|
63
63
|
def parse(self, custom_headers):
|
|
64
|
-
response = httpx.get(self.mpd_url, headers=custom_headers, timeout=max_timeout
|
|
64
|
+
response = httpx.get(self.mpd_url, headers=custom_headers, timeout=max_timeout)
|
|
65
65
|
response.raise_for_status()
|
|
66
66
|
|
|
67
67
|
root = ET.fromstring(response.content)
|
|
@@ -17,7 +17,7 @@ from rich.panel import Panel
|
|
|
17
17
|
# Internal utilities
|
|
18
18
|
from StreamingCommunity.Util.config_json import config_manager
|
|
19
19
|
from StreamingCommunity.Util.headers import get_userAgent
|
|
20
|
-
from StreamingCommunity.Util.os import
|
|
20
|
+
from StreamingCommunity.Util.os import os_manager, internet_manager
|
|
21
21
|
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
|
|
22
22
|
|
|
23
23
|
|
|
@@ -33,11 +33,9 @@ from .segments import M3U8_Segments
|
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
# Config
|
|
36
|
-
ENABLE_AUDIO = config_manager.get_bool('M3U8_DOWNLOAD', 'download_audio')
|
|
37
36
|
ENABLE_SUBTITLE = config_manager.get_bool('M3U8_DOWNLOAD', 'download_subtitle')
|
|
38
37
|
DOWNLOAD_SPECIFIC_AUDIO = config_manager.get_list('M3U8_DOWNLOAD', 'specific_list_audio')
|
|
39
38
|
DOWNLOAD_SPECIFIC_SUBTITLE = config_manager.get_list('M3U8_DOWNLOAD', 'specific_list_subtitles')
|
|
40
|
-
MERGE_AUDIO = config_manager.get_bool('M3U8_DOWNLOAD', 'merge_audio')
|
|
41
39
|
MERGE_SUBTITLE = config_manager.get_bool('M3U8_DOWNLOAD', 'merge_subs')
|
|
42
40
|
CLEANUP_TMP = config_manager.get_bool('M3U8_DOWNLOAD', 'cleanup_tmp_folder')
|
|
43
41
|
FILTER_CUSTOM_REOLUTION = str(config_manager.get('M3U8_PARSER', 'force_resolution')).strip().lower()
|
|
@@ -65,6 +63,7 @@ class HLSClient:
|
|
|
65
63
|
Response content/text or None if all retries fail
|
|
66
64
|
"""
|
|
67
65
|
client = httpx.Client(headers=self.headers, timeout=MAX_TIMEOUT, follow_redirects=True)
|
|
66
|
+
|
|
68
67
|
for attempt in range(RETRY_LIMIT):
|
|
69
68
|
try:
|
|
70
69
|
response = client.get(url)
|
|
@@ -95,11 +94,6 @@ class PathManager:
|
|
|
95
94
|
Ensures output path is valid and follows expected format.
|
|
96
95
|
Creates a hash-based filename if no path is provided.
|
|
97
96
|
"""
|
|
98
|
-
if not path:
|
|
99
|
-
root = config_manager.get('OUT_FOLDER', 'root_path')
|
|
100
|
-
hash_name = compute_sha1_hash(self.m3u8_url) + ".mp4"
|
|
101
|
-
return os.path.join(root, "undefined", hash_name)
|
|
102
|
-
|
|
103
97
|
if not path.endswith(".mp4"):
|
|
104
98
|
path += ".mp4"
|
|
105
99
|
|
|
@@ -171,12 +165,11 @@ class M3U8Manager:
|
|
|
171
165
|
logging.error("Resolution not recognized.")
|
|
172
166
|
self.video_url, self.video_res = self.parser._video.get_best_uri()
|
|
173
167
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
self.
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
]
|
|
168
|
+
# Audio info
|
|
169
|
+
self.audio_streams = [
|
|
170
|
+
s for s in (self.parser._audio.get_all_uris_and_names() or [])
|
|
171
|
+
if s.get('language') in DOWNLOAD_SPECIFIC_AUDIO
|
|
172
|
+
]
|
|
180
173
|
|
|
181
174
|
self.sub_streams = []
|
|
182
175
|
if ENABLE_SUBTITLE:
|
|
@@ -308,8 +301,8 @@ class DownloadManager:
|
|
|
308
301
|
Downloads all selected streams (video, audio, subtitles).
|
|
309
302
|
"""
|
|
310
303
|
return_stopped = False
|
|
311
|
-
|
|
312
304
|
video_file = os.path.join(self.temp_dir, 'video', '0.ts')
|
|
305
|
+
|
|
313
306
|
if not os.path.exists(video_file):
|
|
314
307
|
if self.download_video(video_url):
|
|
315
308
|
if not return_stopped:
|
|
@@ -374,7 +367,7 @@ class MergeManager:
|
|
|
374
367
|
)
|
|
375
368
|
|
|
376
369
|
else:
|
|
377
|
-
if
|
|
370
|
+
if self.audio_streams:
|
|
378
371
|
audio_tracks = [{
|
|
379
372
|
'path': os.path.join(self.temp_dir, 'audio', a['language'], '0.ts'),
|
|
380
373
|
'name': a['language']
|