feat: add liuxing live record and fix huya live

This commit is contained in:
ihmily
2024-05-07 09:14:14 +08:00
parent d8e70f59dc
commit 0f43cb0056
4 changed files with 118 additions and 69 deletions

View File

@@ -40,6 +40,7 @@
- [x] TwitchTV
- [x] LiveMe
- [x] 花椒直播
- [x] 流星直播
- [ ] 更多平台正在更新中
</div>
@@ -173,19 +174,16 @@ https://www.liveme.com/zh/v/17141543493018047815/index.html
花椒直播:
https://www.huajiao.com/user/223184650
流星直播:
https://www.7u66.com/100960
```
直播间分享地址和网页端长地址都能正常进行录制抖音尽量用长链接避免因短链接转换失效导致不能正常录制而且需要有nodejs环境否则无法转换
&emsp;
解析接口:
该解析接口 ~~仅供演示~~(演示接口暂时停止,后续再开放),并且只包含抖音、快手、虎牙直播的解析,其他平台如有需要请自行添加,源码在这里 [DouyinLiveRecorder/api](https://github.com/ihmily/DouyinLiveRecorder/tree/main/api)
在线播放m3u8和flv视频网站[M3U8 在线视频播放器 ](https://jx.hmily.vip/play/),源码是 [index.html](https://github.com/ihmily/DouyinLiveRecorder/blob/main/index.html)
在线播放m3u8和flv视频网站[M3U8 在线视频播放器 ](https://jx.hmily.vip/play/)
&emsp;
@@ -305,9 +303,16 @@ docker-compose stop
## ⏳提交日志
- 20240506
- 修复抖音录制画质解析bug
- 修复虎牙录制 60帧最高画质问题
- 新增流星直播录制
- 20240427
- 新增LiveMe、花椒直播录制
- 20240425
- 新增TwitchTV直播录制

View File

@@ -2,7 +2,7 @@
直播保存路径(不填则默认) =
保存文件夹是否以作者区分 =
视频保存格式ts|mkv|flv|mp4|ts音频|mkv音频 = ts
原画|超清|高清|标清 = 原画
原画|超清|高清|标清|流畅 = 原画
是否使用代理ip是/否) =
代理地址 =
同一时间访问网络的线程数 = 3

111
main.py
View File

@@ -4,7 +4,7 @@
Author: Hmily
GitHub: https://github.com/ihmily
Date: 2023-07-17 23:52:05
Update: 2024-05-06 12:45:21
Update: 2024-05-06 22:45:21
Copyright (c) 2023-2024 by Hmily, All Rights Reserved.
Function: Record live stream video.
"""
@@ -25,7 +25,7 @@ import hashlib
import urllib.parse
import urllib.request
from urllib.error import URLError, HTTPError
from typing import Any, Union
from typing import Any, Union, Dict
import configparser
from spider import (
@@ -55,7 +55,8 @@ from spider import (
get_kugou_stream_url,
get_twitchtv_stream_data,
get_liveme_stream_url,
get_huajiao_stream_url
get_huajiao_stream_url,
get_liuxing_stream_url
)
from web_rid import (
@@ -68,11 +69,11 @@ from utils import (
)
from msg_push import dingtalk, xizhi, tg_bot
version = "v3.0.3"
platforms = "\n国内站点:抖音|快手|虎牙|斗鱼|YY|B站|小红书|bigo|blued|网易CC|千度热播|猫耳FM|Look|TwitCasting|百度|微博|酷狗|LiveMe|花椒直播" \
version = "v3.0.4"
platforms = "\n国内站点:抖音|快手|虎牙|斗鱼|YY|B站|小红书|bigo|blued|网易CC|千度热播|猫耳FM|Look|TwitCasting|百度|微博|酷狗|LiveMe|花椒|流星" \
"\n海外站点TikTok|AfreecaTV|PandaTV|WinkTV|FlexTV|PopkonTV|TwitchTV"
# --------------------------全局变量-------------------------------------
recording = set()
unrecording = set()
warning_count = 0
@@ -98,9 +99,9 @@ rstr = r"[\/\\\:\*\?\"\<\>\|&.。,]"
ffmpeg_path = "ffmpeg" # ffmpeg文件路径
default_path = os.getcwd() + '/downloads'
os.makedirs(default_path, exist_ok=True)
file_update_lock = threading.Lock()
# --------------------------用到的函数-------------------------------------
def signal_handler(_signal, _frame):
sys.exit(0)
@@ -162,10 +163,8 @@ def display_info():
logger.error(f"错误信息: {e} 发生错误的行数: {e.__traceback__.tb_lineno}")
def update_file(file_path: str, old_str: str, new_str: str, start_str: str = None, lock: threading.Lock = None):
if lock is None:
lock = threading.Lock()
with lock:
def update_file(file_path: str, old_str: str, new_str: str, start_str: str = None):
with file_update_lock:
file_data = ""
with open(file_path, "r", encoding="utf-8-sig") as f:
for text_line in f:
@@ -241,9 +240,7 @@ def create_ass_file(filegruop: list):
def change_max_connect():
global max_request
global warning_count
# 动态控制连接次数
preset = max_request
# 记录当前时间
start_time = time.time()
while True:
@@ -252,10 +249,10 @@ def change_max_connect():
if preset > 5:
max_request = 5
else:
max_request //= 2 # 将max_request除以2向下取整
if max_request > 0: # 如果得到的结果大于0则直接取该结果
max_request //= 2
if max_request > 0:
max_request = preset
else: # 否则将其设置为1
else:
preset = 1
print("同一时间访问网络的线程数动态改为", max_request)
@@ -276,7 +273,7 @@ def change_max_connect():
@trace_error_decorator
def get_douyin_stream_url(json_data: dict, video_quality: str) -> dict:
def get_douyin_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
# TODO: 获取抖音直播源地址
anchor_name = json_data.get('anchor_name', None)
@@ -319,12 +316,12 @@ def get_douyin_stream_url(json_data: dict, video_quality: str) -> dict:
@trace_error_decorator
def get_tiktok_stream_url(json_data: dict, video_quality: str) -> dict:
def get_tiktok_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
# TODO: 获取tiktok直播源地址
if not json_data:
return {"anchor_name": None, "is_live": False}
def get_video_quality_url(stream, q_key):
def get_video_quality_url(stream, q_key) -> Dict[str, str]:
return {
'hls': re.sub("https", "http", stream[q_key]['main']['hls']),
'flv': re.sub("https", "http", stream[q_key]['main']['flv']),
@@ -360,7 +357,7 @@ def get_tiktok_stream_url(json_data: dict, video_quality: str) -> dict:
@trace_error_decorator
def get_kuaishou_stream_url(json_data: dict, video_quality: str) -> dict:
def get_kuaishou_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
# TODO: 获取快手直播源地址
if json_data['type'] == 1 and not json_data["is_live"]:
@@ -399,7 +396,7 @@ def get_kuaishou_stream_url(json_data: dict, video_quality: str) -> dict:
@trace_error_decorator
def get_huya_stream_url(json_data: dict, video_quality: str) -> dict:
def get_huya_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
# TODO: 获取虎牙直播源地址
game_live_info = json_data.get('data', [])[0].get('gameLiveInfo', {})
@@ -420,7 +417,7 @@ def get_huya_stream_url(json_data: dict, video_quality: str) -> dict:
hls_url_suffix = select_cdn.get('sHlsUrlSuffix')
flv_anti_code = select_cdn.get('sFlvAntiCode')
def get_anti_code(old_anti_code):
def get_anti_code(old_anti_code: str) -> str:
# js地址https://hd.huya.com/cdn_libs/mobile/hysdk-m-202402211431.js
@@ -461,19 +458,17 @@ def get_huya_stream_url(json_data: dict, video_quality: str) -> dict:
m3u8_url = f'{hls_url}/{stream_name}.{hls_url_suffix}?{new_anti_code}&ratio='
quality_list = flv_anti_code.split('&exsphd=')
if len(quality_list) > 1:
if len(quality_list) > 1 and video_quality not in ["原画", "蓝光"]:
pattern = r"(?<=264_)\d+"
quality_list = [x for x in re.findall(pattern, quality_list[1])][::-1]
while len(quality_list) < 5:
quality_list.append(quality_list[-1])
video_quality_options = {
"原画": quality_list[0],
"蓝光": quality_list[0],
"": quality_list[1],
"高清": quality_list[2],
"标清": quality_list[3],
"流畅": quality_list[4]
"超清": quality_list[0],
"高清": quality_list[1],
"": quality_list[2],
"流畅": quality_list[3]
}
if video_quality not in video_quality_options:
@@ -491,7 +486,7 @@ def get_huya_stream_url(json_data: dict, video_quality: str) -> dict:
@trace_error_decorator
def get_douyu_stream_url(json_data: dict, cookies: str, video_quality: str, proxy_address: str) -> dict:
def get_douyu_stream_url(json_data: dict, cookies: str, video_quality: str, proxy_address: str) -> Dict[str, Any]:
# TODO: 获取斗鱼直播源地址
if not json_data["is_live"]:
return json_data
@@ -517,7 +512,7 @@ def get_douyu_stream_url(json_data: dict, cookies: str, video_quality: str, prox
@trace_error_decorator
def get_yy_stream_url(json_data: dict) -> dict:
def get_yy_stream_url(json_data: dict) -> Dict[str, Any]:
# TODO: 获取YY直播源地址
anchor_name = json_data.get('anchor_name', '')
result = {
@@ -536,7 +531,7 @@ def get_yy_stream_url(json_data: dict) -> dict:
@trace_error_decorator
def get_bilibili_stream_url(json_data: dict, video_quality: str) -> dict:
def get_bilibili_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
# TODO: 获取B站直播源地址
if "is_live" in json_data and not json_data['anchor_name']:
return json_data
@@ -601,7 +596,7 @@ def get_bilibili_stream_url(json_data: dict, video_quality: str) -> dict:
@trace_error_decorator
def get_afreecatv_stream_url(json_data: dict, video_quality: str) -> dict:
def get_afreecatv_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
# TODO: 获取afreecatv直播源地址
if not json_data['is_live']:
return json_data
@@ -623,7 +618,7 @@ def get_afreecatv_stream_url(json_data: dict, video_quality: str) -> dict:
@trace_error_decorator
def get_netease_stream_url(json_data: dict, video_quality: str) -> dict:
def get_netease_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
# TODO: 获取netease直播源地址
if not json_data['is_live']:
return json_data
@@ -646,7 +641,7 @@ def get_netease_stream_url(json_data: dict, video_quality: str) -> dict:
@trace_error_decorator
def get_pandatv_stream_url(json_data: dict, video_quality: str) -> dict:
def get_pandatv_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
# TODO: 获取pandatv直播源地址
if not json_data['is_live']:
return json_data
@@ -668,7 +663,7 @@ def get_pandatv_stream_url(json_data: dict, video_quality: str) -> dict:
@trace_error_decorator
def get_winktv_stream_url(json_data: dict, video_quality: str) -> dict:
def get_winktv_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
# TODO: 获取winktv直播源地址
if not json_data['is_live']:
return json_data
@@ -690,7 +685,7 @@ def get_winktv_stream_url(json_data: dict, video_quality: str) -> dict:
@trace_error_decorator
def get_flextv_stream_url(json_data: dict, video_quality: str) -> dict:
def get_flextv_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
# TODO: 获取flextv直播源地址
if not json_data['is_live']:
return json_data
@@ -712,7 +707,7 @@ def get_flextv_stream_url(json_data: dict, video_quality: str) -> dict:
@trace_error_decorator
def get_baidu_stream_url(json_data: dict, video_quality: str) -> dict:
def get_baidu_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
# TODO: 获取百度直播源地址
if not json_data['is_live']:
return json_data
@@ -733,7 +728,8 @@ def get_baidu_stream_url(json_data: dict, video_quality: str) -> dict:
}
def get_twitchtv_stream_url(json_data: dict, video_quality: str) -> dict:
def get_twitchtv_stream_url(json_data: dict, video_quality: str) -> Dict[str, Any]:
# TODO: 获取twitchtv直播源地址
if not json_data['is_live']:
return json_data
@@ -753,7 +749,7 @@ def get_twitchtv_stream_url(json_data: dict, video_quality: str) -> dict:
}
def push_message(content: str):
def push_message(content: str) -> Union[str, list]:
push_pts = []
if '微信' in live_status_push:
push_pts.append('微信')
@@ -764,7 +760,7 @@ def push_message(content: str):
if 'TG' in live_status_push or 'tg' in live_status_push:
push_pts.append('TG')
tg_bot(tg_chat_id, tg_token, content)
push_pts = ''.join(push_pts) if len(push_pts) > 0 else ''
push_pts = ''.join(push_pts) if len(push_pts) > 0 else []
return push_pts
@@ -1057,6 +1053,12 @@ def start_record(url_data: tuple, count_variable: int = -1):
with semaphore:
port_info = get_huajiao_stream_url(
url=record_url, proxy_addr=proxy_address, cookies=huajiao_cookie)
elif record_url.find("7u66.com/") > -1:
platform = '流星直播'
with semaphore:
port_info = get_liuxing_stream_url(
url=record_url, proxy_addr=proxy_address, cookies=liuxing_cookie)
else:
logger.error(f'{record_url} 未知直播地址')
return
@@ -1192,7 +1194,8 @@ def start_record(url_data: tuple, count_variable: int = -1):
if platform in re_plat:
logger.info(f"{platform} | {anchor_name} | 直播源地址: {port_info['m3u8_url']}")
else:
logger.info(f"{platform} | {anchor_name} | 直播源地址: {port_info['record_url']}")
logger.info(
f"{platform} | {anchor_name} | 直播源地址: {port_info['record_url']}")
if video_save_type == "FLV":
filename = anchor_name + '_' + now + '.flv'
@@ -1540,7 +1543,7 @@ def start_record(url_data: tuple, count_variable: int = -1):
def backup_file(file_path: str, backup_dir_path: str):
"""
备份配置文件到备份目录,分别保留最新 5 个文件
备份配置文件到备份目录,分别保留最新 8 个文件
"""
try:
if not os.path.exists(backup_dir_path):
@@ -1561,13 +1564,13 @@ def backup_file(file_path: str, backup_dir_path: str):
url_files.sort(key=lambda x: os.path.getmtime(os.path.join(backup_dir_path, x)))
config_files.sort(key=lambda x: os.path.getmtime(os.path.join(backup_dir_path, x)))
while len(url_files) > 5:
while len(url_files) > 8:
oldest_file = url_files[0]
os.remove(os.path.join(backup_dir_path, oldest_file))
# print(f'\r已删除最旧的 URL_config.ini 备份文件 {oldest_file}')
url_files = url_files[1:]
while len(config_files) > 5:
while len(config_files) > 8:
oldest_file = config_files[0]
os.remove(os.path.join(backup_dir_path, oldest_file))
# print(f'\r已删除最旧的 config.ini 备份文件 {oldest_file}')
@@ -1641,8 +1644,8 @@ except Exception as err:
print("An unexpected error occurred:", err)
def read_config_value(config_parser: configparser.RawConfigParser, section: str, option: str, default_value: Any) -> (
Union)[str, int, bool]:
def read_config_value(config_parser: configparser.RawConfigParser, section: str, option: str, default_value: Any) \
-> Union[str, int, bool]:
try:
config_parser.read(config_file, encoding=encoding)
@@ -1761,6 +1764,7 @@ while True:
twitch_cookie = read_config_value(config, 'Cookie', 'twitch_cookie', '')
liveme_cookie = read_config_value(config, 'Cookie', 'liveme_cookie', '')
huajiao_cookie = read_config_value(config, 'Cookie', 'huajiao_cookie', '')
liuxing_cookie = read_config_value(config, 'Cookie', 'liuxing_cookie', '')
if len(video_save_type) > 0:
if video_save_type.upper().lower() == "FLV".lower():
@@ -1821,7 +1825,7 @@ while True:
else:
quality, url, name = split_line
if quality not in ["原画", "蓝光", "超清", "高清", "标清"]:
if quality not in ["原画", "蓝光", "超清", "高清", "标清", "流畅"]:
quality = '原画'
if ('http://' not in url) and ('https://' not in url):
@@ -1852,6 +1856,8 @@ while True:
'mfanxing.kugou.com',
'www.liveme.com',
'www.huajiao.com',
'www.7u66.com',
'wap.7u66.com',
]
overseas_platform_host = [
'www.tiktok.com',
@@ -1869,6 +1875,12 @@ while True:
if url_host in ['live.douyin.com', 'live.bilibili.com', 'www.huajiao.com']:
update_file(url_config_file, url, url.split('?')[0])
url = url.split('?')[0]
if url_host in ['www.xiaohongshu.com', 'www.redelight.cn']:
if 'share_source' in url:
xhs_url_h, xhs_url_t, = url.split('?')
new_xhs_url = xhs_url_h + '?appuid=' + xhs_url_t.split('&appuid=')[1].split('&')[0]
update_file(url_config_file, url, new_xhs_url)
url = new_xhs_url
new_line = (quality, url, name)
url_tuples_list.append(new_line)
@@ -1901,7 +1913,6 @@ while True:
print(f"\r新增链接: {url_tuple[1]}")
monitoring += 1
args = [url_tuple, monitoring]
# TODO: 执行开始录制的操作
create_var['thread' + str(monitoring)] = threading.Thread(target=start_record, args=args)
create_var['thread' + str(monitoring)].daemon = True
create_var['thread' + str(monitoring)].start()
@@ -1921,4 +1932,4 @@ while True:
first_run = False
time.sleep(3)
time.sleep(3)

View File

@@ -4,7 +4,7 @@
Author: Hmily
GitHub:https://github.com/ihmily
Date: 2023-07-15 23:15:00
Update: 2024-04-27 23:00:11
Update: 2024-05-06 23:00:11
Copyright (c) 2023 by Hmily, All Rights Reserved.
Function: Get live stream data.
"""
@@ -15,7 +15,7 @@ import time
import urllib.parse
import urllib.error
from urllib.request import Request
from typing import Union, Dict, Any, Tuple
from typing import Union, Dict, Any, Tuple, List
import requests
import ssl
import re
@@ -125,7 +125,7 @@ def replace_url(file_path: str, old: str, new: str) -> None:
def get_play_url_list(m3u8: str, proxy: Union[str, None] = None, header: Union[dict, None] = None,
abroad: bool = False) -> list:
abroad: bool = False) -> List[str]:
resp = get_req(url=m3u8, proxy_addr=proxy, headers=header, abroad=abroad)
play_url_list = []
for i in resp.split('\n'):
@@ -430,7 +430,7 @@ def get_bilibili_stream_data(url: str, proxy_addr: Union[str, None] = None, cook
if cookies:
headers['Cookie'] = cookies
def get_data_from_api(link: str):
def get_data_from_api(link: str) -> Dict[str, Any]:
room_id = link.split('?')[0].rsplit('/', maxsplit=1)[1]
api = f'https://api.live.bilibili.com/xlive/web-room/v2/index/getRoomPlayInfo?room_id={room_id}&no_playurl=0&mask=1&qn=0&platform=web&protocol=0,1&format=0,1,2&codec=0,1,2&dolby=5&panorama=1'
json_str = get_req(url=api, proxy_addr=proxy_addr, headers=headers)
@@ -714,7 +714,7 @@ def get_afreecatv_stream_data(
"is_live": False,
}
def get_url_list(m3u8: str) -> list:
def get_url_list(m3u8: str) -> List[str]:
resp = get_req(url=m3u8, proxy_addr=proxy_addr, headers=headers, abroad=True)
play_url_list = []
url_prefix = m3u8.rsplit('/', maxsplit=1)[0] + '/'
@@ -1811,7 +1811,7 @@ def get_huajiao_sn(live_id: str, cookies: Union[str, None] = None, proxy_addr: U
live_id = url.split('?')[0].rsplit('/', maxsplit=1)[1]
return nickname, sn, uid, live_id
except Exception:
replace_url('./config/URL_config.ini', old=url, new='#'+url)
replace_url('./config/URL_config.ini', old=url, new='#' + url)
raise RuntimeError('获取直播间数据失败,花椒直播间地址非固定,请使用主播主页地址进行录制')
@@ -1847,7 +1847,7 @@ def get_huajiao_user_info(url: str, cookies: Union[str, None] = None, proxy_addr
return anchor_name, None
else:
live_id = url.split('?')[0].rsplit('/',maxsplit=1)[1]
live_id = url.split('?')[0].rsplit('/', maxsplit=1)[1]
data = get_huajiao_sn(live_id)
if data:
profile_url = f'https://www.huajiao.com/user/{data[2].split("?")[0]}'
@@ -1891,6 +1891,37 @@ def get_huajiao_stream_url(url: str, proxy_addr: Union[str, None] = None, cookie
return result
@trace_error_decorator
def get_liuxing_stream_url(url: str, proxy_addr: Union[str, None] = None, cookies: Union[str, None] = None) -> \
Dict[str, Any]:
headers = {
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
'Referer': 'https://wap.7u66.com/198189?promoters=0',
'User-Agent': 'Mozilla/5.0 (Linux; Android 8.0.0; SM-G955U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36 Edg/121.0.0.0',
}
if cookies:
headers['Cookie'] = cookies
room_id = url.split('?')[0].rsplit('/', maxsplit=1)[1]
api = f'https://wap.7u66.com/api/ui/room/v1.0.0/live.ashx?promoters=0&roomidx={room_id}&currentUrl=https://www.7u66.com/{room_id}?promoters=0'
json_str = get_req(url=api, proxy_addr=proxy_addr, headers=headers)
json_data = json.loads(json_str)
room_info = json_data['data']['roomInfo']
anchor_name = room_info['nickname']
live_status = room_info["live_stat"]
result = {"anchor_name": anchor_name, "is_live": False}
if live_status == 1:
result["is_live"] = True
idx = room_info['idx']
live_id = room_info['liveId1']
flv_url = f'https://txpull1.5see.com/live/{idx}/{live_id}.flv'
result['flv_url'] = flv_url
result['record_url'] = flv_url
return result
if __name__ == '__main__':
# 尽量用自己的cookie以避免默认的不可用导致无法获取数据
# 以下示例链接不保证时效性,请自行查看链接是否能正常访问
@@ -1905,8 +1936,8 @@ if __name__ == '__main__':
# room_url = 'https://live.bilibili.com/21593109' # b站直播
# room_url = 'https://live.bilibili.com/23448867' # b站直播
# 小红书直播
# room_url = 'https://www.redelight.cn/hina/livestream/569077534207413574/1707413727088?appuid=5f3f478a00000000010005b3&'
# room_url = 'https://www.xiaohongshu.com/hina/livestream/569098486282043893/1708661048594?appuid=5f3f478a00000000010005b3&'
# room_url = 'https://www.redelight.cn/hina/livestream/569077534207413574?appuid=5f3f478a00000000010005b3&'
# room_url = 'https://www.xiaohongshu.com/hina/livestream/569098486282043893?appuid=5f3f478a00000000010005b3&'
# room_url = 'https://www.bigo.tv/cn/716418802' # bigo直播
# room_url = 'https://app.blued.cn/live?id=Mp6G2R' # blued直播
# room_url = 'https://play.afreecatv.com/sw7love' # afreecatv直播
@@ -1928,6 +1959,7 @@ if __name__ == '__main__':
# room_url = 'https://www.twitch.tv/gamerbee' # TwitchTV
# room_url = 'https://www.liveme.com/zh/v/17141937295821012854/index.html' # LiveMe
# room_url = 'https://www.huajiao.com/user/223184650' # 花椒直播
# room_url = 'https://www.7u66.com/100960' # 流星直播
print(get_douyin_stream_data(room_url, proxy_addr=''))
# print(get_tiktok_stream_data(room_url, proxy_addr=''))
@@ -1955,4 +1987,5 @@ if __name__ == '__main__':
# print(get_kugou_stream_url(room_url, proxy_addr=''))
# print(get_twitchtv_stream_data(room_url, proxy_addr=''))
# print(get_liveme_stream_url(room_url, proxy_addr=''))
# print(get_huajiao_stream_url(room_url, proxy_addr=''))
# print(get_huajiao_stream_url(room_url, proxy_addr=''))
# print(get_liuxing_stream_url(room_url, proxy_addr=''))