fix stuck 98%

This commit is contained in:
Ghost 2024-01-19 16:58:29 +01:00
parent 715e0524d7
commit 0709edde7f
6 changed files with 81 additions and 34 deletions

1
.gitignore vendored
View File

@ -7,4 +7,3 @@ pyvenv.cfg
# Project specific # Project specific
videos/ videos/
tmp/ tmp/
Src/Util/file_list.txt

View File

@ -121,7 +121,7 @@ def dw_single_ep(tv_id, eps, index_ep_select, domain, token, tv_name, season_sel
m3u8_url_audio = get_m3u8_audio(json_win_video, json_win_param, tv_name, season_select, index_ep_select+1, eps[index_ep_select]['name'], token_render) m3u8_url_audio = get_m3u8_audio(json_win_video, json_win_param, tv_name, season_select, index_ep_select+1, eps[index_ep_select]['name'], token_render)
if m3u8_url_audio != None: if m3u8_url_audio != None:
console.print("[red]=> Use m3u8 audio") console.print("[blue]Use m3u8 audio => [red]True")
dw_m3u8(m3u8_url, m3u8_url_audio, m3u8_key, mp4_path) dw_m3u8(m3u8_url, m3u8_url_audio, m3u8_key, mp4_path)

View File

@ -1,5 +1,5 @@
__title__ = 'Streaming_community' __title__ = 'Streaming_community'
__version__ = 'v0.7.5' __version__ = 'v0.7.8'
__author__ = 'Ghost6446' __author__ = 'Ghost6446'
__description__ = 'A command-line program to download film' __description__ = 'A command-line program to download film'
__license__ = 'MIT License' __license__ = 'MIT License'

View File

@ -1,7 +1,7 @@
# 4.01.2023 # 4.01.2023
# Import # Import
import ffmpeg import ffmpeg, subprocess, re
def convert_utf8_name(name): def convert_utf8_name(name):
return str(name).encode('utf-8').decode('latin-1') return str(name).encode('utf-8').decode('latin-1')
@ -10,8 +10,15 @@ def there_is_audio(ts_file_path):
probe = ffmpeg.probe(ts_file_path) probe = ffmpeg.probe(ts_file_path)
return any(stream['codec_type'] == 'audio' for stream in probe['streams']) return any(stream['codec_type'] == 'audio' for stream in probe['streams'])
def merge_ts_files(video_path, audio_path, output_path): def merge_ts_files(video_path, audio_path, output_path):
input_video = ffmpeg.input(video_path) input_video = ffmpeg.input(video_path)
input_audio = ffmpeg.input(audio_path) input_audio = ffmpeg.input(audio_path)
ffmpeg.output(input_video, input_audio, output_path, format='mpegts', acodec='copy', vcodec='copy', loglevel='quiet').run()
ffmpeg_command = ffmpeg.output(input_video, input_audio, output_path, format='mpegts', acodec='copy', vcodec='copy', loglevel='quiet').compile()
try:
subprocess.run(ffmpeg_command, check=True, stderr=subprocess.PIPE)
return True
except subprocess.CalledProcessError as e:
#print(f"Failed convert: {video_path} \ {audio_path} to {output_path}")
return False

View File

@ -1,12 +1,12 @@
# 5.01.24 -> 7.01.24 # 5.01.24 -> 7.01.24
# Import # Import
import requests, re, os, ffmpeg, shutil, time, sys import requests, re, os, ffmpeg, shutil, time, sys, warnings
from tqdm.rich import tqdm from tqdm.rich import tqdm
from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ThreadPoolExecutor
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend from cryptography.hazmat.backends import default_backend
import moviepy.editor as mp
# Class import # Class import
from Src.Util.Helper.console import console from Src.Util.Helper.console import console
@ -14,6 +14,12 @@ from Src.Util.Helper.headers import get_headers
from Src.Util.Helper.util import there_is_audio, merge_ts_files from Src.Util.Helper.util import there_is_audio, merge_ts_files
# Disable warning
from tqdm import TqdmExperimentalWarning
warnings.filterwarnings("ignore", category=TqdmExperimentalWarning)
warnings.filterwarnings("ignore", category=UserWarning, module="cryptography")
# Variable # Variable
os.makedirs("videos", exist_ok=True) os.makedirs("videos", exist_ok=True)
@ -26,6 +32,9 @@ class M3U8Downloader:
self.m3u8_audio = m3u8_audio self.m3u8_audio = m3u8_audio
self.key = key self.key = key
self.output_filename = output_filename self.output_filename = output_filename
if output_filename == None:
console.log(f"Cant pass None as output file name")
sys.exit(0)
self.segments = [] self.segments = []
self.segments_audio = [] self.segments_audio = []
@ -35,6 +44,8 @@ class M3U8Downloader:
self.temp_folder = "tmp" self.temp_folder = "tmp"
os.makedirs(self.temp_folder, exist_ok=True) os.makedirs(self.temp_folder, exist_ok=True)
self.download_audio = False self.download_audio = False
self.max_retry = 3
self.failed_segments = []
def decode_ext_x_key(self, key_str): def decode_ext_x_key(self, key_str):
key_str = key_str.replace('"', '').lstrip("#EXT-X-KEY:") key_str = key_str.replace('"', '').lstrip("#EXT-X-KEY:")
@ -119,6 +130,21 @@ class M3U8Downloader:
return decrypted_data return decrypted_data
def make_req_single_ts_file(self, ts_url, retry=0):
if retry == self.max_retry:
console.log(f"[red]Failed download: {ts_url}")
self.segments.remove(ts_url)
return None
req = requests.get(ts_url, headers={'user-agent': get_headers()}, timeout=10, allow_redirects=True)
if req.status_code == 200:
return req.content
else:
retry += 1
return self.make_req_single_ts_file(ts_url, retry)
def decrypt_and_save(self, index): def decrypt_and_save(self, index):
video_ts_url = self.segments[index] video_ts_url = self.segments[index]
@ -126,8 +152,9 @@ class M3U8Downloader:
# Download video or audio ts file # Download video or audio ts file
if not os.path.exists(video_ts_filename): # Only for media that not use audio if not os.path.exists(video_ts_filename): # Only for media that not use audio
ts_response = requests.get(video_ts_url, headers={'user-agent': get_headers()}).content ts_response = self.make_req_single_ts_file(video_ts_url)
if ts_response != None:
if self.key and self.iv: if self.key and self.iv:
decrypted_data = self.decrypt_ts(ts_response) decrypted_data = self.decrypt_ts(ts_response)
with open(video_ts_filename, "wb") as ts_file: with open(video_ts_filename, "wb") as ts_file:
@ -137,17 +164,19 @@ class M3U8Downloader:
with open(video_ts_filename, "wb") as ts_file: with open(video_ts_filename, "wb") as ts_file:
ts_file.write(ts_response) ts_file.write(ts_response)
# Donwload only audio ts file # Donwload only audio ts file and merge with video
if self.download_audio: if self.download_audio:
audio_ts_url = self.segments_audio[index] audio_ts_url = self.segments_audio[index]
audio_ts_filename = os.path.join(self.temp_folder, f"{index}_a.ts") audio_ts_filename = os.path.join(self.temp_folder, f"{index}_a.ts")
video_audio_ts_filename = os.path.join(self.temp_folder, f"{index}_v_a.ts") video_audio_ts_filename = os.path.join(self.temp_folder, f"{index}_v_a.ts")
if not os.path.exists(video_audio_ts_filename): # Only for media use audio if not os.path.exists(video_audio_ts_filename): # Only for media use audio
ts_response = requests.get(audio_ts_url, headers={'user-agent': get_headers()}).content ts_response = self.make_req_single_ts_file(audio_ts_url)
if ts_response != None:
if self.key and self.iv: if self.key and self.iv:
decrypted_data = self.decrypt_ts(ts_response) decrypted_data = self.decrypt_ts(ts_response)
with open(audio_ts_filename, "wb") as ts_file: with open(audio_ts_filename, "wb") as ts_file:
ts_file.write(decrypted_data) ts_file.write(decrypted_data)
@ -156,14 +185,24 @@ class M3U8Downloader:
ts_file.write(ts_response) ts_file.write(ts_response)
# Join ts video and audio # Join ts video and audio
merge_ts_files(video_ts_filename, audio_ts_filename, video_audio_ts_filename) res_merge = merge_ts_files(video_ts_filename, audio_ts_filename, video_audio_ts_filename)
if res_merge:
os.remove(video_ts_filename) os.remove(video_ts_filename)
os.remove(audio_ts_filename) os.remove(audio_ts_filename)
# If merge fail, so we have only video and audio, take only video
else:
self.failed_segments.append(index)
os.remove(audio_ts_filename)
def download_and_save_ts(self): def download_and_save_ts(self):
with ThreadPoolExecutor(max_workers=30) as executor: with ThreadPoolExecutor(max_workers=30) as executor:
list(tqdm(executor.map(self.decrypt_and_save, range(len(self.segments)) ), total=len(self.segments), unit="bytes", unit_scale=True, unit_divisor=1024, desc="[yellow]Download")) list(tqdm(executor.map(self.decrypt_and_save, range(len(self.segments)) ), total=len(self.segments), unit="bytes", unit_scale=True, unit_divisor=1024, desc="[yellow]Download"))
if len(self.failed_segments) > 0:
console.log(f"[red]Segment ts: {self.failed_segments}, cant use audio")
def join_ts_files(self): def join_ts_files(self):
current_dir = os.path.dirname(os.path.realpath(__file__)) current_dir = os.path.dirname(os.path.realpath(__file__))

4
run.py
View File

@ -18,7 +18,9 @@ site_version = Page.get_version(domain)
def main(): def main():
msg_start() msg_start()
main_update() try: main_update()
except: console.print("[blue]Req github [white]=> [red]Failed")
console.print(f"[blue]Find system [white]=> [red]{sys.platform} \n") console.print(f"[blue]Find system [white]=> [red]{sys.platform} \n")
film_search = msg.ask("\n[blue]Insert word to search in all site: ").strip() film_search = msg.ask("\n[blue]Insert word to search in all site: ").strip()