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
This commit is contained in:
1 parent
8a7ee5fbfc
commit
edd760cc46
6 files changed
+153
-188
No files matched your search
+2
-1
@@ -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
|
||||
|
||||
@@ -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())
|
||||
|
||||
+75
-128
@@ -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
|
||||
+28
-19
@@ -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
|
||||
+15
-13
@@ -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'
|
||||
|
||||
# 日志输出配置
|
||||
|
||||
+12
-23
@@ -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;'
|
||||
|
||||
Reference in new issue
Block a user