From edd760cc46e770c689c2285ed4538dbcab0d24cd Mon Sep 17 00:00:00 2001 From: XuanRan_Nyan <31968665+xxxxuanran@users.noreply.github.com> Date: Sun, 19 Mar 2023 10:48:47 +0800 Subject: [PATCH] Optimize the plugin code of Douyu and Bilibili (#386) * Optimize the plugin code of Douyu and Bilibili * Fix some wrong * Fix some wrong * fix some wrong --- .gitignore | 3 +- biliup/engine/download.py | 25 ++++- biliup/plugins/bilibili.py | 203 ++++++++++++++----------------------- biliup/plugins/douyu.py | 47 +++++---- public/config.toml | 28 ++--- public/config.yaml | 35 +++---- 6 files changed, 153 insertions(+), 188 deletions(-) diff --git a/.gitignore b/.gitignore index c85682c..8e39de7 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,7 @@ *.part backup venv./ -config.yaml +config*.yaml !public/config.yaml /configlog.ini ds_update.log* @@ -16,6 +16,7 @@ ds_update.log* *.egg-info dist/ build/ +cover/ *.back bili.cookie.json diff --git a/biliup/engine/download.py b/biliup/engine/download.py index f97afe6..195dc08 100644 --- a/biliup/engine/download.py +++ b/biliup/engine/download.py @@ -39,7 +39,7 @@ class DownloadBase: 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3', - 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:60.1) Gecko/20100101 Firefox/60.1' + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36' } self.default_output_args = [ @@ -68,7 +68,7 @@ class DownloadBase: if self.downloader == 'stream-gears': stream_gears_download(self.raw_stream_url, self.fake_headers, filename, config.get('segment_time'), config.get('file_size')) - elif self.downloader == 'streamlink': + elif self.downloader == 'streamlink': parsed_url = urlparse(self.raw_stream_url) path = parsed_url.path if '.flv' in path: #streamlink无法处理flv,所以回退到ffmpeg @@ -77,7 +77,24 @@ class DownloadBase: self.streamlink_download(fmtname) else: self.ffmpeg_download(fmtname) - + + def get_live_cover(self, uname, room_id, filename, timestamp, cover_url): + import requests + headers = self.fake_headers.copy() + response = requests.get(cover_url, headers=headers, timeout=5) + save_dir = f'cover/{uname}_{room_id}/' + local_time = time.strftime('%Y-%m-%d_%H-%M-%S', time.localtime(timestamp)) + if not os.path.exists(save_dir): + os.makedirs(save_dir) + cover_file_name = get_valid_filename(f'{filename}_{local_time}.png') + live_cover_path = f'{save_dir}{cover_file_name}' + if os.path.exists(live_cover_path): + return live_cover_path + else: + with open(live_cover_path, 'wb') as f: + f.write(response.content) + return live_cover_path + def streamlink_download(self, filename): #streamlink+ffmpeg混合下载模式,适用于下载hls流 streamlink_input_args = ['--stream-segment-threads', '5'] streamlink_cmd = ['streamlink', *streamlink_input_args, self.raw_stream_url, 'best', '-O'] @@ -93,7 +110,7 @@ class DownloadBase: ffmpeg_proc = subprocess.Popen(ffmpeg_cmd, stdin=streamlink_proc.stdout, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) try: with ffmpeg_proc.stdout as stdout: - for line in iter(stdout.readline, b''): + for line in iter(stdout.readline, b''): decode_line = line.decode(errors='ignore') print(decode_line, end='', file=sys.stderr) logger.debug(decode_line.rstrip()) diff --git a/biliup/plugins/bilibili.py b/biliup/plugins/bilibili.py index 0a42e25..bcd32be 100644 --- a/biliup/plugins/bilibili.py +++ b/biliup/plugins/bilibili.py @@ -1,5 +1,3 @@ -import os -import random import re import time import requests @@ -15,135 +13,121 @@ from ..engine.download import DownloadBase class Bilibili(DownloadBase): def __init__(self, fname, url, suffix='flv'): super().__init__(fname, url, suffix) - self.fake_headers['User-Agent'] = 'Mozilla/5.0 (X11; Linux x86_64; rv:60.1) Gecko/20100101 Firefox/60.1' self.fake_headers['Referer'] = 'https://live.bilibili.com' - if config.get('user', {}).get('bili_cookie'): - self.fake_headers['cookie'] = config.get('user', {}).get('bili_cookie') - self.customAPI_use_cookie = config.get('user', {}).get('customAPI_use_cookie') - self.bili_cdn_fallback = config.get('bili_cdn_fallback', True) + self.customAPI_use_cookie = config.get('user', {}).get('customAPI_use_cookie', False) self.use_live_cover = config.get('use_live_cover', False) self.bilibili_danmaku = config.get('bilibili_danmaku', False) + if config.get('user', {}).get('bili_cookie') is not None: + self.fake_headers['cookie'] = config.get('user', {}).get('bili_cookie') def check_stream(self): # 预读配置 params = { 'room_id': match1(self.url, r'/(\d+)'), - 'protocol': '0,1', - 'format': '0,1,2', - 'codec': '0,1', + 'protocol': '0,1',# 0: http_stream, 1: http_hls + 'format': '0,1,2',# 0: flv, 1: ts, 2: fmp4 + 'codec': '0', # 0: avc, 1: hevc 'qn': '10000', 'platform': config.get('biliplatform', 'web'), - # 'ptype': '8', 'dolby': '5', 'panorama': '1' } protocol = config.get('bili_protocol', 'stream') perf_cdn = config.get('bili_perfCDN') - force_source = config.get('bili_force_source') - force_ov05_ip = config.get('bili_force_ov05_ip') - force_cn01_domain = config.get('bili_force_cn01_domains') + bili_cdn_fallback = config.get('bili_cdn_fallback', True) + force_source = config.get('bili_force_source', False) + ov05_ip = config.get('bili_force_ov05_ip') + cn01_domains = config.get('bili_force_cn01_domains', '').split(",") official_api_host = "https://api.live.bilibili.com" with requests.Session() as s: s.headers = self.fake_headers.copy() # 获取直播状态与房间标题 info_by_room_url = f"{official_api_host}/xlive/web-room/v1/index/getInfoByRoom?room_id={params['room_id']}" try: - room_info = s.get(info_by_room_url, timeout=5).json() + room_info = s.get(info_by_room_url, timeout=3).json() except requests.exceptions.ConnectionError: logger.error(f"在连接到 {info_by_room_url} 时出现错误") return False if room_info['code'] != 0 or room_info['data']['room_info']['live_status'] != 1: logger.debug(room_info['message']) return False - room_id = room_info['data']['room_info']['room_id'] cover_url = room_info['data']['room_info']['cover'] live_start_time = room_info['data']['room_info']['live_start_time'] uname = room_info['data']['anchor_info']['base_info']['uname'] - room_title = room_info['data']['room_info']['title'] + self.room_title = room_info['data']['room_info']['title'] if self.use_live_cover is True: # 获取直播封面并保存到cover目录下 try: - self.live_cover_path = get_live_cover(uname, room_id, room_title, live_start_time, cover_url) + self.live_cover_path = \ + super().get_live_cover(uname, params['room_id'], self.room_title, live_start_time, cover_url) except: logger.error(f"获取直播封面失败") - params['room_id'] = room_info['data']['room_info']['room_id'] - self.room_title = room_info['data']['room_info']['title'] custom_api = config.get('bili_liveapi') is not None # 当 Cookie 存在,并且自定义APi使用Cookie开关关闭时,仅使用官方 Api - if config.get('user', {}).get('bili_cookie') and self.customAPI_use_cookie is not True: + if config.get('user', {}).get('bili_cookie') and self.customAPI_use_cookie: custom_api = False play_info = get_play_info(s, custom_api, official_api_host, params) - if play_info['code'] != 0: - logger.debug(play_info['message']) + if play_info['code'] != 0: + logger.debug(play_info['message']) + return False + streams = play_info['data']['playurl_info']['playurl']['stream'] + stream = streams[1] if protocol.startswith('hls') else streams[0] + if protocol == "hls_fmp4": + if len(stream['format']) > 1: + stream_info = stream['format'][1]['codec'][0] + elif int(time.time()) - live_start_time <= 45: # 等待45s,如果还没有fmp4流就回退到flv流 return False - streams = play_info['data']['playurl_info']['playurl']['stream'] - live_start_time = room_info['data']['room_info']['live_start_time'] - if protocol == "stream": - stream = streams[0] - stream_info = stream['format'][0]['codec'][0] - elif protocol == "hls_ts" or protocol == "hls": - stream = streams[1] - stream_info = stream['format'][0]['codec'][0] - elif protocol == "hls_fmp4": - try: - stream = streams[1] - stream_info = stream['format'][1]['codec'][0] - logger.debug(f"获取到{uname}房间的fmp4流") - except: - now_timestamp = int(time.time()) - if now_timestamp - live_start_time <= 45: # 等待45s,如果还没有fmp4流就回退到flv流 - return False - else: - stream = streams[0] - stream_info = stream['format'][0]['codec'][0] - logger.debug(f"获取{uname}房间fmp4流失败,回退到flv流") - found_perf_cdn = False #优选CDN节点 - for url_info in stream_info['url_info']: - if perf_cdn and perf_cdn in url_info['extra']: - found_perf_cdn = True - logger.debug(f"找到了perfCDN{url_info['extra']}") - break - if not found_perf_cdn: #没找到优选CDN就回到第一个节点 - url_info['host'] = stream_info['url_info'][0]['host'] - url_info['extra'] = stream_info['url_info'][0]['extra'] - logger.debug(f"没找到perfCDN哦") - # 哔哩哔哩直播强制原画(仅限HLS_ts流的 cn-gotcha01 CDN). 并且仅当主播有二压的时候才自动去掉m3u8的_bluray前缀,避免stream-gears的疯狂分段bug - if force_source is True and "cn-gotcha01" in url_info['extra'] and "_bluray.m3u8" in stream_info['base_url']: - stream_info['base_url'] = re.sub(r'_bluray(?=.*m3u8)', "", stream_info['base_url']) - # 强制替换cn-gotcha01的节点为指定节点 注意:只有大陆ip才能获取到cn-gotcha01的节点。 - if force_cn01_domain and "cn-gotcha01" in url_info['extra']: - i = 0 - while i < 6: # 测试随机到的节点是否可用 - random_choice = random.choice(force_cn01_domain.split(",")) - i += 1 - try: # 发起 GET 请求,并获取响应状态码 - status_code = s.get(f"https://{random_choice}{stream_info['base_url']}{url_info['extra']}", - stream=True).status_code - if status_code == 200: # 如果响应状态码是 200,跳出循环 - break - except requests.exceptions.ConnectionError: # 如果发生连接异常,继续下一次循环 - logger.debug(f"随机到的域名 {random_choice} 无法访问,尝试重新发起随机。") - continue else: - logger.error(f"强制替换hls流的cn-gotcha01的节点为指定节点失败啦") - return False - logger.debug(f"随机到的域名 {random_choice} 返回了 200 状态码。") - url_info['host'] = "https://" + random_choice - # 强制替换ov05 302redirect之后的真实地址为指定的域名或ip达到自选ov05节点的目的 - if force_ov05_ip and "ov-gotcha05" in url_info['host']: - response = requests.get(url_info['host'] + stream_info['base_url'] + url_info['extra']) - self.raw_stream_url = re.sub(r"https://([a-z0-9]+)\.ourdvsss\.com", f"http://{force_ov05_ip}", - response.url) - logger.debug(f"将ov-gotcha05的节点ip替换为了{force_ov05_ip}") - self.raw_stream_url = url_info['host'] + stream_info['base_url'] + url_info['extra'] - if self.bili_cdn_fallback is False: - return True - stream_info['url_info'].reverse() - # 检查直播流是否可用以倒叙尝试回退 - for stream_url in stream_info['url_info']: - self.raw_stream_url = stream_url['host'] + stream_info['base_url'] + stream_url['extra'] - if s.get(self.raw_stream_url, stream=True).status_code == 404: - continue - break + stream = streams[0] + logger.debug(f"获取{uname}房间fmp4流失败,回退到flv流") + stream_info = stream['format'][0]['codec'][0] + stream_url = {'base_url': stream_info['base_url']} + if perf_cdn is not None: + for url_info in stream_info['url_info']: + if perf_cdn in url_info['extra']: + stream_url['host'] = url_info['host'] + stream_url['extra'] = url_info['extra'] + logger.debug(f"找到了perfCDN{stream_url['host']}") + else: + stream_url['host'] = stream_info['url_info'][-1]['host'] + stream_url['extra'] = stream_info['url_info'][-1]['extra'] + if "cn-gotcha01" in stream_url['extra']: + # 强制替换cn-gotcha01的节点为指定节点 注意:只有大陆ip才能获取到cn-gotcha01的节点。 + if cn01_domains[0] != '': + import random + i = len(cn01_domains) + while i: # 测试节点是否可用 + i-=1 + host = cn01_domains[i] + try: + if s.get(f"https://{host}{stream_url['base_url']}{stream_url['extra']}", + stream=True).status_code == 200: # 如果响应状态码是 200,跳出循环 + break + except requests.exceptions.ConnectionError: # 如果发生连接异常,继续下一次循环 + logger.debug(f"节点 {host} 无法访问,尝试下一个节点。") + continue + else: + logger.error(f"配置文件中的cn-gotcha01节点均不可用") + logger.debug(f"节点 {host} 可用,替换为该节点") + stream_url['host'] = "https://" + host + # 强制去除 hls_ts 的 _bluray 文件名 + if force_source: + stream_url['base_url'] = re.sub(r'_bluray(?=\.m3u8)?', "", stream_url['base_url'], 1) + self.raw_stream_url = stream_url['host'] + stream_url['base_url'] + stream_url['extra'] + # 强制替换ov05 302redirect之后的真实地址为指定的域名或ip达到自选ov05节点的目的 + if ov05_ip and "ov-gotcha05" in stream_url['host']: + r = s.get(self.raw_stream_url, stream=True) + self.raw_stream_url = re.sub(r".*(?=/d1--ov-gotcha05)", f"http://{ov05_ip}", r.url, 1) + logger.debug(f"将ov-gotcha05的节点ip替换为了{ov05_ip}") + if bili_cdn_fallback: + try: + if s.get(self.raw_stream_url, stream=True).status_code == 404: + stream_info['url_info'].reverse() + for url_info in stream_info['url_info']: + self.raw_stream_url = url_info['host'] + stream_info['base_url'] + url_info['extra'] + if s.get(self.raw_stream_url, stream=True).status_code == 200: + break + except Exception: + logger.error('') return True async def danmaku_download_start(self, filename): @@ -164,46 +148,9 @@ def get_play_info(s, custom_api, official_api_host, params): custom_api_host = \ (lambda a: a if a.startswith(('http://', 'https://')) else 'http://' + a)(config.get('bili_liveapi') .rstrip('/')) - # 尝试获取直播流 try: return s.get(custom_api_host + '/xlive/web-room/v2/index/getRoomPlayInfo', params=params, timeout=5).json() except requests.exceptions.ConnectionError: logger.error(f"{custom_api_host}连接失败,尝试回退至官方Api") return s.get(official_api_host + '/xlive/web-room/v2/index/getRoomPlayInfo', params=params, timeout=5).json() - -def get_live_cover(uname, room_id, room_title, live_start_time, cover_url): - headers = { - "origin": "https://www.bilibili.com", - "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.41" - } - response = requests.get(cover_url, headers=headers, timeout=5) - save_dir = f'cover/{uname}_{room_id}/' - local_time = time.strftime('%Y-%m-%d_%H-%M-%S', time.localtime(live_start_time)) - if not os.path.exists(save_dir): - os.makedirs(save_dir) - cover_file_name = f'{room_title}_{local_time}.png' - cover_file_name = get_valid_filename(cover_file_name) - live_cover_path = f'{save_dir}{cover_file_name}' - if os.path.exists(live_cover_path): - return live_cover_path - else: - with open(live_cover_path, 'wb') as f: - f.write(response.content) - return live_cover_path - -def get_valid_filename(name): - """ - Return the given string converted to a string that can be used for a clean - filename. Remove leading and trailing spaces; convert other spaces to - underscores; and remove anything that is not an alphanumeric, dash, - underscore, or dot. - # >>> get_valid_filename("john's portrait in 2004.jpg") - >>> get_valid_filename("{self.fname}%Y-%m-%dT%H_%M_%S") - '{self.fname}%Y-%m-%dT%H_%M_%S' - """ - # s = str(name).strip().replace(" ", "_") #因为有些人会在主播名中间加入空格,为了避免和录播完毕自动改名冲突,所以注释掉 - s = re.sub(r"(?u)[^-\w.%{}\[\]【】「」\s]", "", str(name)) - if s in {"", ".", ".."}: - raise RuntimeError("Could not derive file name from '%s'" % name) - return s diff --git a/biliup/plugins/douyu.py b/biliup/plugins/douyu.py index acae6b7..8d0a6aa 100644 --- a/biliup/plugins/douyu.py +++ b/biliup/plugins/douyu.py @@ -17,10 +17,9 @@ class Douyu(DownloadBase): self.douyu_danmaku = config.get('douyu_danmaku', False) def check_stream(self): - logger.debug(self.fname) from ykdl.extractors.douyu.util import ub98484234 if len(self.url.split("douyu.com/")) < 2: - logger.debug("直播间地址:" + self.url + " 错误") + logger.error("直播间地址:" + self.url + " 错误") return False html = requests.get(self.url).text vid = match1(html, r'\$ROOM\.room_id\s*=\s*(\d+)', @@ -28,34 +27,28 @@ class Douyu(DownloadBase): r'"room_id.?":(\d+)', r'data-onlineid=(\d+)') if not vid: - logger.debug("直播间" + vid + ":被关闭或不存在") + logger.error("直播间" + vid + ":被关闭或不存在") return False roominfo = requests.get(f"https://www.douyu.com/betard/{vid}").json()['room'] - videoloop = roominfo['videoLoop'] - show_status = roominfo['show_status'] - if show_status != 1 or videoloop != 0: - logger.debug("直播间" + vid + ":未开播或正在放录播") + if roominfo['show_status'] != 1 or roominfo['videoLoop'] != 0: + logger.error("直播间" + vid + ":未开播或正在放录播") return False - # tct-h5 - douyucdn = config.get('douyucdn') if config.get('douyucdn') else '' + self.room_title = roominfo['room_name'] html_h5enc = requests.get(f'https://www.douyu.com/swf_api/homeH5Enc?rids={vid}').json() js_enc = html_h5enc['data']['room' + vid] params = { - 'cdn': douyucdn, + 'cdn': config.get('douyucdn', ''), 'iar': 0, 'ive': 0, + 'rate': 0, } - # print(js_enc) Extractor = namedtuple('Extractor', ['vid', 'logger']) ub98484234(js_enc, Extractor(vid, logger), params) - params['rate'] = 0 - html_content = requests.post(f'https://www.douyu.com/lapi/live/getH5Play/{vid}', headers=self.fake_headers, - params=params).json() - live_data = html_content["data"] - if type(live_data) is dict: - self.raw_stream_url = f"{live_data.get('rtmp_url')}/{live_data.get('rtmp_live')}" - self.room_title = roominfo['room_name'] - return True + live_data = get_play_info(vid, self.fake_headers, params) + if type(live_data) is not dict: + return False + self.raw_stream_url = f"{live_data.get('rtmp_url')}/{live_data.get('rtmp_live')}" + return True async def danmaku_download_start(self, filename): if self.douyu_danmaku: @@ -67,3 +60,19 @@ class Douyu(DownloadBase): if self.douyu_danmaku: self.danmaku.stop() logger.info("结束弹幕录制") + +def get_play_info(vid, fake_headers, params): + import random + try: + html_content = requests.post(f'https://www.douyu.com/lapi/live/getH5Play/{vid}', headers=fake_headers, + params=params).json() + live_data = html_content["data"] + # 尝试规避斗鱼自建scdn + # scdn 仅在该省市的ISP首次访问上方API后才会新增,且在新增后两分钟内无流可用(404) + if not live_data['rtmp_cdn'].endswith('h5'): + while not params['cdn'].endswith('h5'): + params['cdn'] = random.choice(live_data['cdnsWithName']).get('cdn') + return get_play_info(vid, fake_headers, params) + except Exception: + return None + return live_data \ No newline at end of file diff --git a/public/config.toml b/public/config.toml index e49817e..142d956 100644 --- a/public/config.toml +++ b/public/config.toml @@ -45,22 +45,25 @@ check_sourcecode = 15 #########各平台分设置######### +### 使用直播间封面作为投稿封面。此封面优先级低于单个主播指定的自定义封面。(直播封面将会保存于cover文件夹下,请自行定期删除) +#use_live_cover = true #------斗鱼------# -# 如遇到斗鱼录制卡顿可以尝试切换线路,tct-h5(备用线路5),ali-h5(备用线路6),akm-h5(主线路1) +### 如遇到斗鱼录制卡顿可以尝试切换线路。 +### tctc-h5(备用线路4), tct-h5(备用线路5), ali-h5(备用线路6), hw-h5(备用线路7), hs-h5(备用线路13) #douyucdn = "tct-h5" # 录制斗鱼弹幕,只有使用FFMPEG作为下载器才支持,默认关闭 #douyu_danmaku = false #------虎牙------# -### 如遇到虎牙录制卡顿可以尝试切换线路,AL, HW, TX, WS +### 如遇到虎牙录制卡顿可以尝试切换线路。可选以下线路 +### AL(阿里云), HW(华为云), TX(腾讯云), WS(网宿), HS(火山引擎), AL13(阿里云), HW16(华为云) #huyacdn = "AL" ### 录制虎牙弹幕,只有使用FFMPEG作为下载器才支持,默认关闭 #huya_danmaku = false #------哔哩哔哩------# -### 获取BILIBILI直播间封面并作为投稿封面。此封面优先级低于单个主播指定的自定义封面。(直播封面将会保存于cover文件夹下,请自行定期删除) -#use_live_cover = true + ### 录制BILIBILI弹幕,目前暂时不支持视频按时长分段下的弹幕文件自动分段,默认关闭 # bilibili_danmaku = false ### 哔哩哔哩直播流协议.可选 stream(flv流),hls_ts(ts流)与hls_fmp4(fmp4流),默认为stream @@ -72,13 +75,12 @@ check_sourcecode = 15 ### 哔哩哔哩直播优选CDN,默认无 #bili_perfCDN = "cn-gotcha01" ### 哔哩哔哩直播强制原画(仅限HLS流的 cn-gotcha01 CDN),默认为关闭 -#bili_forceScoure = false +#bili_force_source = false ### 自定义哔哩哔哩直播api,默认无 #bili_liveapi = "https://api.live.bilibili.com" ### CDN自动Fallback开关,默认为开启 #bili_cdn_fallback = true ### 强制替换ov-gotcha05的下载地址为指定的自选IP -#bili_force_ov05 = true #bili_force_ov05_ip = "163.171.197.234" ### 强制替换cn-gotcha01(叔叔自建,理论上最稳定)为指定的自选域名组(可多个域名,请用逗号分隔) ### 完整CDN列表请参考 https://rec.danmuji.org/dev/bilibili-cdn/ 中"B站视频云"的部分 @@ -86,10 +88,10 @@ check_sourcecode = 15 ### 此功能目前会和stream-gears冲突导致很多分段,请考虑使用ffmpeg录制 ### 如果海外机器需要使用此功能,需要在bili_liveapi中指定国内的反代API来获取cn-gotcha01的节点信息。 ### 海外机的玩法:配合一个国内的机器(例如便宜的腾讯云,阿里云等等)自建反代api.live.bilibili.com -### 如果海外机到联通或者移动网络线路还不错,就可以参考https://rec.danmuji.org/dev/bilibili-cdn/ 选取一些联通或者移动的节点并填入下面 +### 如果海外机到联通或者移动网络线路还不错,就可以参考***完整CDN列表***选取一些联通或者移动的节点并填入下面 ### 每次会随机返回填入的其中一个线路,并且会自动判断所填入的节点是否可用 #bili_force_cn01 = true -#bili_force_cn01_domains = "cn-gdst-cm-01-15.bilivideo.com,cn-gdst-cm-01-06.bilivideo.com,cn-fjqz-cm-01-06.bilivideo.com,cn-jssz-cm-01-02.bilivideo.com,cn-jxnc-cm-01-02.bilivideo.com" +#bili_force_cn01_domains = "cn-jxnc-cm-01-16.bilivideo.com,cn-gddg-cm-01-06.bilivideo.com,cn-fjqz-cm-01-06.bilivideo.com,cn-jssz-cm-01-02.bilivideo.com,cn-gddg-ct-01-12.bilivideo.com" #------YouTube------# ### 设置偏好的YouTube下载封装格式 @@ -102,7 +104,7 @@ check_sourcecode = 15 #youtube_prefer_acodec = "opus|mp4a" ### 可用opus,mp4a ### 设置偏好的YouTube下载最高纵向分辨率 ### 最高纵向分辨率,也就是xxxxP.如果youtube_prefer_format指定为mp4,将最高只能下载1080p的视频。 -#youtube_max_resolution = "440" +#youtube_max_resolution = "440" ### 限制单个视频的最大大小。 ### 注意:此参数优先级高于分辨率设置,并且不包括音频部分的大小,仅仅只是视频部分的大小。 ### 如果某个视频实在没有低于此大小的分辨率版本,将会选择最低画质的版本下载。 @@ -152,8 +154,9 @@ tags = [ "biliup", "视频标签" ] [user] #------哔哩哔哩------# #------哔哩哔哩获取直播流用COOKIE------# -### 参照https://github.com/BililiveRecorder/BililiveRecorder/issues/263 -#bili_cookie = "" +### 可参照https://github.com/BililiveRecorder/BililiveRecorder/issues/263. +### 也可使用biliup-rs来获取以下项目. +#bili_cookie: 'SESSDATA=none;bili_jct=none;DedeUserID__ckMd5=none;DedeUserID=none;access_token=none;' ### 重要!!! ###是否将cookie传入第三方API。将Cookie传入未知的第三方API有几率泄露帐号登录信息。 ###在开启了自定义Cookie(bili_cookie)又同时设置了第三方API(bili_liveapi)的情况下,如果打开了允许第三方API使用Cookie,那么就使用第三方API,如果没有允许(默认),那么设置的第三方API就不生效 @@ -170,9 +173,8 @@ douyin_cookie = '__ac_nonce=123456; __ac_signature=123456;' #twitch_cookie = 'asdiouo2h987r23hf2893fh923y7' #------YouTube------# -### 使用Cookies登陆YouTube帐号,可用于下载会限,私享等未登录账号无法访问的内容。请使用Netscape 格式的 Cookies 文本路径。 +### 使用Cookies登陆YouTube帐号,可用于下载会限,私享等未登录账号无法访问的内容。请使用 Netscape 格式的 Cookies 文本路径。 ### 可以使用Chrome插件Get cookies.txt来生成txt文件。 -# Netscape 格式的 Cookies 文本路径 #youtube_cookie = 'cookiejar.txt' # 日志输出配置 diff --git a/public/config.yaml b/public/config.yaml index 1dba998..435b67c 100644 --- a/public/config.yaml +++ b/public/config.yaml @@ -43,22 +43,24 @@ pool2_size: 3 check_sourcecode: 15 #########各平台分设置######### +### 使用直播间封面作为投稿封面。此封面优先级低于单个主播指定的自定义封面。(直播封面将会保存于cover文件夹下,请自行定期删除) +#use_live_cover: true #------斗鱼------# -### 如遇到斗鱼录制卡顿可以尝试切换线路,tct-h5(备用线路5),ali-h5(备用线路6),akm-h5(主线路1) +### 如遇到斗鱼录制卡顿可以尝试切换线路。可选以下线路 +### tctc-h5(备用线路4), tct-h5(备用线路5), ali-h5(备用线路6), hw-h5(备用线路7), hs-h5(备用线路13) #douyucdn: tct-h5 # 录制斗鱼弹幕,目前暂时不支持视频按时长分段下的弹幕文件自动分段,只有使用ffmpeg(包括streamlink混合模式)作为下载器才支持,默认关闭默认关闭 #douyu_danmaku: false #------虎牙------# -### 如遇到虎牙录制卡顿可以尝试切换线路,AL, HW, TX, WS +### 如遇到虎牙录制卡顿可以尝试切换线路。可选以下线路 +### AL(阿里云), HW(华为云), TX(腾讯云), WS(网宿), HS(火山引擎), AL13(阿里云), HW16(华为云) #huyacdn: AL ### 录制虎牙弹幕,目前暂时不支持视频按时长分段下的弹幕文件自动分段,只有使用ffmpeg(包括streamlink混合模式)作为下载器才支持,默认关闭默认关闭 #huya_danmaku: false #------哔哩哔哩------# -### 获取BILIBILI直播间封面并作为投稿封面。此封面优先级低于单个主播指定的自定义封面。(直播封面将会保存于cover文件夹下,请自行定期删除) -#use_live_cover: true ### 录制BILIBILI弹幕,目前暂时不支持视频按时长分段下的弹幕文件自动分段,只有使用ffmpeg(包括streamlink混合模式)作为下载器才支持,默认关闭默认关闭 # bilibili_danmaku: false ### 哔哩哔哩直播流协议.可选 stream(flv流),hls_ts(ts流)与hls_fmp4(fmp4流),默认为stream @@ -70,7 +72,7 @@ check_sourcecode: 15 ### 哔哩哔哩直播优选CDN,默认无 #bili_perfCDN: cn-gotcha01 ### 哔哩哔哩直播强制原画(仅限HLS流的 cn-gotcha01 CDN),默认为关闭 -#bili_forceScoure: false +#bili_force_source: false ### 自定义哔哩哔哩直播api,默认无 #bili_liveapi: 'https://api.live.bilibili.com' ### CDN自动Fallback开关,默认为开启 @@ -83,9 +85,9 @@ check_sourcecode: 15 ### 此功能目前会和stream-gears冲突导致很多分段,请考虑使用ffmpeg录制 ### 如果海外机器需要使用此功能,需要在bili_liveapi中指定国内的反代API来获取cn-gotcha01的节点信息。 ### 海外机的玩法:配合一个国内的机器(例如便宜的腾讯云,阿里云等等)自建反代api.live.bilibili.com -### 如果海外机到联通或者移动网络线路还不错,就可以参考https://rec.danmuji.org/dev/bilibili-cdn/ 选取一些联通或者移动的节点并填入下面 +### 如果海外机到联通或者移动网络线路还不错,就可以参考***完整CDN列表***选取一些联通或者移动的节点并填入下面 ### 每次会随机返回填入的其中一个线路,并且会自动判断所填入的节点是否可用 -#bili_force_cn01_domains: 'cn-gdst-cm-01-15.bilivideo.com,cn-gdst-cm-01-06.bilivideo.com,cn-fjqz-cm-01-06.bilivideo.com,cn-jssz-cm-01-02.bilivideo.com,cn-jxnc-cm-01-02.bilivideo.com' +#bili_force_cn01_domains: 'cn-jxnc-cm-01-16.bilivideo.com,cn-gddg-cm-01-06.bilivideo.com,cn-fjqz-cm-01-06.bilivideo.com,cn-jssz-cm-01-02.bilivideo.com,cn-gddg-ct-01-12.bilivideo.com' #------YouTube------# ### 设置偏好的YouTube下载封装格式 @@ -99,7 +101,7 @@ check_sourcecode: 15 ### 设置偏好的YouTube下载最高纵向分辨率 ### 最高纵向分辨率,也就是xxxxP。如果youtube_prefer_vcodec指定AVC,将最高只能下载1080p的视频。 #youtube_max_videosize: "5G" -#youtube_max_resolution: 1440 +#youtube_max_resolution: 1440 ### 限制单个视频的最大大小。 ### 注意:此参数优先级高于分辨率设置,并且不包括音频部分的大小,仅仅只是视频部分的大小。 ### 如果某个视频实在没有低于此大小的分辨率版本,将会选择最低画质的版本下载。 @@ -153,26 +155,13 @@ streamers: #user: #------哔哩哔哩------# #------哔哩哔哩获取直播流用COOKIE------# - ### 参照https://github.com/BililiveRecorder/BililiveRecorder/issues/263 - #bili_cookie: '' + ### 参照https://github.com/BililiveRecorder/BililiveRecorder/issues/263. 请至少填入以下项目. + #bili_cookie: 'SESSDATA=none; bili_jct=none;DedeUserID__ckMd5=none;DedeUserID=123;access_token=none;' ### 重要!!! ###是否将cookie传入第三方API。将Cookie传入未知的第三方API有几率泄露帐号登录信息。 ###在开启了自定义Cookie(bili_cookie)又同时设置了第三方API(bili_liveapi)的情况下,如果打开了允许第三方API使用Cookie,那么就使用第三方API,如果没有允许(默认),那么设置的第三方API就不生效 #customAPI_use_cookie : False - #------bili-web用(已过时,无视我)------# - # cookies: - # SESSDATA: your SESSDATA - # bili_jct: your bili_jct - # DedeUserID__ckMd5: your ckMd5 - # DedeUserID: your DedeUserID - # access_token: your access_key - # account: - # username: your usrname - # password: your password - # app_key: bca7e84c2d947ac6 ### 若账号密码方式无法登录可尝试更改此值 - # appsec: 60698ba2f68e01ce44738920a0ffe768 - #------抖音------# ### 如需要录制抖音请在此填入cookie需要__ac_nonce与__ac_signature的值 #douyin_cookie: '__ac_nonce=123456; __ac_signature=123456;'