Skip to content

Commit

Permalink
:[Dev] 加入模擬人類觀看速度功能
Browse files Browse the repository at this point in the history
  • Loading branch information
dream-rhythm committed Nov 26, 2024
1 parent 8de20f3 commit 028c56b
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 11 deletions.
50 changes: 43 additions & 7 deletions Anime.py
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,32 @@ def __get_temp_filename(self, resolution, temp_suffix):
+ '.' + self._settings['video_filename_extension']
temp_filename = Config.legalize_filename(temp_filename)
return temp_filename


def __parsem3u8_video_list(self, m3u8_text):
m3u8 = []
re_time = re.compile(r'\d*.\d*,') # 取得時間
re_name = re.compile(r'media_b.+ts.*') # 取得檔名

chunklist = re.findall(r'#EXTINF:.+,.*\nmedia_b.+ts.*', m3u8_text) # chunk

if len(chunklist) == 0:
# 如果帶時間的解析方法失敗,則採僅解析檔名
chunklist = re.findall(r'media_b.+ts.*', m3u8_text) # chunk
for chunk in chunklist:
m3u8.append({
'ts_time' : 0,
'ts_name': chunk,
})
else:
for chunk in chunklist:
ts_time = re_time.search(chunk).group(0)
ts_name = re_name.search(chunk).group(0)
m3u8.append({
'ts_time' : float(ts_time[:-1]),
'ts_name': ts_name,
})
return m3u8

def __segment_download_mode(self, resolution=''):
# 设定文件存放路径
filename = self.__get_filename(resolution)
Expand Down Expand Up @@ -645,14 +670,15 @@ def __segment_download_mode(self, resolution=''):
with open(m3u8_key_path, 'wb') as f: # 保存 key
f.write(self.__request(key_uri, no_cookies=True).content)

chunk_list = re.findall(r'media_b.+ts.*', m3u8_text) # chunk
chunk_list = self.__parsem3u8_video_list(m3u8_text)

limiter = threading.Semaphore(self._settings['multi_downloading_segment']) # chunk 并发下载限制器
total_chunk_num = len(chunk_list)
finished_chunk_counter = 0
failed_flag = False

def download_chunk(uri):
def download_chunk(uri, chunk_time):
chunk_shoud_end_time = time.time() + chunk_time # 此chunk影片時間(用於下載限速 0=不限速)
chunk_name = re.findall(r'media_b.+ts', uri)[0] # chunk 文件名
chunk_local_path = os.path.join(temp_dir, chunk_name) # chunk 路径
nonlocal failed_flag
Expand Down Expand Up @@ -683,6 +709,10 @@ def download_chunk(uri):
if self.realtime_show_file_size:
sys.stdout.write('\r正在下載: sn=' + str(self._sn) + ' ' + filename + ' ' + str(progress_rate) + '% ')
sys.stdout.flush()

# 下載限速
while time.time() < chunk_shoud_end_time:
time.sleep(1)
limiter.release()

if self.realtime_show_file_size:
Expand All @@ -694,8 +724,9 @@ def download_chunk(uri):

chunk_tasks_list = []
for chunk in chunk_list:
chunk_uri = url_path + '/' + chunk
task = threading.Thread(target=download_chunk, args=(chunk_uri,))
chunk_uri = url_path + '/' + chunk['ts_name']
chunk_time = chunk['ts_time'] if self._settings['simulator_human_watching'] else 0
task = threading.Thread(target=download_chunk, args=(chunk_uri, chunk_time))
chunk_tasks_list.append(task)
task.daemon = True
limiter.acquire()
Expand All @@ -716,9 +747,9 @@ def download_chunk(uri):
# replace('\\', '\\\\') 为转义win路径
m3u8_text_local_version = m3u8_text.replace(original_key_uri, os.path.join(temp_dir, 'key.m3u8key')).replace('\\', '\\\\')
for chunk in chunk_list:
chunk_filename = re.findall(r'media_b.+ts', chunk)[0] # chunk 文件名
chunk_filename = re.findall(r'media_b.+ts', chunk['ts_name'])[0] # chunk 文件名
chunk_path = os.path.join(temp_dir, chunk_filename).replace('\\', '\\\\') # chunk 本地路径
m3u8_text_local_version = m3u8_text_local_version.replace(chunk, chunk_path)
m3u8_text_local_version = m3u8_text_local_version.replace(chunk['ts_name'], chunk_path)
with open(m3u8_path, 'w', encoding='utf-8') as f: # 保存本地化的 m3u8
f.write(m3u8_text_local_version)

Expand Down Expand Up @@ -984,6 +1015,11 @@ def download(self, resolution='', save_dir='', bangumi_tag='', realtime_show_fil
Config.tasks_progress_rate[int(self._sn)]['status'] = '正在下載'
Config.tasks_progress_rate[int(self._sn)]['filename'] = self.get_filename()

# 設定模擬人類觀看速度時,強制開啟分段下載,並設定分段併發數為1
if self._settings['simulator_human_watching']:
self._settings['multi_downloading_segment'] = 1
self._settings['segment_download_mode'] = True

if self._settings['segment_download_mode']:
self.__segment_download_mode(resolution)
else:
Expand Down
7 changes: 6 additions & 1 deletion Config.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
cookie_path = os.path.join(working_dir, 'cookie.txt')
logs_dir = os.path.join(working_dir, 'logs')
aniGamerPlus_version = 'v24.6'
latest_config_version = 17.2
latest_config_version = 24.6
latest_database_version = 2.0
cookie = None
max_multi_thread = 5
Expand Down Expand Up @@ -94,6 +94,7 @@ def __init_settings():
'multi_upload': 3, # 最大并发上传数
'segment_download_mode': True, # 由 aniGamerPlus 下载分段, False 为 ffmpeg 下载
'multi_downloading_segment': 2, # 在上面配置为 True 时有效, 每个视频并发下载分段数
'simulator_human_watching': False, # 模擬人類觀看時間, True時會強迫開啟分段下載,並設置分段併發數為1
'segment_max_retry': 8, # 在分段下载模式时有效, 每个分段最大重试次数, -1 为 无限重试
'add_bangumi_name_to_video_filename': True,
'add_resolution_to_video_filename': True, # 是否在文件名中添加清晰度说明
Expand Down Expand Up @@ -386,6 +387,10 @@ def __update_settings(old_settings): # 升级配置文件
# v24.4 sn解析冷卻時間(秒)
new_settings['parse_sn_cd'] = 5

if 'simulator_human_watching' not in new_settings.keys():
# v24.6 模擬人類觀看速度
new_settings['simulator_human_watching'] = True

new_settings['config_version'] = latest_config_version
with open(config_path, 'w', encoding='utf-8') as f:
json.dump(new_settings, f, ensure_ascii=False, indent=4)
Expand Down
23 changes: 22 additions & 1 deletion Dashboard/static/js/aniGamerPlus.js
Original file line number Diff line number Diff line change
Expand Up @@ -245,4 +245,25 @@ function showSnList(){
$.get("data/sn_list", function(data) {
$("#sn_list").val(data);
})
}
}

$().ready(() => {
$('#simulator_human_watching').on('switchChange.bootstrapSwitch', function(event, state) {
if(state){
// 如果啟用模擬人類觀看速度
// 下載併發數須為1
// 分段下載功能需被開啟
$('#multi_downloading_segment').val('1');
$('#multi_downloading_segment').attr('readonly', true);

$('#segment_download_mode').bootstrapSwitch('state', true);
$('#segment_download_mode').bootstrapSwitch('toggleReadonly',true);
}else{
// 如果停用模擬人類觀看速度
// 解鎖下載併發數
// 解鎖分段下載功能
$('#multi_downloading_segment').removeAttr('readonly');
$('#segment_download_mode').bootstrapSwitch('toggleReadonly',false);
}
});
})
3 changes: 2 additions & 1 deletion Dashboard/static/js/settings_id_list.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ var id_list = [
'save_logs',
'quantity_of_logs',
'download_cd',
'parse_sn_cd'
'parse_sn_cd',
'simulator_human_watching'
]
7 changes: 6 additions & 1 deletion Dashboard/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ <h4 class="modal-title">手動添加任務</h4>
<input id="manual_danmu" type="checkbox" data-toggle="switch" data-on-color="success"  data-size="normal" />
</div>
</div>

<div class="row input-group setting-content" style="max-width: 15rem;">
<div class="input-group-prepend">
<span class="input-group-text">最大并發下載數</span>
Expand Down Expand Up @@ -282,6 +281,12 @@ <h2 class="col">下載設定</h2>
<input id="danmu" type="checkbox" data-toggle="switch" data-on-color="success"  data-size="normal" />
</div>
</div>
<div class="input-group col-md-4 my-button">
<div class="input-group-prepend">
<span class="input-group-text">模擬人類觀看速度</span>
<input id="simulator_human_watching" type="checkbox" data-toggle="switch" data-on-color="success"  data-size="normal" />
</div>
</div>
<div class="input-group col-md-4 my-button">
<div class="input-group-prepend">
<span class="input-group-text">下載解析度  </span>
Expand Down

0 comments on commit 028c56b

Please sign in to comment.