117 lines
4.8 KiB
Python
117 lines
4.8 KiB
Python
import requests, pathlib
|
|
import math, subprocess
|
|
import os, sys, shutil
|
|
|
|
class WvDownloader(object):
|
|
def __init__(self, config):
|
|
self.xml = config.xml
|
|
self.output_file = config.output_file
|
|
self.config = config
|
|
|
|
def download_track(self, aria2c_infile, file_name):
|
|
aria2c_opts = [
|
|
'aria2c',
|
|
'--enable-color=false',
|
|
'--allow-overwrite=true',
|
|
'--summary-interval=0',
|
|
'--download-result=hide',
|
|
'--async-dns=false',
|
|
'--check-certificate=false',
|
|
'--auto-file-renaming=false',
|
|
'--file-allocation=none',
|
|
'--console-log-level=warn',
|
|
'-x16', '-s16', '-j16',
|
|
'-i', aria2c_infile]
|
|
subprocess.run(aria2c_opts)
|
|
|
|
source_files = pathlib.Path(temp_folder).rglob(r'./*.mp4')
|
|
with open(file_name, mode='wb') as (destination):
|
|
for file in source_files:
|
|
with open(file, mode='rb') as (source):
|
|
shutil.copyfileobj(source, destination)
|
|
if os.path.exists(temp_folder):
|
|
shutil.rmtree(temp_folder)
|
|
os.remove(aria2c_infile)
|
|
print('\nDone!')
|
|
|
|
def process_url_templace(self, template, representation_id, bandwidth, time, number):
|
|
if representation_id is not None: result = template.replace('$RepresentationID$', representation_id)
|
|
if number is not None:
|
|
nstart = result.find('$Number')
|
|
if nstart >= 0:
|
|
nend = result.find('$', nstart+1)
|
|
if nend >= 0:
|
|
var = result[nstart+1 : nend]
|
|
if 'Number%' in var:
|
|
value = var[6:] % (int(number))
|
|
else:
|
|
value = number
|
|
result = result.replace('$'+var+'$', value)
|
|
if bandwidth is not None: result = result.replace('$Bandwidth$', bandwidth)
|
|
if time is not None: result = result.replace('$Time$', time)
|
|
result = result.replace('$$', '$').replace('../', '')
|
|
return result
|
|
|
|
def generate_segments(self):
|
|
segment_template = self.get_segment_template()
|
|
return self.get_segments(segment_template)
|
|
|
|
def get_segments(self, segment_template):
|
|
urls = []
|
|
urls.append(self.config.base_url + segment_template['@initialization'].replace('$RepresentationID$', self.config.format_id))
|
|
current_number = 1
|
|
for seg in self.force_segmentimeline(segment_template):
|
|
if '@t' in seg:
|
|
current_time = seg['@t']
|
|
for i in range(int(seg.get('@r', 0)) + 1):
|
|
urls.append(self.config.base_url + self.process_url_templace(segment_template['@media'],
|
|
representation_id=self.config.format_id,
|
|
bandwidth=None, time=str(current_time), number=str(current_number)))
|
|
current_number += 1
|
|
current_time += seg['@d']
|
|
return urls
|
|
|
|
def force_segmentimeline(self, segment_timeline):
|
|
if isinstance(segment_timeline['SegmentTimeline']['S'], list):
|
|
x16 = segment_timeline['SegmentTimeline']['S']
|
|
else:
|
|
x16 = [segment_timeline['SegmentTimeline']['S']]
|
|
return x16
|
|
|
|
def force_instance(self, x):
|
|
if isinstance(x['Representation'], list):
|
|
X = x['Representation']
|
|
else:
|
|
X = [x['Representation']]
|
|
return X
|
|
|
|
def get_segment_template(self):
|
|
x = [item for (i, item) in enumerate(self.xml['MPD']['Period']['AdaptationSet']) if self.config.track_id == item["@id"]][0]
|
|
segment_level = [item['SegmentTemplate'] for (i, item) in enumerate(self.force_instance(x)) if self.config.format_id == item["@id"]][0]
|
|
return segment_level
|
|
|
|
def run(self):
|
|
urls = self.generate_segments()
|
|
|
|
print('\n' + self.output_file)
|
|
global temp_folder
|
|
aria2c_infile = 'aria2c_infile.txt'
|
|
if os.path.isfile(aria2c_infile):
|
|
os.remove(aria2c_infile)
|
|
temp_folder = self.output_file.replace('.mp4', '')
|
|
if os.path.exists(temp_folder):
|
|
shutil.rmtree(temp_folder)
|
|
if not os.path.exists(temp_folder):
|
|
os.makedirs(temp_folder)
|
|
|
|
if len(urls) > 1:
|
|
num_segments = int(math.log10(len(urls))) + 1
|
|
with open(aria2c_infile, 'a', encoding='utf8') as (file):
|
|
for (i, url) in enumerate(urls):
|
|
file.write(f'{url}\n')
|
|
file.write(f'\tout={temp_folder}.{i:0{num_segments}d}.mp4\n')
|
|
file.write(f'\tdir={temp_folder}\n')
|
|
file.flush()
|
|
self.download_track(aria2c_infile, self.output_file)
|
|
print('Done!')
|