fix(subtitles): add subtitles to corresponding folder

This commit is contained in:
cohvir 2024-03-04 18:30:12 +01:00
parent 3f716739c4
commit 04431a12a7
3 changed files with 55 additions and 39 deletions

View File

@ -10,6 +10,7 @@ from Src.Lib.FFmpeg.my_m3u8 import download_m3u8
import requests, os, re, json, sys, binascii
from bs4 import BeautifulSoup
# [func]
def get_iframe(id_title, domain):
req = requests.get(url = f"https://streamingcommunity.{domain}/iframe/{id_title}", headers = {
@ -29,7 +30,8 @@ def get_iframe(id_title, domain):
else:
console.log(f"[red]Error: {req.status_code}")
sys.exit(0)
def select_quality(json_win_param):
if json_win_param['token1080p']:
@ -41,6 +43,7 @@ def select_quality(json_win_param):
else:
return "360p"
def parse_content(embed_content):
# Parse parameter from req embed content
@ -53,10 +56,12 @@ def parse_content(embed_content):
json_win_param = json_win_param.replace(",}", "}").replace("'", '"')
return json.loads(json_win_video), json.loads(json_win_param), select_quality(json.loads(json_win_param))
def get_m3u8_url(json_win_video, json_win_param, render_quality):
token_render = f"token{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']}"
def get_m3u8_key(json_win_video, json_win_param, title_name, token_render):
response = requests.get('https://vixcloud.co/storage/enc.key', headers={
'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"]}',
@ -68,6 +73,7 @@ def get_m3u8_key(json_win_video, json_win_param, title_name, token_render):
console.log(f"[red]Error: {response.status_code}")
sys.exit(0)
def get_m3u8_audio(json_win_video, json_win_param, title_name, token_render):
req = requests.get(f'https://vixcloud.co/playlist/{json_win_video["id"]}', params={'token': json_win_param['token'], 'expires': json_win_param["expires"] }, headers={
'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"]}'
@ -101,7 +107,7 @@ def main_dw_film(id_film, title_name, domain):
m3u8_url_audio = get_m3u8_audio(json_win_video, json_win_param, title_name, token_render)
if m3u8_url_audio != None:
if m3u8_url_audio is not None:
console.print("[blue]Using m3u8 audio => [red]True")
download_m3u8(m3u8_index=m3u8_url, m3u8_audio=m3u8_url_audio, m3u8_subtitle=m3u8_url, key=m3u8_key, output_filename=mp4_path)
subtitle_path = os.path.join(config['root_path'], config['series_folder_name'], mp4_name)
download_m3u8(m3u8_index=m3u8_url, m3u8_audio=m3u8_url_audio, m3u8_subtitle=m3u8_url, key=m3u8_key, output_filename=mp4_path, subtitle_folder=subtitle_path, content_name=mp4_name)

View File

@ -17,6 +17,7 @@ def get_token(id_tv, domain):
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):
req = requests.get(f"https://streamingcommunity.{domain}/titles/{id_film}-{title_name}", headers={
@ -31,6 +32,7 @@ def get_info_tv(id_film, title_name, site_version, domain):
console.log(f"[red]Error: {req.status_code}")
sys.exit(0)
def get_info_season(tv_id, tv_name, domain, version, token, n_stagione):
req = requests.get(f'https://streamingcommunity.{domain}/titles/{tv_id}-{tv_name}/stagione-{n_stagione}', headers={
'authority': f'streamingcommunity.{domain}', 'referer': f'https://streamingcommunity.broker/titles/{tv_id}-{tv_name}',
@ -43,6 +45,7 @@ def get_info_season(tv_id, tv_name, domain, version, token, n_stagione):
console.log(f"[red]Error: {req.status_code}")
sys.exit(0)
def get_iframe(tv_id, ep_id, domain, token):
req = requests.get(f'https://streamingcommunity.{domain}/iframe/{tv_id}', params={'episode_id': ep_id, 'next_episode': '1'}, cookies={'XSRF-TOKEN': token}, headers={
'referer': f'https://streamingcommunity.{domain}/watch/{tv_id}?e={ep_id}',
@ -86,14 +89,17 @@ def parse_content(embed_content):
json_win_param = json_win_param.replace(",}", "}").replace("'", '"')
return json.loads(json_win_video), json.loads(json_win_param), select_quality(json.loads(json_win_param))
def get_playlist(json_win_video, json_win_param, 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']}"
def get_m3u8_url(json_win_video, json_win_param, render_quality):
token_render = f"token{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']}"
def get_m3u8_key_ep(json_win_video, json_win_param, tv_name, n_stagione, n_ep, ep_title, token_render):
response = requests.get('https://vixcloud.co/storage/enc.key', headers={
'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_stagione}%3AE{n_ep}+{ep_title}&nextEpisode=1',
@ -124,7 +130,7 @@ def get_m3u8_playlist(json_win_video, json_win_param, tv_name, n_stagione, n_ep,
# [func \ main]
def dw_single_ep(tv_id, eps, index_ep_select, domain, token, tv_name, season_select):
enccoded_name = urllib.parse.quote(eps[index_ep_select]['name'])
encoded_name = urllib.parse.quote(eps[index_ep_select]['name'])
console.print(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)
@ -135,20 +141,23 @@ 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_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, enccoded_name, token_render)
m3u8_key = get_m3u8_key_ep(json_win_video, json_win_param, tv_name, season_select, index_ep_select+1, 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_format = f"{mp4_name}.mp4"
season = mp4_name.rsplit("E", 1)[0]
mp4_path = os.path.join(config['root_path'], config['series_folder_name'], tv_name, season, mp4_format)
m3u8_url_audio = get_m3u8_playlist(json_win_video, json_win_param, tv_name, season_select, index_ep_select+1, enccoded_name, token_render)
m3u8_url_audio = get_m3u8_playlist(json_win_video, json_win_param, tv_name, season_select, index_ep_select+1, encoded_name, token_render)
if m3u8_url_audio != None:
if m3u8_url_audio is not None:
console.print("[blue]Using m3u8 audio => [red]True")
# Movie_Name.[Language_Code].vtt
# Movie_Name.[Language_Code].forced.vtt
subtitle_path = os.path.join(config['root_path'], config['series_folder_name'], mp4_name, season)
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)
download_m3u8(m3u8_index=m3u8_url, m3u8_audio=m3u8_url_audio, m3u8_subtitle=m3u8_playlist, key=m3u8_key, output_filename=mp4_path)
def main_dw_tv(tv_id, tv_name, version, domain):
token = get_token(tv_id, domain)

View File

@ -66,7 +66,7 @@ class M3U8_Parser:
})
for key in m3u8_obj.keys:
if key != None:
if key is not None:
self.keys = ({
"method": key.method,
"uri": key.uri,
@ -91,7 +91,6 @@ class M3U8_Parser:
"uri": media.uri
})
for segment in m3u8_obj.segments:
if "vtt" not in segment.uri:
self.segments.append(segment.uri)
@ -111,10 +110,10 @@ class M3U8_Parser:
print("No video playlist found")
return None
def download_subtitle(self):
def download_subtitle(self, subtitle_path, content_name):
"""Download all subtitle if present"""
path = os.path.join(config['root_path'], "Film o Serie", "nome film o stagione serie")
path = subtitle_path
if self.subtitle_playlist:
for sub_info in self.subtitle_playlist:
@ -130,9 +129,12 @@ class M3U8_Parser:
sub_parse = M3U8_Parser()
sub_parse.parse_data(req_sub_content.text)
url_subtitle = sub_parse.subtitle[0]
# Subtitles convention:
# Movie_Name.[Language_Code].vtt
# Movie_Name.[Language_Code].forced.vtt
open(os.path.join(path, "nome film o serie" ,f".{name_language}" + "se conteneva forced: .forced" + ".vtt"), "wb").write(requests.get(url_subtitle).content)
# Movie_Name.[Language_Code].forced.vtt # If forced
# Implementare "forced"
open(os.path.join(path, content_name + f".{name_language}" + ".vtt"), "wb").write(requests.get(url_subtitle).content)
else:
console.log("[red]No subtitle found")
@ -143,7 +145,7 @@ class M3U8_Parser:
if self.audio_ts:
console.log(f"[cyan]Found {len(self.audio_ts)}, playlist with audio")
if language_name != None:
if language_name is not None:
for obj_audio in self.audio_ts:
if obj_audio.get("name") == language_name:
return obj_audio.get("uri")
@ -152,12 +154,13 @@ class M3U8_Parser:
else:
console.log("[red]Couldn't find any playlist with audio")
class M3U8_Segments:
def __init__(self, url, key=None):
self.url = url
self.key = key
if key != None:
if key is not None:
self.decription = Decryption(key)
self.temp_folder = os.path.join("tmp", "segments")
@ -173,7 +176,7 @@ class M3U8_Segments:
m3u8_parser.parse_data(m3u8_content)
# Add decryption iv if present
if self.key != None and m3u8_parser.keys:
if self.key is not None and m3u8_parser.keys:
self.decription.parse_key(m3u8_parser.keys.get("iv"))
# Add all segments
@ -186,7 +189,7 @@ class M3U8_Segments:
if response.ok:
self.parse_data(response.text)
#console.log(f"[red]Ts segments find [white]=> [yellow]{len(self.segments)}")
# console.log(f"[red]Ts segments find [white]=> [yellow]{len(self.segments)}")
if len(self.segments) == 0:
console.log("[red]Couldn't find any segments to download, retry")
@ -215,20 +218,19 @@ class M3U8_Segments:
if response.status_code == 200:
return response.content
else:
#print(f"Failed to fetch {ts_url}: {response.status_code}")
# print(f"Failed to fetch {ts_url}: {response.status_code}")
failed_segments.append(str(url_number))
return None
except Exception as e:
#print(f"Failed to fetch {ts_url}: {str(e)}")
# print(f"Failed to fetch {ts_url}: {str(e)}")
failed_segments.append(str(url_number))
return None
else:
#print("Skip ", ts_url, " arr ", failed_segments)
# print("Skip ", ts_url, " arr ", failed_segments)
return None
def save_ts(self, index, progress_counter, quit_event):
"""Save ts file and decrypt if there is iv present in decryption class"""
@ -249,7 +251,7 @@ class M3U8_Segments:
progress_counter.update(1)
def download_ts(self):
"""Loop to donwload all segment of playlist m3u8 and break it if there is no progress"""
"""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")
@ -313,6 +315,7 @@ class M3U8_Segments:
file_list_path = os.path.join(current_dir, 'file_list.txt')
ts_files = [f for f in os.listdir(self.temp_folder) if f.endswith(".ts")]
def extract_number(file_name):
return int(''.join(filter(str.isdigit, file_name)))
ts_files.sort(key=extract_number)
@ -321,7 +324,6 @@ class M3U8_Segments:
console.log("[red]Couldn't find any segments to join, retry")
sys.exit(0)
with open(file_list_path, 'w') as f:
for ts_file in ts_files:
relative_path = os.path.relpath(os.path.join(self.temp_folder, ts_file), current_dir)
@ -338,6 +340,7 @@ class M3U8_Segments:
os.remove(file_list_path)
shutil.rmtree("tmp", ignore_errors=True)
class M3U8_Downloader:
def __init__(self, m3u8_url, m3u8_audio = None, key=None, output_filename="output.mp4"):
self.m3u8_url = m3u8_url
@ -355,7 +358,7 @@ class M3U8_Downloader:
print_duration_table(self.video_path)
print("\n")
if self.m3u8_audio != None:
if self.m3u8_audio is not None:
audio_m3u8 = M3U8_Segments(self.m3u8_audio, self.key)
console.log("[green]Downloading audio ts")
audio_m3u8.get_info()
@ -407,6 +410,7 @@ def df_make_req(url):
console.log(f"[red]Wrong url, error: {response.status_code}")
sys.exit(0)
def download_subtitle(url, name_language):
"""Make req to vtt url and save to video subtitle folder"""
@ -416,12 +420,13 @@ def download_subtitle(url, 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)
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):
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=""):
# Get byte of key
key = bytes.fromhex(key) if key is not None else key
if m3u8_playlist != None:
if m3u8_playlist is not None:
console.log(f"[green]Downloading m3u8 from playlist")
# Parse m3u8 playlist
@ -433,15 +438,13 @@ def download_m3u8(m3u8_playlist=None, m3u8_index = None, m3u8_audio=None, m3u8_s
else:
parse_class_m3u8.parse_data(m3u8_playlist)
# Get italian language if present as default
if DOWNLOAD_DEFAULT_LANGUAGE:
m3u8_audio = parse_class_m3u8.get_track_audio("Italian")
console.log(f"[green]Selected language => [purple]{m3u8_audio}")
# Get best quality
if m3u8_index == None:
if m3u8_index is None:
m3u8_index = parse_class_m3u8.get_best_quality()
if "https" in m3u8_index:
if log: console.log(f"[green]Selected m3u8 index => [purple]{m3u8_index}")
@ -449,12 +452,11 @@ def download_m3u8(m3u8_playlist=None, m3u8_index = None, m3u8_audio=None, m3u8_s
console.log("[red]Couldn't find a valid m3u8 index")
sys.exit(0)
# Download subtitle if present ( normally in m3u8 playlist )
if DOWNLOAD_SUB:
parse_class_m3u8.download_subtitle()
parse_class_m3u8.download_subtitle(subtitle_path=subtitle_folder, content_name=content_name)
if m3u8_subtitle != None:
if m3u8_subtitle is not None:
parse_class_m3u8_sub = M3U8_Parser()
@ -466,8 +468,7 @@ def download_m3u8(m3u8_playlist=None, m3u8_index = None, m3u8_audio=None, m3u8_s
# Download subtitle if present ( normally in m3u8 playlist )
if DOWNLOAD_SUB:
parse_class_m3u8_sub.download_subtitle()
parse_class_m3u8_sub.download_subtitle(subtitle_path=subtitle_folder, content_name=content_name)
# Download m3u8 index, with segments
# os.makedirs("videos", exist_ok=True)
@ -476,4 +477,4 @@ def download_m3u8(m3u8_playlist=None, m3u8_index = None, m3u8_audio=None, m3u8_s
if log:
console.log(f"[green]Download m3u8 from index [white]=> [purple]{m3u8_index}")
M3U8_Downloader(m3u8_index, m3u8_audio, key=key, output_filename=output_filename).start()
M3U8_Downloader(m3u8_index, m3u8_audio, key=key, output_filename=output_filename).start()