forked from DRMTalks/devine
Shutdown HLS & DASH dl pool, pass exceptions to dl
This results in a noticeably faster speed cancelling segmented track downloads on CTRL+C and Errors. It's also reducing code duplication as the dl code will now handle the exception and cleanup for them. This also simplifies the STOPPING/STOPPED and FAILING/FAILED status messages by quite a bit.
This commit is contained in:
parent
fbe78308eb
commit
9f48aab80c
|
@ -4,10 +4,8 @@ import base64
|
|||
import logging
|
||||
import math
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
from concurrent import futures
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from copy import copy
|
||||
|
@ -450,7 +448,8 @@ class DASH:
|
|||
|
||||
def download_segment(filename: str, segment: tuple[str, Optional[str]]) -> int:
|
||||
if stop_event.is_set():
|
||||
return 0
|
||||
# the track already started downloading, but another failed or was stopped
|
||||
raise KeyboardInterrupt()
|
||||
|
||||
segment_save_path = (save_dir / filename).with_suffix(".mp4")
|
||||
|
||||
|
@ -507,8 +506,6 @@ class DASH:
|
|||
progress(total=len(segments))
|
||||
|
||||
finished_threads = 0
|
||||
has_stopped = False
|
||||
has_failed = False
|
||||
download_sizes = []
|
||||
last_speed_refresh = time.time()
|
||||
|
||||
|
@ -522,28 +519,27 @@ class DASH:
|
|||
for i, segment in enumerate(segments)
|
||||
)):
|
||||
finished_threads += 1
|
||||
|
||||
try:
|
||||
download_size = download.result()
|
||||
except KeyboardInterrupt:
|
||||
stop_event.set()
|
||||
stop_event.set() # skip pending track downloads
|
||||
progress(downloaded="[yellow]STOPPING")
|
||||
pool.shutdown(wait=True, cancel_futures=True)
|
||||
progress(downloaded="[yellow]STOPPED")
|
||||
# tell dl that it was cancelled
|
||||
# the pool is already shut down, so exiting loop is fine
|
||||
raise
|
||||
except Exception as e:
|
||||
stop_event.set()
|
||||
if has_stopped:
|
||||
# we don't care because we were stopping anyway
|
||||
continue
|
||||
if not has_failed:
|
||||
has_failed = True
|
||||
stop_event.set() # skip pending track downloads
|
||||
progress(downloaded="[red]FAILING")
|
||||
traceback.print_exception(e)
|
||||
log.error(f"Segment Download worker threw an unhandled exception: {e!r}")
|
||||
continue
|
||||
|
||||
if stop_event.is_set():
|
||||
if not has_stopped:
|
||||
has_stopped = True
|
||||
progress(downloaded="[orange]STOPPING")
|
||||
continue
|
||||
|
||||
pool.shutdown(wait=True, cancel_futures=True)
|
||||
progress(downloaded="[red]FAILED")
|
||||
# tell dl that it failed
|
||||
# the pool is already shut down, so exiting loop is fine
|
||||
raise e
|
||||
else:
|
||||
# it successfully downloaded, and it was not cancelled
|
||||
progress(advance=1)
|
||||
|
||||
now = time.time()
|
||||
|
@ -559,22 +555,13 @@ class DASH:
|
|||
last_speed_refresh = now
|
||||
download_sizes.clear()
|
||||
|
||||
try:
|
||||
if has_stopped:
|
||||
progress(downloaded="[yellow]STOPPED")
|
||||
return
|
||||
if has_failed:
|
||||
progress(downloaded="[red]FAILED")
|
||||
return
|
||||
|
||||
with open(save_path, "wb") as f:
|
||||
for segment_file in sorted(save_dir.iterdir()):
|
||||
f.write(segment_file.read_bytes())
|
||||
segment_file.unlink()
|
||||
|
||||
track.path = save_path
|
||||
finally:
|
||||
shutil.rmtree(save_dir)
|
||||
save_dir.rmdir()
|
||||
|
||||
@staticmethod
|
||||
def get_language(*options: Any) -> Optional[Language]:
|
||||
|
|
|
@ -2,10 +2,8 @@ from __future__ import annotations
|
|||
|
||||
import logging
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
from concurrent import futures
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from functools import partial
|
||||
|
@ -217,7 +215,8 @@ class HLS:
|
|||
|
||||
def download_segment(filename: str, segment: m3u8.Segment, init_data: Queue, segment_key: Queue) -> int:
|
||||
if stop_event.is_set():
|
||||
return 0
|
||||
# the track already started downloading, but another failed or was stopped
|
||||
raise KeyboardInterrupt()
|
||||
|
||||
segment_save_path = (save_dir / filename).with_suffix(".mp4")
|
||||
|
||||
|
@ -345,8 +344,6 @@ class HLS:
|
|||
progress(total=len(master.segments))
|
||||
|
||||
finished_threads = 0
|
||||
has_stopped = False
|
||||
has_failed = False
|
||||
download_sizes = []
|
||||
last_speed_refresh = time.time()
|
||||
|
||||
|
@ -362,28 +359,27 @@ class HLS:
|
|||
for i, segment in enumerate(master.segments)
|
||||
)):
|
||||
finished_threads += 1
|
||||
|
||||
try:
|
||||
download_size = download.result()
|
||||
except KeyboardInterrupt:
|
||||
stop_event.set()
|
||||
stop_event.set() # skip pending track downloads
|
||||
progress(downloaded="[yellow]STOPPING")
|
||||
pool.shutdown(wait=True, cancel_futures=True)
|
||||
progress(downloaded="[yellow]STOPPED")
|
||||
# tell dl that it was cancelled
|
||||
# the pool is already shut down, so exiting loop is fine
|
||||
raise
|
||||
except Exception as e:
|
||||
stop_event.set()
|
||||
if has_stopped:
|
||||
# we don't care because we were stopping anyway
|
||||
continue
|
||||
if not has_failed:
|
||||
has_failed = True
|
||||
stop_event.set() # skip pending track downloads
|
||||
progress(downloaded="[red]FAILING")
|
||||
traceback.print_exception(e)
|
||||
log.error(f"Segment Download worker threw an unhandled exception: {e!r}")
|
||||
continue
|
||||
|
||||
if stop_event.is_set():
|
||||
if not has_stopped:
|
||||
has_stopped = True
|
||||
progress(downloaded="[orange]STOPPING")
|
||||
continue
|
||||
|
||||
pool.shutdown(wait=True, cancel_futures=True)
|
||||
progress(downloaded="[red]FAILED")
|
||||
# tell dl that it failed
|
||||
# the pool is already shut down, so exiting loop is fine
|
||||
raise e
|
||||
else:
|
||||
# it successfully downloaded, and it was not cancelled
|
||||
progress(advance=1)
|
||||
|
||||
now = time.time()
|
||||
|
@ -399,22 +395,13 @@ class HLS:
|
|||
last_speed_refresh = now
|
||||
download_sizes.clear()
|
||||
|
||||
try:
|
||||
if has_stopped:
|
||||
progress(downloaded="[yellow]STOPPED")
|
||||
return
|
||||
if has_failed:
|
||||
progress(downloaded="[red]FAILED")
|
||||
return
|
||||
|
||||
with open(save_path, "wb") as f:
|
||||
for segment_file in sorted(save_dir.iterdir()):
|
||||
f.write(segment_file.read_bytes())
|
||||
segment_file.unlink()
|
||||
|
||||
track.path = save_path
|
||||
finally:
|
||||
shutil.rmtree(save_dir)
|
||||
save_dir.rmdir()
|
||||
|
||||
@staticmethod
|
||||
def get_drm(
|
||||
|
|
Loading…
Reference in New Issue