From 99a57595a587c546d3a5a596ad5015bf1099ed03 Mon Sep 17 00:00:00 2001 From: Fede14 Date: Mon, 4 Mar 2024 23:30:12 +0100 Subject: [PATCH] audio default + sub --- Src/Api/film.py | 17 ++++- Src/Api/tv.py | 22 ++++-- Src/Lib/FFmpeg/my_m3u8.py | 150 +++++++++++++++++++++++++++++--------- 3 files changed, 148 insertions(+), 41 deletions(-) diff --git a/Src/Api/film.py b/Src/Api/film.py index 7820d89..41c3ec1 100644 --- a/Src/Api/film.py +++ b/Src/Api/film.py @@ -74,9 +74,22 @@ def get_m3u8_audio(json_win_video, json_win_param, title_name, token_render): if req.ok: m3u8_cont = req.text.split() + m3u8_cont_arr = [] for row in m3u8_cont: - if "audio" in str(row) and "ita" in str(row): - return row.split(",")[-1].split('"')[-2] + if "audio" in str(row): + lang=None + default=False + for field in row.split(","): + if "NAME" in field: + lang = field.split('"')[-2] + if "DEFAULT" in field: + default_str = field.split('=')[1] + default = default_str.strip() == "YES" + audioobj={"url": row.split(",")[-1].split('"')[-2], "lang": lang, "default": default} + if audioobj['lang'] is None: + continue + m3u8_cont_arr.append(audioobj) + return m3u8_cont_arr or None else: console.log(f"[red]Error: {req.status_code}") sys.exit(0) diff --git a/Src/Api/tv.py b/Src/Api/tv.py index 3848662..fd15eeb 100644 --- a/Src/Api/tv.py +++ b/Src/Api/tv.py @@ -104,17 +104,29 @@ def get_m3u8_key_ep(json_win_video, json_win_param, tv_name, n_stagione, n_ep, e console.log(f"[red]Error: {response.status_code}") sys.exit(0) -def get_m3u8_playlist(json_win_video, json_win_param, tv_name, n_stagione, n_ep, ep_title, token_render): +def get_m3u8_audio(json_win_video, json_win_param, tv_name, n_stagione, n_ep, ep_title, 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={tv_name}&referer=1&expires={json_win_param["expires"]}&description=S{n_stagione}%3AE{n_ep}+{ep_title}&nextEpisode=1' }) if req.ok: m3u8_cont = req.text.split() - + m3u8_cont_arr = [] for row in m3u8_cont: - if "audio" in str(row) and "ita" in str(row): - return row.split(",")[-1].split('"')[-2] + if "audio" in str(row): + lang=None + default=False + for field in row.split(","): + if "NAME" in field: + lang = field.split('"')[-2] + if "DEFAULT" in field: + default_str = field.split('=')[1] + default = default_str.strip() == "YES" + audioobj={"url": row.split(",")[-1].split('"')[-2], "lang": lang, "default": default} + if audioobj['lang'] is None: + continue + m3u8_cont_arr.append(audioobj) + return m3u8_cont_arr or None else: console.log(f"[red]Error: {req.status_code}") sys.exit(0) @@ -140,7 +152,7 @@ def dw_single_ep(tv_id, eps, index_ep_select, domain, token, tv_name, season_sel mp4_format = f"{mp4_name}.mp4" mp4_path = os.path.join("videos",tv_name, 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_audio(json_win_video, json_win_param, tv_name, season_select, index_ep_select+1, enccoded_name, token_render) if m3u8_url_audio != None: console.print("[blue]Use m3u8 audio => [red]True") diff --git a/Src/Lib/FFmpeg/my_m3u8.py b/Src/Lib/FFmpeg/my_m3u8.py index d493b98..8d5dcef 100644 --- a/Src/Lib/FFmpeg/my_m3u8.py +++ b/Src/Lib/FFmpeg/my_m3u8.py @@ -19,9 +19,10 @@ warnings.filterwarnings("ignore", category=TqdmExperimentalWarning) warnings.filterwarnings("ignore", category=UserWarning, module="cryptography") # Variable -MAX_WORKER = 20 +MAX_WORKER = 150 DONWLOAD_SUB = True -DOWNLOAD_DEFAULT_LANGUAGE = False +DOWNLOAD_DEFAULT_LANGUAGE = False # True to select default language, False to select language +SELECTED_LANGUAGE = "English" # Ex. "English" if DOWNLOAD_DEFAULT_LANGUAGE is False failed_segments = [] @@ -118,8 +119,10 @@ class M3U8_Parser: if self.subtitle_playlist: for sub_info in self.subtitle_playlist: name_language = sub_info.get("language") + full_name = sub_info.get("name") - if name_language in ["auto", "ita"]: + + if name_language in ["auto"]: continue os.makedirs(path, exist_ok=True) @@ -130,7 +133,7 @@ class M3U8_Parser: sub_parse.parse_data(req_sub_content.text) url_subititle = sub_parse.subtitle[0] - open(os.path.join(path, name_language + ".vtt"), "wb").write(requests.get(url_subititle).content) + open(os.path.join(path, full_name + ".vtt"), "wb").write(requests.get(url_subititle).content) else: console.log("[red]No subtitle find") @@ -363,6 +366,9 @@ class M3U8_Downloader: print("\n") self.join_audio() + else: + self.join_subtitle(self.video_path) + def join_audio(self): """Join audio with video and sync it""" @@ -386,11 +392,76 @@ class M3U8_Downloader: console.print("[green]Merge completed successfully.") + self.join_subtitle(self.video_path + ".mp4") + except ffmpeg.Error as e: print("ffmpeg error:", e) os.remove(self.video_path) os.remove(self.audio_path) + + def join_subtitle(self, video_path): + """Join subtitles with video and sync them""" + + subtitle_dir = "videos/subtitle/" + italian_subtitle_file = "Italian.vtt" + portuguese_subtitle_file = "Portuguese.vtt" + + italian_subtitle_path = os.path.join(subtitle_dir, italian_subtitle_file) + portuguese_subtitle_path = os.path.join(subtitle_dir, portuguese_subtitle_file) + + if not os.path.exists(italian_subtitle_path): + console.log(f"[red]Subtitle file '{italian_subtitle_file}' not found in '{subtitle_dir}'") + return + + if not os.path.exists(portuguese_subtitle_path): + console.log(f"[red]Subtitle file '{portuguese_subtitle_file}' not found in '{subtitle_dir}'") + return + + try: + video_stream = ffmpeg.input(video_path) + italian_subtitle_stream = ffmpeg.input(italian_subtitle_path) + portuguese_subtitle_stream = ffmpeg.input(portuguese_subtitle_path) + + process = ( + ffmpeg.output( + video_stream, + italian_subtitle_stream, + portuguese_subtitle_stream, + f"{os.path.splitext(video_path)[0]}_subtitled.mp4", + vcodec="copy", + acodec="copy", + scodec="mov_text", + loglevel='quiet', + ) + .global_args( + '-map', + '0:v:0', + '-map', + '1:s:0', + '-metadata:s:s:0', + 'language=ita', + '-map', + '2:s:0', + '-metadata:s:s:1', + 'language=por', + '-shortest', + '-strict', + 'experimental', + ) + .run() + ) + + + console.log("[green]Subtitles merged successfully.") + + except ffmpeg.Error as e: + print("ffmpeg error:", e) + + os.remove(video_path) # Optionally remove original video if desired + os.remove(italian_subtitle_path) + os.remove(portuguese_subtitle_path) + # [ main function ] @@ -415,43 +486,54 @@ def download_subtitle(url, 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): - + m3u8_audio_url=None # Get byte of key key = bytes.fromhex(key) if key is not None else key - if m3u8_playlist != None: - console.log(f"[green]Dowload m3u8 from playlist") + # if m3u8_playlist != None: + # console.log(f"[green]Dowload m3u8 from playlist") - # Parse m3u8 playlist - parse_class_m3u8 = M3U8_Parser() + # # Parse m3u8 playlist + # parse_class_m3u8 = M3U8_Parser() - # Parse directly m3u8 content pass if present - if "#EXTM3U" not in m3u8_playlist: - parse_class_m3u8.parse_data(df_make_req(m3u8_playlist)) - else: - parse_class_m3u8.parse_data(m3u8_playlist) + # # Parse directly m3u8 content pass if present + # if "#EXTM3U" not in m3u8_playlist: + # parse_class_m3u8.parse_data(df_make_req(m3u8_playlist)) + # else: + # parse_class_m3u8.parse_data(m3u8_playlist) - # Get italian language in present as defualt + # # Get italian language in present as defualt + # if DOWNLOAD_DEFAULT_LANGUAGE: + # m3u8_audio = parse_class_m3u8.get_track_audio("English") + # console.log(f"[green]Select language => [purple]{m3u8_audio}") + + + # # Get best quality + # if m3u8_index == None: + # m3u8_index = parse_class_m3u8.get_best_quality() + # if "https" in m3u8_index: + # if log: console.log(f"[green]Select m3u8 index => [purple]{m3u8_index}") + # else: + # console.log("[red]Cant find a valid m3u8 index") + # sys.exit(0) + + + # # Download subtitle if present ( normaly in m3u8 playlist ) + # if DONWLOAD_SUB: + # parse_class_m3u8.download_subtitle() + + if m3u8_audio is not None: + m3u8_audio_obj = None if DOWNLOAD_DEFAULT_LANGUAGE: - m3u8_audio = parse_class_m3u8.get_track_audio("Italian") - console.log(f"[green]Select language => [purple]{m3u8_audio}") - - - # Get best quality - if m3u8_index == None: - m3u8_index = parse_class_m3u8.get_best_quality() - if "https" in m3u8_index: - if log: console.log(f"[green]Select m3u8 index => [purple]{m3u8_index}") - else: - console.log("[red]Cant find a valid m3u8 index") - sys.exit(0) - - - # Download subtitle if present ( normaly in m3u8 playlist ) - if DONWLOAD_SUB: - parse_class_m3u8.download_subtitle() - + m3u8_audio_obj = next((audioobj for audioobj in m3u8_audio if audioobj.get("default", False)), None) or m3u8_audio[0] + elif SELECTED_LANGUAGE: + m3u8_audio_obj = next((audioobj for audioobj in m3u8_audio if audioobj["lang"] == SELECTED_LANGUAGE), None) + if m3u8_audio_obj is None: + console.log("[red]Cant find a valid m3u8 audio") + sys.exit(0) + m3u8_audio_url = m3u8_audio_obj["url"] + console.log(f"[green]Select language => [purple]{m3u8_audio_obj['lang']}") if m3u8_subtitle != None: parse_class_m3u8_sub = M3U8_Parser() @@ -474,4 +556,4 @@ def download_m3u8(m3u8_playlist=None, m3u8_index = None, m3u8_audio=None, m3u8_s if log: console.log(f"[green]Dowload m3u8 from index [white]=> [purple]{m3u8_index}") - M3U8_Downloader(m3u8_index, m3u8_audio, key=key, output_filename=output_filename).start() \ No newline at end of file + M3U8_Downloader(m3u8_index, m3u8_audio_url, key=key, output_filename=output_filename).start() \ No newline at end of file