mirror of
https://github.com/Arrowar/StreamingCommunity.git
synced 2025-06-08 20:45:25 +00:00
fix ubuntu bug
This commit is contained in:
parent
941abc4f13
commit
5aeeceb309
@ -6,7 +6,7 @@
|
|||||||
This repository provide a simple script designed to facilitate the downloading of films and series from a popular streaming community platform. The script allows users to download individual films, entire series, or specific episodes, providing a seamless experience for content consumers.
|
This repository provide a simple script designed to facilitate the downloading of films and series from a popular streaming community platform. The script allows users to download individual films, entire series, or specific episodes, providing a seamless experience for content consumers.
|
||||||
|
|
||||||
## Join us
|
## Join us
|
||||||
You can chat, help improve this repo, or just hang around for some fun in the **Git_StreamingCommunity** Discord Server: hhttps://discord.gg/8QRPaH6Y
|
You can chat, help improve this repo, or just hang around for some fun in the **Git_StreamingCommunity** Discord [Server](https://discord.gg/6K9KeDm5)
|
||||||
|
|
||||||
# Table of Contents
|
# Table of Contents
|
||||||
* [INSTALLATION](#installation)
|
* [INSTALLATION](#installation)
|
||||||
|
@ -54,18 +54,16 @@ class M3U8_Parser:
|
|||||||
self.audio_ts = []
|
self.audio_ts = []
|
||||||
|
|
||||||
def parse_data(self, m3u8_content):
|
def parse_data(self, m3u8_content):
|
||||||
"""Extract all info present in m3u8 content"""
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
m3u8_obj = M3U8_Lib(m3u8_content)
|
m3u8_obj = M3U8_Lib(m3u8_content)
|
||||||
|
|
||||||
for playlist in m3u8_obj.playlists:
|
for playlist in m3u8_obj.playlists:
|
||||||
self.video_playlist.append({"uri": playlist.uri})
|
self.video_playlist.append({
|
||||||
self.stream_infos = ({
|
"uri": playlist.uri,
|
||||||
"bandwidth": playlist.stream_info.bandwidth,
|
"width": playlist.stream_info.resolution,
|
||||||
"codecs": playlist.stream_info.codecs,
|
"codecs": playlist.stream_info.codecs
|
||||||
"resolution": playlist.stream_info.resolution
|
})
|
||||||
})
|
|
||||||
|
|
||||||
for key in m3u8_obj.keys:
|
for key in m3u8_obj.keys:
|
||||||
if key is not None:
|
if key is not None:
|
||||||
@ -84,7 +82,8 @@ class M3U8_Parser:
|
|||||||
"language": media.language,
|
"language": media.language,
|
||||||
"uri": media.uri
|
"uri": media.uri
|
||||||
})
|
})
|
||||||
else:
|
|
||||||
|
if media.type == "AUDIO":
|
||||||
self.audio_ts.append({
|
self.audio_ts.append({
|
||||||
"type": media.type,
|
"type": media.type,
|
||||||
"name": media.name,
|
"name": media.name,
|
||||||
@ -111,7 +110,6 @@ class M3U8_Parser:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def download_subtitle(self, subtitle_path, content_name):
|
def download_subtitle(self, subtitle_path, content_name):
|
||||||
"""Download all subtitle if present"""
|
|
||||||
|
|
||||||
path = subtitle_path
|
path = subtitle_path
|
||||||
|
|
||||||
@ -134,16 +132,13 @@ class M3U8_Parser:
|
|||||||
else:
|
else:
|
||||||
subtitle_name = f"{content_name}.{name_language}.vtt"
|
subtitle_name = f"{content_name}.{name_language}.vtt"
|
||||||
|
|
||||||
# Save vtt to path
|
open(os.path.join(path, subtitle_name), "wb"
|
||||||
open(
|
|
||||||
os.path.join(path, subtitle_name), "wb"
|
|
||||||
).write(requests.get(url_subtitle).content)
|
).write(requests.get(url_subtitle).content)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
console.log("[red]No subtitle found")
|
console.log("[red]No subtitle found")
|
||||||
|
|
||||||
def get_track_audio(self, language_name): # Ex. English
|
def get_track_audio(self, language_name):
|
||||||
"""Return url of audio eng audio playlist if present"""
|
|
||||||
|
|
||||||
if self.audio_ts:
|
if self.audio_ts:
|
||||||
console.log(f"[cyan]Found {len(self.audio_ts)}, playlist with audio")
|
console.log(f"[cyan]Found {len(self.audio_ts)}, playlist with audio")
|
||||||
@ -172,8 +167,6 @@ class M3U8_Segments:
|
|||||||
self.max_retry = 3
|
self.max_retry = 3
|
||||||
|
|
||||||
def parse_data(self, m3u8_content):
|
def parse_data(self, m3u8_content):
|
||||||
|
|
||||||
# Parse index m3u8
|
|
||||||
m3u8_parser = M3U8_Parser()
|
m3u8_parser = M3U8_Parser()
|
||||||
m3u8_parser.parse_data(m3u8_content)
|
m3u8_parser.parse_data(m3u8_content)
|
||||||
|
|
||||||
@ -185,8 +178,6 @@ class M3U8_Segments:
|
|||||||
self.segments = m3u8_parser.segments
|
self.segments = m3u8_parser.segments
|
||||||
|
|
||||||
def get_info(self):
|
def get_info(self):
|
||||||
"""Make req to index m3u8"""
|
|
||||||
|
|
||||||
response = requests.get(self.url, headers={'user-agent': get_headers()})
|
response = requests.get(self.url, headers={'user-agent': get_headers()})
|
||||||
|
|
||||||
if response.ok:
|
if response.ok:
|
||||||
@ -201,8 +192,6 @@ class M3U8_Segments:
|
|||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
def get_req_ts(self, ts_url):
|
def get_req_ts(self, ts_url):
|
||||||
"""Single req to a ts file to get content"""
|
|
||||||
|
|
||||||
url_number = self.segments.index(ts_url)
|
url_number = self.segments.index(ts_url)
|
||||||
|
|
||||||
is_valid = True
|
is_valid = True
|
||||||
@ -214,7 +203,7 @@ class M3U8_Segments:
|
|||||||
if is_valid:
|
if is_valid:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = requests.get(ts_url, headers={'user-agent': get_headers()}, timeout=10)
|
response = requests.get(ts_url, headers={'user-agent': get_headers()}, timeout=5)
|
||||||
|
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
return response.content
|
return response.content
|
||||||
@ -229,8 +218,10 @@ class M3U8_Segments:
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def save_ts(self, index, progress_counter, quit_event):
|
def save_ts(self, index, progress_counter, stop_event):
|
||||||
"""Save ts file and decrypt if there is iv present in decryption class"""
|
|
||||||
|
if stop_event.is_set():
|
||||||
|
return
|
||||||
|
|
||||||
ts_url = self.segments[index]
|
ts_url = self.segments[index]
|
||||||
ts_filename = os.path.join(self.temp_folder, f"{index}.ts")
|
ts_filename = os.path.join(self.temp_folder, f"{index}.ts")
|
||||||
@ -250,35 +241,32 @@ class M3U8_Segments:
|
|||||||
|
|
||||||
def download_ts(self):
|
def download_ts(self):
|
||||||
progress_counter = tqdm(total=len(self.segments), unit="bytes", desc="[yellow]Download")
|
progress_counter = tqdm(total=len(self.segments), unit="bytes", desc="[yellow]Download")
|
||||||
|
stop_event = threading.Event()
|
||||||
|
progress_thread = threading.Thread(target=self.timer, args=(progress_counter, stop_event))
|
||||||
|
progress_thread.start()
|
||||||
|
|
||||||
quit_event = threading.Event()
|
with ThreadPoolExecutor(max_workers=MAX_WORKER) as executor:
|
||||||
timeout_occurred = False
|
futures = []
|
||||||
|
|
||||||
timer_thread = threading.Thread(target=self.timer, args=(progress_counter, quit_event, lambda: timeout_occurred))
|
# Submit tasks for downloading segments
|
||||||
timer_thread.start()
|
for index in range(len(self.segments)):
|
||||||
|
future = executor.submit(self.save_ts, index, progress_counter, stop_event)
|
||||||
try:
|
futures.append(future)
|
||||||
with ThreadPoolExecutor(max_workers=MAX_WORKER) as executor:
|
|
||||||
futures = []
|
|
||||||
for index in range(len(self.segments)):
|
|
||||||
if timeout_occurred:
|
|
||||||
break
|
|
||||||
future = executor.submit(self.save_ts, index, progress_counter, quit_event)
|
|
||||||
futures.append(future)
|
|
||||||
|
|
||||||
|
try:
|
||||||
for future in as_completed(futures):
|
for future in as_completed(futures):
|
||||||
try:
|
future.result()
|
||||||
future.result()
|
if progress_counter.n >= len(self.segments) * 0.995:
|
||||||
except Exception as e:
|
console.log(f"[yellow]Progress reached {0.995*100}%. Stopping.")
|
||||||
print(f"An error occurred: {str(e)}")
|
break
|
||||||
|
|
||||||
finally:
|
except KeyboardInterrupt:
|
||||||
progress_counter.close()
|
console.log("[red]Ctrl+C detected. Exiting gracefully [white]...")
|
||||||
quit_event.set()
|
stop_event.set()
|
||||||
timer_thread.join()
|
|
||||||
|
|
||||||
|
progress_thread.join()
|
||||||
|
|
||||||
def timer(self, progress_counter, quit_event, timeout_checker):
|
def timer(self, progress_counter, quit_event):
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
last_count = 0
|
last_count = 0
|
||||||
|
|
||||||
@ -290,13 +278,11 @@ class M3U8_Segments:
|
|||||||
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. Stopping.")
|
||||||
console.log("[red]Breaking ThreadPoolExecutor...")
|
|
||||||
timeout_checker()
|
|
||||||
quit_event.set()
|
quit_event.set()
|
||||||
break
|
break
|
||||||
|
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
progress_counter.refresh()
|
progress_counter.refresh()
|
||||||
@ -320,13 +306,11 @@ class M3U8_Segments:
|
|||||||
relative_path = os.path.relpath(os.path.join(self.temp_folder, ts_file))
|
relative_path = os.path.relpath(os.path.join(self.temp_folder, ts_file))
|
||||||
f.write(f"file '{relative_path}'\n")
|
f.write(f"file '{relative_path}'\n")
|
||||||
|
|
||||||
#console.log("[cyan]Joining all files...")
|
|
||||||
try:
|
try:
|
||||||
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}")
|
||||||
|
|
||||||
#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)
|
||||||
|
|
||||||
|
9
run.py
9
run.py
@ -11,13 +11,16 @@ from Src.Upload.update import main_update
|
|||||||
from Src.Lib.FFmpeg.installer import check_ffmpeg
|
from Src.Lib.FFmpeg.installer import check_ffmpeg
|
||||||
|
|
||||||
# Import
|
# Import
|
||||||
import sys
|
import sys, platform
|
||||||
|
|
||||||
def initialize():
|
def initialize():
|
||||||
"""
|
"""
|
||||||
Initializes the application by performing necessary setup tasks.
|
Initializes the application by performing necessary setup tasks.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# Get system where script is run
|
||||||
|
run_system = platform.system()
|
||||||
|
|
||||||
# Checking Python version
|
# Checking Python version
|
||||||
if sys.version_info < (3, 11):
|
if sys.version_info < (3, 11):
|
||||||
console.log("Install python version > 3.11")
|
console.log("Install python version > 3.11")
|
||||||
@ -34,7 +37,9 @@ def initialize():
|
|||||||
console.print(f"[blue]Request GitHub [white]=> [red]Failed: {e}")
|
console.print(f"[blue]Request GitHub [white]=> [red]Failed: {e}")
|
||||||
|
|
||||||
# Checking FFmpeg installation
|
# Checking FFmpeg installation
|
||||||
check_ffmpeg()
|
if run_system != 'Windows':
|
||||||
|
check_ffmpeg()
|
||||||
|
|
||||||
print("\n")
|
print("\n")
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user