mirror of
https://github.com/Arrowar/StreamingCommunity.git
synced 2025-06-07 20:15:24 +00:00
remove token headers
This commit is contained in:
parent
30bfc207a4
commit
8fda9d59ce
@ -9,15 +9,16 @@ import requests
|
|||||||
import sys
|
import sys
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
|
||||||
|
# Class import
|
||||||
from Src.Lib.FFmpeg.my_m3u8 import download_m3u8
|
from Src.Lib.FFmpeg.my_m3u8 import download_m3u8
|
||||||
from Src.Lib.FFmpeg.util import audio_extractor_m3u8
|
from Src.Lib.FFmpeg.util import audio_extractor_m3u8
|
||||||
from Src.Util.config import config
|
from Src.Util.config import config
|
||||||
from Src.Util.console import console
|
from Src.Util.console import console
|
||||||
# Class import
|
|
||||||
from Src.Util.headers import get_headers
|
from Src.Util.headers import get_headers
|
||||||
|
|
||||||
|
|
||||||
# [func]
|
|
||||||
def get_iframe(id_title, domain):
|
def get_iframe(id_title, domain):
|
||||||
req = requests.get(url=f"https://streamingcommunity.{domain}/iframe/{id_title}", headers={
|
req = requests.get(url=f"https://streamingcommunity.{domain}/iframe/{id_title}", headers={
|
||||||
"User-agent": get_headers()
|
"User-agent": get_headers()
|
||||||
@ -72,10 +73,8 @@ def get_playlist(json_win_video, json_win_param, render_quality):
|
|||||||
token_render = f"token{render_quality}"
|
token_render = f"token{render_quality}"
|
||||||
return f"https://vixcloud.co/playlist/{json_win_video['id']}?token={json_win_param['token']}&{token_render}={json_win_param[token_render]}&expires={json_win_param['expires']}"
|
return f"https://vixcloud.co/playlist/{json_win_video['id']}?token={json_win_param['token']}&{token_render}={json_win_param[token_render]}&expires={json_win_param['expires']}"
|
||||||
|
|
||||||
def get_m3u8_key(json_win_video, json_win_param, title_name, token_render):
|
def get_m3u8_key():
|
||||||
response = requests.get('https://vixcloud.co/storage/enc.key', headers={
|
response = requests.get('https://vixcloud.co/storage/enc.key')
|
||||||
'referer': f'https://vixcloud.co/embed/{json_win_video["id"]}?token={json_win_param[token_render]}&title={title_name}&referer=1&expires={json_win_param["expires"]}',
|
|
||||||
})
|
|
||||||
|
|
||||||
if response.ok:
|
if response.ok:
|
||||||
return binascii.hexlify(response.content).decode('utf-8')
|
return binascii.hexlify(response.content).decode('utf-8')
|
||||||
@ -111,7 +110,7 @@ def main_dw_film(id_film, title_name, domain):
|
|||||||
console.print(f"[blue]Selected quality => [red]{render_quality}")
|
console.print(f"[blue]Selected quality => [red]{render_quality}")
|
||||||
|
|
||||||
m3u8_url = get_m3u8_url(json_win_video, json_win_param, render_quality)
|
m3u8_url = get_m3u8_url(json_win_video, json_win_param, render_quality)
|
||||||
m3u8_key = get_m3u8_key(json_win_video, json_win_param, title_name, token_render)
|
m3u8_key = get_m3u8_key()
|
||||||
m3u8_playlist = get_playlist(json_win_video, json_win_param, render_quality)
|
m3u8_playlist = get_playlist(json_win_video, json_win_param, render_quality)
|
||||||
|
|
||||||
mp4_name = title_name.replace("+", " ").replace(",", "").replace("-", "_")
|
mp4_name = title_name.replace("+", " ").replace(",", "").replace("-", "_")
|
||||||
@ -123,5 +122,6 @@ def main_dw_film(id_film, title_name, domain):
|
|||||||
if m3u8_url_audio is not None:
|
if m3u8_url_audio is not None:
|
||||||
console.print("[blue]Using m3u8 audio => [red]True")
|
console.print("[blue]Using m3u8 audio => [red]True")
|
||||||
subtitle_path = os.path.join(config['root_path'], config['movies_folder_name'], mp4_name)
|
subtitle_path = os.path.join(config['root_path'], config['movies_folder_name'], mp4_name)
|
||||||
|
|
||||||
download_m3u8(m3u8_index=m3u8_url, m3u8_audio=m3u8_url_audio, m3u8_subtitle=m3u8_playlist, key=m3u8_key,
|
download_m3u8(m3u8_index=m3u8_url, m3u8_audio=m3u8_url_audio, m3u8_subtitle=m3u8_playlist, key=m3u8_key,
|
||||||
output_filename=mp4_path, subtitle_folder=subtitle_path, content_name=mp4_name)
|
output_filename=mp4_path, subtitle_folder=subtitle_path, content_name=mp4_name)
|
||||||
|
@ -10,26 +10,19 @@ import sys
|
|||||||
import urllib
|
import urllib
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
# Class import
|
||||||
from Src.Lib.FFmpeg.my_m3u8 import download_m3u8
|
from Src.Lib.FFmpeg.my_m3u8 import download_m3u8
|
||||||
from Src.Lib.FFmpeg.util import audio_extractor_m3u8
|
from Src.Lib.FFmpeg.util import audio_extractor_m3u8
|
||||||
from Src.Util.config import config
|
from Src.Util.config import config
|
||||||
from Src.Util.console import console, msg
|
from Src.Util.console import console, msg
|
||||||
# Class import
|
|
||||||
from Src.Util.headers import get_headers
|
from Src.Util.headers import get_headers
|
||||||
|
|
||||||
|
|
||||||
# [func]
|
|
||||||
def get_token(id_tv, domain):
|
|
||||||
session = requests.Session()
|
|
||||||
session.get(f"https://streamingcommunity.{domain}/watch/{id_tv}")
|
|
||||||
return session.cookies['XSRF-TOKEN']
|
|
||||||
|
|
||||||
|
|
||||||
def get_info_tv(id_film, title_name, site_version, domain):
|
def get_info_tv(id_film, title_name, site_version, domain):
|
||||||
req = requests.get(f"https://streamingcommunity.{domain}/titles/{id_film}-{title_name}", headers={
|
req = requests.get(f"https://streamingcommunity.{domain}/titles/{id_film}-{title_name}", headers={
|
||||||
|
'user-agent': get_headers(),
|
||||||
'X-Inertia': 'true',
|
'X-Inertia': 'true',
|
||||||
'X-Inertia-Version': site_version,
|
'X-Inertia-Version': site_version,
|
||||||
'User-Agent': get_headers()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if req.ok:
|
if req.ok:
|
||||||
@ -39,16 +32,13 @@ def get_info_tv(id_film, title_name, site_version, domain):
|
|||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
def get_info_season(tv_id, tv_name, domain, version, token, n_season):
|
def get_info_season(tv_id, tv_name, domain, version, n_season):
|
||||||
req = requests.get(
|
req = requests.get(
|
||||||
f'https://streamingcommunity.{domain}/titles/{tv_id}-{tv_name}/stagione-{n_season}',
|
f'https://streamingcommunity.{domain}/titles/{tv_id}-{tv_name}/stagione-{n_season}',
|
||||||
headers={
|
headers={
|
||||||
'authority': f'streamingcommunity.{domain}',
|
|
||||||
'referer': f'https://streamingcommunity.broker/titles/{tv_id}-{tv_name}',
|
|
||||||
'user-agent': get_headers(),
|
'user-agent': get_headers(),
|
||||||
'x-inertia': 'true',
|
'x-inertia': 'true',
|
||||||
'x-inertia-version': version,
|
'x-inertia-version': version,
|
||||||
'x-xsrf-token': token,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if req.ok:
|
if req.ok:
|
||||||
@ -59,22 +49,11 @@ def get_info_season(tv_id, tv_name, domain, version, token, n_season):
|
|||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
def get_iframe(tv_id, ep_id, domain, token):
|
def get_iframe(tv_id, ep_id, domain):
|
||||||
req = requests.get(f'https://streamingcommunity.{domain}/iframe/{tv_id}',
|
req = requests.get(f'https://streamingcommunity.{domain}/iframe/{tv_id}',
|
||||||
params={'episode_id': ep_id, 'next_episode': '1'},
|
params={'episode_id': ep_id, 'next_episode': '1'},
|
||||||
cookies={'XSRF-TOKEN': token},
|
headers={'user-agent': get_headers()}
|
||||||
headers={
|
)
|
||||||
'referer': f'https://streamingcommunity.{domain}/watch/{tv_id}?e={ep_id}',
|
|
||||||
'user-agent': get_headers()
|
|
||||||
})
|
|
||||||
|
|
||||||
# Change user agent m3u8 (unused)
|
|
||||||
"""
|
|
||||||
custom_headers_req = {
|
|
||||||
'referer': f'https://streamingcommunity.{domain}/watch/{tv_id}?e={ep_id}',
|
|
||||||
'user-agent': get_headers()
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
if req.ok:
|
if req.ok:
|
||||||
try:
|
try:
|
||||||
@ -122,10 +101,8 @@ def get_m3u8_url(json_win_video, json_win_param, render_quality):
|
|||||||
return f"https://vixcloud.co/playlist/{json_win_video['id']}?type=video&rendition={render_quality}&token={json_win_param[token_render]}&expires={json_win_param['expires']}"
|
return f"https://vixcloud.co/playlist/{json_win_video['id']}?type=video&rendition={render_quality}&token={json_win_param[token_render]}&expires={json_win_param['expires']}"
|
||||||
|
|
||||||
|
|
||||||
def get_m3u8_key_ep(json_win_video, json_win_param, tv_name, n_season, n_ep, ep_title, token_render):
|
def get_m3u8_key_ep():
|
||||||
response = requests.get('https://vixcloud.co/storage/enc.key', headers={
|
response = requests.get('https://vixcloud.co/storage/enc.key')
|
||||||
'referer': f'https://vixcloud.co/embed/{json_win_video["id"]}?token={json_win_param[token_render]}&title={tv_name}&referer=1&expires={json_win_param["expires"]}&description=S{n_season}%3AE{n_ep}+{ep_title}&nextEpisode=1',
|
|
||||||
})
|
|
||||||
|
|
||||||
if response.ok:
|
if response.ok:
|
||||||
return binascii.hexlify(response.content).decode('utf-8')
|
return binascii.hexlify(response.content).decode('utf-8')
|
||||||
@ -151,12 +128,12 @@ def get_m3u8_audio(json_win_video, json_win_param, tv_name, n_season, n_ep, ep_t
|
|||||||
|
|
||||||
|
|
||||||
# [func \ main]
|
# [func \ main]
|
||||||
def dw_single_ep(tv_id, eps, index_ep_select, domain, token, tv_name, season_select):
|
def dw_single_ep(tv_id, eps, index_ep_select, domain, tv_name, season_select):
|
||||||
encoded_name = urllib.parse.quote(eps[index_ep_select]['name'])
|
encoded_name = urllib.parse.quote(eps[index_ep_select]['name'])
|
||||||
|
|
||||||
console.print(
|
console.print(
|
||||||
f"[green]Downloading episode: [blue]{eps[index_ep_select]['n']} [green]=> [purple]{eps[index_ep_select]['name']}")
|
f"[green]Downloading episode: [blue]{eps[index_ep_select]['n']} [green]=> [purple]{eps[index_ep_select]['name']}")
|
||||||
embed_content = get_iframe(tv_id, eps[index_ep_select]['id'], domain, token)
|
embed_content = get_iframe(tv_id, eps[index_ep_select]['id'], domain)
|
||||||
if embed_content is None:
|
if embed_content is None:
|
||||||
return
|
return
|
||||||
json_win_video, json_win_param, render_quality = parse_content(embed_content)
|
json_win_video, json_win_param, render_quality = parse_content(embed_content)
|
||||||
@ -166,8 +143,7 @@ def dw_single_ep(tv_id, eps, index_ep_select, domain, token, tv_name, season_sel
|
|||||||
|
|
||||||
m3u8_playlist = get_playlist(json_win_video, json_win_param, render_quality)
|
m3u8_playlist = get_playlist(json_win_video, json_win_param, render_quality)
|
||||||
m3u8_url = get_m3u8_url(json_win_video, json_win_param, render_quality)
|
m3u8_url = get_m3u8_url(json_win_video, json_win_param, render_quality)
|
||||||
m3u8_key = get_m3u8_key_ep(json_win_video, json_win_param, tv_name, season_select, index_ep_select + 1,
|
m3u8_key = get_m3u8_key_ep()
|
||||||
encoded_name, token_render)
|
|
||||||
|
|
||||||
mp4_name = f"{tv_name.replace('+', '_')}_S{str(season_select).zfill(2)}E{str(index_ep_select + 1).zfill(2)}"
|
mp4_name = f"{tv_name.replace('+', '_')}_S{str(season_select).zfill(2)}E{str(index_ep_select + 1).zfill(2)}"
|
||||||
mp4_format = f"{mp4_name}.mp4"
|
mp4_format = f"{mp4_name}.mp4"
|
||||||
@ -186,7 +162,6 @@ def dw_single_ep(tv_id, eps, index_ep_select, domain, token, tv_name, season_sel
|
|||||||
|
|
||||||
|
|
||||||
def main_dw_tv(tv_id, tv_name, version, domain):
|
def main_dw_tv(tv_id, tv_name, version, domain):
|
||||||
token = get_token(tv_id, domain)
|
|
||||||
|
|
||||||
num_season_find = get_info_tv(tv_id, tv_name, version, domain)
|
num_season_find = get_info_tv(tv_id, tv_name, version, domain)
|
||||||
console.print(
|
console.print(
|
||||||
@ -197,14 +172,14 @@ def main_dw_tv(tv_id, tv_name, version, domain):
|
|||||||
start, end = map(int, season_select[1:-1].split('-'))
|
start, end = map(int, season_select[1:-1].split('-'))
|
||||||
result = list(range(start, end + 1))
|
result = list(range(start, end + 1))
|
||||||
for n_season in result:
|
for n_season in result:
|
||||||
eps = get_info_season(tv_id, tv_name, domain, version, token, n_season)
|
eps = get_info_season(tv_id, tv_name, domain, version, n_season)
|
||||||
for ep in eps:
|
for ep in eps:
|
||||||
dw_single_ep(tv_id, eps, int(ep['n']) - 1, domain, token, tv_name, n_season)
|
dw_single_ep(tv_id, eps, int(ep['n']) - 1, domain, tv_name, n_season)
|
||||||
print("\n")
|
print("\n")
|
||||||
elif season_select != "*":
|
elif season_select != "*":
|
||||||
season_select = int(season_select)
|
season_select = int(season_select)
|
||||||
if 1 <= season_select <= num_season_find:
|
if 1 <= season_select <= num_season_find:
|
||||||
eps = get_info_season(tv_id, tv_name, domain, version, token, season_select)
|
eps = get_info_season(tv_id, tv_name, domain, version, season_select)
|
||||||
|
|
||||||
for ep in eps:
|
for ep in eps:
|
||||||
console.print(f"[green]Episode: [blue]{ep['n']} [green]=> [purple]{ep['name']}")
|
console.print(f"[green]Episode: [blue]{ep['n']} [green]=> [purple]{ep['name']}")
|
||||||
@ -218,27 +193,27 @@ def main_dw_tv(tv_id, tv_name, version, domain):
|
|||||||
|
|
||||||
for n_range_ep in result:
|
for n_range_ep in result:
|
||||||
# index_ep_select = int(n_range_ep) # Unused
|
# index_ep_select = int(n_range_ep) # Unused
|
||||||
dw_single_ep(tv_id, eps, n_range_ep - 1, domain, token, tv_name, season_select)
|
dw_single_ep(tv_id, eps, n_range_ep - 1, domain, tv_name, season_select)
|
||||||
|
|
||||||
# Download single ep
|
# Download single ep
|
||||||
elif index_ep_select != "*":
|
elif index_ep_select != "*":
|
||||||
if 1 <= int(index_ep_select) <= len(eps):
|
if 1 <= int(index_ep_select) <= len(eps):
|
||||||
index_ep_select = int(index_ep_select) - 1
|
index_ep_select = int(index_ep_select) - 1
|
||||||
dw_single_ep(tv_id, eps, index_ep_select, domain, token, tv_name, season_select)
|
dw_single_ep(tv_id, eps, index_ep_select, domain, tv_name, season_select)
|
||||||
else:
|
else:
|
||||||
console.print("[red]Wrong [yellow]INDEX [red]for the selected Episode")
|
console.print("[red]Wrong [yellow]INDEX [red]for the selected Episode")
|
||||||
|
|
||||||
# Download all
|
# Download all
|
||||||
else:
|
else:
|
||||||
for ep in eps:
|
for ep in eps:
|
||||||
dw_single_ep(tv_id, eps, int(ep['n']) - 1, domain, token, tv_name, season_select)
|
dw_single_ep(tv_id, eps, int(ep['n']) - 1, domain, tv_name, season_select)
|
||||||
print("\n")
|
print("\n")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
console.print("[red]Wrong [yellow]INDEX for the selected Season")
|
console.print("[red]Wrong [yellow]INDEX for the selected Season")
|
||||||
else:
|
else:
|
||||||
for n_season in range(1, num_season_find + 1):
|
for n_season in range(1, num_season_find + 1):
|
||||||
eps = get_info_season(tv_id, tv_name, domain, version, token, n_season)
|
eps = get_info_season(tv_id, tv_name, domain, version, n_season)
|
||||||
for ep in eps:
|
for ep in eps:
|
||||||
dw_single_ep(tv_id, eps, int(ep['n']) - 1, domain, token, tv_name, n_season)
|
dw_single_ep(tv_id, eps, int(ep['n']) - 1, domain, tv_name, n_season)
|
||||||
print("\n")
|
print("\n")
|
||||||
|
@ -126,10 +126,6 @@ class M3U8_Parser:
|
|||||||
sub_parse.parse_data(req_sub_content.text)
|
sub_parse.parse_data(req_sub_content.text)
|
||||||
url_subtitle = sub_parse.subtitle[0]
|
url_subtitle = sub_parse.subtitle[0]
|
||||||
|
|
||||||
# Subtitles convention:
|
|
||||||
# Movie_Name.[Language_Code].vtt
|
|
||||||
# Movie_Name.[Language_Code].forced.vtt # If forced
|
|
||||||
|
|
||||||
if "forced" in name_language.lower():
|
if "forced" in name_language.lower():
|
||||||
name_language = name_language.lower().replace("forced", "").strip()
|
name_language = name_language.lower().replace("forced", "").strip()
|
||||||
name_language = name_language.lower().replace("-", "").strip()
|
name_language = name_language.lower().replace("-", "").strip()
|
||||||
@ -161,7 +157,6 @@ class M3U8_Parser:
|
|||||||
else:
|
else:
|
||||||
console.log("[red]Couldn't find any playlist with audio")
|
console.log("[red]Couldn't find any playlist with audio")
|
||||||
|
|
||||||
|
|
||||||
class M3U8_Segments:
|
class M3U8_Segments:
|
||||||
def __init__(self, url, key=None):
|
def __init__(self, url, key=None):
|
||||||
self.url = url
|
self.url = url
|
||||||
@ -195,7 +190,6 @@ class M3U8_Segments:
|
|||||||
|
|
||||||
if response.ok:
|
if response.ok:
|
||||||
self.parse_data(response.text)
|
self.parse_data(response.text)
|
||||||
# console.log(f"[red]Ts segments find [white]=> [yellow]{len(self.segments)}")
|
|
||||||
|
|
||||||
if len(self.segments) == 0:
|
if len(self.segments) == 0:
|
||||||
console.log("[red]Couldn't find any segments to download, retry")
|
console.log("[red]Couldn't find any segments to download, retry")
|
||||||
@ -224,17 +218,14 @@ class M3U8_Segments:
|
|||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
return response.content
|
return response.content
|
||||||
else:
|
else:
|
||||||
# print(f"Failed to fetch {ts_url}: {response.status_code}")
|
|
||||||
failed_segments.append(str(url_number))
|
failed_segments.append(str(url_number))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# print(f"Failed to fetch {ts_url}: {str(e)}")
|
|
||||||
failed_segments.append(str(url_number))
|
failed_segments.append(str(url_number))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# print("Skip ", ts_url, " arr ", failed_segments)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def save_ts(self, index, progress_counter, quit_event):
|
def save_ts(self, index, progress_counter, quit_event):
|
||||||
@ -257,11 +248,8 @@ class M3U8_Segments:
|
|||||||
progress_counter.update(1)
|
progress_counter.update(1)
|
||||||
|
|
||||||
def download_ts(self):
|
def download_ts(self):
|
||||||
"""Loop to download all segment of playlist m3u8 and break it if there is no progress"""
|
|
||||||
|
|
||||||
progress_counter = tqdm(total=len(self.segments), unit="bytes", desc="[yellow]Download")
|
progress_counter = tqdm(total=len(self.segments), unit="bytes", desc="[yellow]Download")
|
||||||
|
|
||||||
# Event to signal when to quit
|
|
||||||
quit_event = threading.Event()
|
quit_event = threading.Event()
|
||||||
timeout_occurred = False
|
timeout_occurred = False
|
||||||
|
|
||||||
@ -272,7 +260,7 @@ class M3U8_Segments:
|
|||||||
with ThreadPoolExecutor(max_workers=MAX_WORKER) as executor:
|
with ThreadPoolExecutor(max_workers=MAX_WORKER) as executor:
|
||||||
futures = []
|
futures = []
|
||||||
for index in range(len(self.segments)):
|
for index in range(len(self.segments)):
|
||||||
if timeout_occurred: # Check if timeout occurred before submitting tasks
|
if timeout_occurred:
|
||||||
break
|
break
|
||||||
future = executor.submit(self.save_ts, index, progress_counter, quit_event)
|
future = executor.submit(self.save_ts, index, progress_counter, quit_event)
|
||||||
futures.append(future)
|
futures.append(future)
|
||||||
@ -282,13 +270,12 @@ class M3U8_Segments:
|
|||||||
future.result()
|
future.result()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"An error occurred: {str(e)}")
|
print(f"An error occurred: {str(e)}")
|
||||||
# Handle the error as needed
|
|
||||||
finally:
|
finally:
|
||||||
progress_counter.close()
|
progress_counter.close()
|
||||||
quit_event.set() # Signal the timer thread to quit
|
quit_event.set()
|
||||||
timer_thread.join() # Ensure the timer thread is terminated
|
timer_thread.join()
|
||||||
|
|
||||||
# Continue with the rest of your code here...
|
|
||||||
|
|
||||||
def timer(self, progress_counter, quit_event, timeout_checker):
|
def timer(self, progress_counter, quit_event, timeout_checker):
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
@ -298,21 +285,20 @@ class M3U8_Segments:
|
|||||||
current_count = progress_counter.n
|
current_count = progress_counter.n
|
||||||
|
|
||||||
if current_count != last_count:
|
if current_count != last_count:
|
||||||
start_time = time.time() # Update start time when progress is made
|
start_time = time.time()
|
||||||
last_count = current_count
|
last_count = current_count
|
||||||
|
|
||||||
elapsed_time = time.time() - start_time
|
elapsed_time = time.time() - start_time
|
||||||
if elapsed_time > self.progress_timeout:
|
if elapsed_time > self.progress_timeout:
|
||||||
console.log(f"[red]No progress for {self.progress_timeout} seconds.")
|
console.log(f"[red]No progress for {self.progress_timeout} seconds.")
|
||||||
console.log("[red]Breaking ThreadPoolExecutor...")
|
console.log("[red]Breaking ThreadPoolExecutor...")
|
||||||
timeout_checker() # Set the flag indicating a timeout
|
timeout_checker()
|
||||||
quit_event.set() # Signal the main thread to quit
|
quit_event.set()
|
||||||
break # Break the loop instead of exiting
|
break
|
||||||
|
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
# Execution reaches here when the loop is broken
|
progress_counter.refresh()
|
||||||
progress_counter.refresh() # Refresh the progress bar to reflect the last progress
|
|
||||||
|
|
||||||
def join(self, output_filename):
|
def join(self, output_filename):
|
||||||
"""Join all segments file to a mp4 file name"""
|
"""Join all segments file to a mp4 file name"""
|
||||||
@ -340,13 +326,11 @@ class M3U8_Segments:
|
|||||||
ffmpeg.input(file_list_path, format='concat', safe=0).output(output_filename, map_metadata='-1', c='copy', loglevel='error').run()
|
ffmpeg.input(file_list_path, format='concat', safe=0).output(output_filename, map_metadata='-1', c='copy', loglevel='error').run()
|
||||||
except ffmpeg.Error as e:
|
except ffmpeg.Error as e:
|
||||||
console.log(f"[red]Error saving MP4: {e.stdout}")
|
console.log(f"[red]Error saving MP4: {e.stdout}")
|
||||||
#sys.exit(0)
|
|
||||||
|
|
||||||
console.log(f"[cyan]Clean ...")
|
console.log(f"[cyan]Clean ...")
|
||||||
os.remove(file_list_path)
|
os.remove(file_list_path)
|
||||||
shutil.rmtree("tmp", ignore_errors=True)
|
shutil.rmtree("tmp", ignore_errors=True)
|
||||||
|
|
||||||
|
|
||||||
class M3U8_Downloader:
|
class M3U8_Downloader:
|
||||||
def __init__(self, m3u8_url, m3u8_audio = None, key=None, output_filename="output.mp4"):
|
def __init__(self, m3u8_url, m3u8_audio = None, key=None, output_filename="output.mp4"):
|
||||||
self.m3u8_url = m3u8_url
|
self.m3u8_url = m3u8_url
|
||||||
@ -378,10 +362,7 @@ class M3U8_Downloader:
|
|||||||
if os.path.exists(f"{self.video_path}.mp4"):
|
if os.path.exists(f"{self.video_path}.mp4"):
|
||||||
os.renames(f"{self.video_path}.mp4", self.video_path)
|
os.renames(f"{self.video_path}.mp4", self.video_path)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def join_audio(self):
|
def join_audio(self):
|
||||||
"""Join audio with video and sync it"""
|
|
||||||
console.log("[cyan]Join audio and video")
|
console.log("[cyan]Join audio and video")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -414,11 +395,8 @@ class M3U8_Downloader:
|
|||||||
os.remove(self.audio_path)
|
os.remove(self.audio_path)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [ main function ]
|
# [ main function ]
|
||||||
def df_make_req(url):
|
def df_make_req(url):
|
||||||
"""Make req to get text"""
|
|
||||||
|
|
||||||
response = requests.get(url)
|
response = requests.get(url)
|
||||||
|
|
||||||
if response.ok:
|
if response.ok:
|
||||||
@ -427,19 +405,16 @@ def df_make_req(url):
|
|||||||
console.log(f"[red]Wrong url, error: {response.status_code}")
|
console.log(f"[red]Wrong url, error: {response.status_code}")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
def download_subtitle(url, name_language):
|
def download_subtitle(url, name_language):
|
||||||
"""Make req to vtt url and save to video subtitle folder"""
|
|
||||||
|
|
||||||
path = os.path.join("videos", "subtitle")
|
path = os.path.join("videos", "subtitle")
|
||||||
os.makedirs(path, exist_ok=True)
|
os.makedirs(path, exist_ok=True)
|
||||||
|
|
||||||
console.log(f"[green]Downloading subtitle: [red]{name_language}")
|
console.log(f"[green]Downloading subtitle: [red]{name_language}")
|
||||||
open(os.path.join(path, name_language + ".vtt"), "wb").write(requests.get(url).content)
|
open(os.path.join(path, name_language + ".vtt"), "wb").write(requests.get(url).content)
|
||||||
|
|
||||||
|
|
||||||
def download_m3u8(m3u8_playlist=None, m3u8_index = None, m3u8_audio=None, m3u8_subtitle=None, key=None, output_filename=os.path.join("videos", "output.mp4"), log=False, subtitle_folder="subtitles", content_name=""):
|
def download_m3u8(m3u8_playlist=None, m3u8_index = None, m3u8_audio=None, m3u8_subtitle=None, key=None, output_filename=os.path.join("videos", "output.mp4"), log=False, subtitle_folder="subtitles", content_name=""):
|
||||||
m3u8_audio_url=None
|
m3u8_audio_url=None
|
||||||
|
# m3u8_playlist never use in this version
|
||||||
|
|
||||||
key = bytes.fromhex(key) if key is not None else key
|
key = bytes.fromhex(key) if key is not None else key
|
||||||
|
|
||||||
@ -454,6 +429,7 @@ def download_m3u8(m3u8_playlist=None, m3u8_index = None, m3u8_audio=None, m3u8_s
|
|||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
m3u8_audio_url = m3u8_audio_obj["url"]
|
m3u8_audio_url = m3u8_audio_obj["url"]
|
||||||
console.log(f"[green]Select language => [purple]{m3u8_audio_obj['lang']}")
|
console.log(f"[green]Select language => [purple]{m3u8_audio_obj['lang']}")
|
||||||
|
|
||||||
if m3u8_subtitle != None:
|
if m3u8_subtitle != None:
|
||||||
|
|
||||||
parse_class_m3u8_sub = M3U8_Parser()
|
parse_class_m3u8_sub = M3U8_Parser()
|
||||||
|
2
run.py
2
run.py
@ -31,7 +31,6 @@ def initialize():
|
|||||||
check_ffmpeg()
|
check_ffmpeg()
|
||||||
print("\n")
|
print("\n")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
initialize()
|
initialize()
|
||||||
@ -90,6 +89,5 @@ def main():
|
|||||||
|
|
||||||
console.print("[red]Done!")
|
console.print("[red]Done!")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user