Fix video recording file segmentation and bigo record bugs

This commit is contained in:
ihmily 2023-12-10 22:55:42 +08:00
parent 107e9f434c
commit 25a1af42fc
4 changed files with 179 additions and 130 deletions

View File

@ -12,7 +12,7 @@
## 😺已支持平台
- [x] 抖音
- [x] Tiktok
- [x] TikTok
- [x] 快手
- [x] 虎牙
- [x] 斗鱼
@ -72,7 +72,7 @@
https://live.douyin.com/745964462470
https://v.douyin.com/iQFeBnt/
Tiktok
TikTok
https://www.tiktok.com/@pearlgaga88/live
快手:
@ -104,7 +104,7 @@ AfreecaTV
https://play.afreecatv.com/sw7love/249471484
```
Tiktok目前只支持PC网页端地址我没下载app其他平台 app端直播间分享地址和网页端长地址都能正常进行录制(抖音尽量用长链接,避免因短链接转换失效导致不能正常录制)。
直播间分享地址和网页端长地址都能正常进行录制(抖音尽量用长链接,避免因短链接转换失效导致不能正常录制)。
</div>
@ -143,9 +143,16 @@ GET https://hmily.vip/api/jx/live/convert.php?url=https://v.douyin.com/iQLgKSj/
## ⏳提交日志
- 20231210
- 修复录制分段bug修复bigo录制检测bug
- 新增自定义修改录制主播名
- 新增AfreecaTV直播录制修复某些可能会发生的bug
- 20231207
- 新增blued直播录制修复YY直播录制新增直播结束消息推送
- 20231206
@ -166,7 +173,7 @@ GET https://hmily.vip/api/jx/live/convert.php?url=https://v.douyin.com/iQLgKSj/
- 祝大家中秋节快乐!
- 20230919
- 修复了快手版本更新后录制出错的问题增加了其自动获取cookie(~~稳定性未知~~)
- 修复了Tiktok显示正在直播但不进行录制的问题
- 修复了TikTok显示正在直播但不进行录制的问题
- 20230907
- 修复了因抖音官方更新了版本导致的录制出错以及短链接转换出错
@ -174,7 +181,7 @@ GET https://hmily.vip/api/jx/live/convert.php?url=https://v.douyin.com/iQLgKSj/
- 修改了配置文件字段新增各平台自定义设置Cookie
- 20230903
- 修复了Tiktok录制时报644无法录制的问题
- 修复了TikTok录制时报644无法录制的问题
- 新增直播状态推送到钉钉和微信的功能,如有需要请看 [设置推送教程](https://d04vqdiqwr3.feishu.cn/docx/XFPwdDDvfobbzlxhmMYcvouynDh?from=from_copylink)
- 最近比较忙,其他问题有时间再更新
- 20230816
@ -193,15 +200,15 @@ GET https://hmily.vip/api/jx/live/convert.php?url=https://v.douyin.com/iQLgKSj/
- 20230805
- 新增了虎牙直播录制其暂时只能用flv视频流进行录制
- Web API 新增了快手和虎牙这两个平台的直播流解析Tiktok要代理
- Web API 新增了快手和虎牙这两个平台的直播流解析TikTok要代理
- 20230804
- 新增了快手直播录制,优化了部分代码
- 上传了一个自动化获取抖音直播间页面Cookie的代码可以用于录制
- 20230803
- 通宵更新
- 新增了国际版抖音Tiktok的直播录制去除冗余 简化了部分代码
- 新增了国际版抖音TikTok的直播录制去除冗余 简化了部分代码
- 20230724
- 新增了一个通过抖音直播间地址获取直播视频流链接的API接口使用php写的 上传即可用
- 新增了一个通过抖音直播间地址获取直播视频流链接的API接口上传即可用
&emsp;

View File

@ -1,35 +1,35 @@
[录制设置]
直播保存路径(不填则默认) =
直播保存路径(不填则默认) =
视频保存格式ts|mkv|flv|mp4|ts音频|mkv音频 = mp4
原画|超清|高清|标清 = 原画
是否使用代理ip是/否) =
代理地址 =
代理地址 =
同一时间访问网络的线程数 = 3
循环时间(秒) = 60
循环时间(秒) = 120
排队读取网址时间(秒) = 0
是否显示循环秒数 =
ts格式分段录制是否开启 =
视频分段大小(兆) = 1000
ts录制完成后自动增加生成mp4格式 =
ts录制完成后自动增加生成m4a格式 =
追加格式后删除原文件 =
分段录制是否开启 =
视频分段时间(秒) = 3600
生成时间文件 =
TS录制完成后自动转为mp4格式 =
TS录制完成后自动增加生成m4a格式 =
追加格式后删除原文件 =
[推送配置]
直播状态通知(可选微信|钉钉或者两个都填) =
钉钉推送接口链接 =
微信推送接口链接 =
钉钉通知@对象(填手机号) =
直播状态通知(可选微信|钉钉或者两个都填) =
钉钉推送接口链接 =
微信推送接口链接 =
钉钉通知@对象(填手机号) =
[Cookie]
抖音cookie(录制抖音必须要有) = ttwid=1%7CB1qls3GdnZhUov9o2NxOMxxYS2ff6OSvEWbv0ytbES4%7C1680522049%7C280d802d6d478e3e78d0c807f7c487e7ffec0ae4e5fdd6a0fe74c3c6af149511; my_rd=1; passport_csrf_token=3ab34460fa656183fccfb904b16ff742; passport_csrf_token_default=3ab34460fa656183fccfb904b16ff742; d_ticket=9f562383ac0547d0b561904513229d76c9c21; n_mh=hvnJEQ4Q5eiH74-84kTFUyv4VK8xtSrpRZG1AhCeFNI; store-region=cn-fj; store-region-src=uid; LOGIN_STATUS=1; __security_server_data_status=1; FORCE_LOGIN=%7B%22videoConsumedRemainSeconds%22%3A180%7D; pwa2=%223%7C0%7C3%7C0%22; download_guide=%223%2F20230729%2F0%22; volume_info=%7B%22isUserMute%22%3Afalse%2C%22isMute%22%3Afalse%2C%22volume%22%3A0.6%7D; strategyABtestKey=%221690824679.923%22; stream_recommend_feed_params=%22%7B%5C%22cookie_enabled%5C%22%3Atrue%2C%5C%22screen_width%5C%22%3A1536%2C%5C%22screen_height%5C%22%3A864%2C%5C%22browser_online%5C%22%3Atrue%2C%5C%22cpu_core_num%5C%22%3A8%2C%5C%22device_memory%5C%22%3A8%2C%5C%22downlink%5C%22%3A10%2C%5C%22effective_type%5C%22%3A%5C%224g%5C%22%2C%5C%22round_trip_time%5C%22%3A150%7D%22; VIDEO_FILTER_MEMO_SELECT=%7B%22expireTime%22%3A1691443863751%2C%22type%22%3Anull%7D; home_can_add_dy_2_desktop=%221%22; __live_version__=%221.1.1.2169%22; device_web_cpu_core=8; device_web_memory_size=8; xgplayer_user_id=346045893336; csrf_session_id=2e00356b5cd8544d17a0e66484946f28; odin_tt=724eb4dd23bc6ffaed9a1571ac4c757ef597768a70c75fef695b95845b7ffcd8b1524278c2ac31c2587996d058e03414595f0a4e856c53bd0d5e5f56dc6d82e24004dc77773e6b83ced6f80f1bb70627; __ac_nonce=064caded4009deafd8b89; __ac_signature=_02B4Z6wo00f01HLUuwwAAIDBh6tRkVLvBQBy9L-AAHiHf7; ttcid=2e9619ebbb8449eaa3d5a42d8ce88ec835; webcast_leading_last_show_time=1691016922379; webcast_leading_total_show_times=1; webcast_local_quality=sd; live_can_add_dy_2_desktop=%221%22; msToken=1JDHnVPw_9yTvzIrwb7cQj8dCMNOoesXbA_IooV8cezcOdpe4pzusZE7NB7tZn9TBXPr0ylxmv-KMs5rqbNUBHP4P7VBFUu0ZAht_BEylqrLpzgt3y5ne_38hXDOX8o=; msToken=jV_yeN1IQKUd9PlNtpL7k5vthGKcHo0dEh_QPUQhr8G3cuYv-Jbb4NnIxGDmhVOkZOCSihNpA2kvYtHiTW25XNNX_yrsv5FN8O6zm3qmCIXcEe0LywLn7oBO2gITEeg=; tt_scid=mYfqpfbDjqXrIGJuQ7q-DlQJfUSG51qG.KUdzztuGP83OjuVLXnQHjsz-BRHRJu4e986
快手cookie =
Tiktok_cookie =
虎牙cookie =
斗鱼cookie =
YY_cookie =
B站cookie =
小红书cookie =
bigo_cookie =
blued_cookie =
afreecatv_cookie =
快手cookie =
tiktok_cookie =
虎牙cookie =
斗鱼cookie =
yy_cookie =
B站cookie =
小红书cookie =
bigo_cookie =
blued_cookie =
afreecatv_cookie =

228
main.py
View File

@ -4,7 +4,7 @@
Author: Hmily
GitHub: https://github.com/ihmily
Date: 2023-07-17 23:52:05
Update: 2023-12-10 05:13:20
Update: 2023-12-10 22:03:56
Copyright (c) 2023 by Hmily, All Rights Reserved.
Function: Record live stream video.
"""
@ -49,8 +49,8 @@ from utils import (
)
from msg_push import dingtalk, xizhi
version = "v2.0.6"
platforms = "抖音|Tiktok|快手|虎牙|斗鱼|YY|B站|小红书|bigo直播|blued直播|AfreecaTV"
version = "v2.0.7"
platforms = "抖音|TikTok|快手|虎牙|斗鱼|YY|B站|小红书|bigo直播|blued直播|AfreecaTV"
# --------------------------全局变量-------------------------------------
recording = set()
unrecording = set()
@ -98,8 +98,8 @@ def display_info():
sys.exit(0)
print(f"是否开启代理录制: {'' if use_proxy else ''}", end=" | ")
if split_video_by_size:
print(f"TS录制分段开启录制分段大小为 {split_size} M", end=" | ")
if split_video_by_time:
print(f"录制分段开启: {split_time}", end=" | ")
print(f"是否生成时间文件: {'' if create_time_file else ''}", end=" | ")
print(f"录制视频质量为: {video_quality}", end=" | ")
print(f"录制视频格式为: {video_save_type}", end=" | ")
@ -615,9 +615,16 @@ def start_record(url_tuple, count_variable=-1):
with semaphore:
port_info = get_afreecatv_stream_url(record_url, afreecatv_cookie)
anchor_name: str = port_info.get("anchor_name", '')
if anchor_name:
anchor_split = anchor_name.split('主播:')
if len(anchor_split) > 1 and anchor_split[1].strip():
anchor_name = anchor_split[1].strip()
else:
anchor_name = port_info.get("anchor_name", '')
else:
anchor_name = port_info.get("anchor_name", '')
if not anchor_name:
if anchor_name == '':
print(f'序号{count_variable} 网址内容获取失败,进行重试中...获取失败的地址是:{url_tuple}')
warning_count += 1
else:
@ -654,18 +661,18 @@ def start_record(url_tuple, count_variable=-1):
if real_url != "":
live_list.append(anchor_name)
now = time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime(time.time()))
try:
if len(video_save_path) > 0:
if video_save_path[-1] != "/":
video_save_path = video_save_path + "/"
full_path = f'{video_save_path}/{anchor_name}'
if not os.path.exists(full_path):
os.makedirs(full_path)
else:
full_path = './' + anchor_name
if not os.path.exists(anchor_name):
os.makedirs(full_path)
video_save_path = default_path + '/'
video_save_path = video_save_path.replace("\\", "/")
full_path = f'{video_save_path}{anchor_name}'
if not os.path.exists(full_path):
os.makedirs(full_path)
except Exception as e:
print(f"路径错误信息: {e} 发生错误的行数: {e.__traceback__.tb_lineno}")
logger.warning(f"错误信息: {e} 发生错误的行数: {e.__traceback__.tb_lineno}")
@ -696,13 +703,12 @@ def start_record(url_tuple, count_variable=-1):
"-sn", "-dn",
"-reconnect_delay_max", "30",
"-reconnect_streamed", "-reconnect_at_eof",
"-c:a", "copy",
"-max_muxing_queue_size", "64",
"-correct_ts_overflow", "1",
]
# 添加代理参数
need_proxy_url = ['tiktok','afreecatv']
need_proxy_url = ['tiktok', 'afreecatv']
for i in need_proxy_url:
if i in real_url:
if use_proxy and proxy_addr != '':
@ -747,20 +753,38 @@ def start_record(url_tuple, count_variable=-1):
filename = anchor_name + '_' + now + ".mkv"
print(f'{rec_info}/{filename}')
save_file_path = full_path + '/' + filename
if create_time_file:
filename_gruop = [anchor_name, filename_short]
create_var[str(filename_short)] = threading.Thread(target=create_ass_file,
args=(filename_gruop,))
create_var[str(filename_short)].daemon = True
create_var[str(filename_short)].start()
try:
command = [
"-map", "0",
"-c:v", "copy", # 直接用copy的话体积特别大.
"-f", "matroska",
"{path}".format(path=save_file_path),
]
if split_video_by_time:
now = time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime())
save_file_path = f"{full_path}/{anchor_name}_{now}_%03d.mkv"
command = [
"-c:v", "copy",
"-c:a", "aac",
"-map", "0",
"-f", "segment",
"-segment_time", split_time,
"-segment_format", "matroska",
"-reset_timestamps", "1",
save_file_path,
]
else:
if create_time_file:
filename_gruop = [anchor_name, filename_short]
create_var[str(filename_short)] = threading.Thread(
target=create_ass_file,
args=(filename_gruop,))
create_var[str(filename_short)].daemon = True
create_var[str(filename_short)].start()
command = [
"-map", "0",
"-c:v", "copy",
"-c:a", "copy",
"-f", "matroska",
"{path}".format(path=save_file_path),
]
ffmpeg_command.extend(command)
_output = subprocess.check_output(ffmpeg_command, stderr=subprocess.STDOUT)
@ -777,26 +801,41 @@ def start_record(url_tuple, count_variable=-1):
print(f'{rec_info}/{filename}')
save_file_path = full_path + '/' + filename
if create_time_file:
filename_gruop = [anchor_name, filename_short]
create_var[str(filename_short)] = threading.Thread(target=create_ass_file,
args=(filename_gruop,))
create_var[str(filename_short)].daemon = True
create_var[str(filename_short)].start()
try:
command = [
"-map", "0",
"-c:v", "copy", # 直接用copy的话体积特别大.
"-f", "mp4",
"{path}".format(path=save_file_path),
]
if split_video_by_time:
now = time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime())
save_file_path = f"{full_path}/{anchor_name}_{now}_%03d.mp4"
command = [
"-c:v", "copy",
"-c:a", "aac",
"-map", "0",
"-f", "segment",
"-segment_time", split_time,
"-segment_format", "mp4",
"-movflags", "+faststart",
"-reset_timestamps", "1",
save_file_path,
]
else:
if create_time_file:
filename_gruop = [anchor_name, filename_short]
create_var[str(filename_short)] = threading.Thread(
target=create_ass_file,
args=(filename_gruop,))
create_var[str(filename_short)].daemon = True
create_var[str(filename_short)].start()
command = [
"-map", "0",
"-c:v", "copy",
"-c:a", "copy",
"-f", "mp4",
"{path}".format(path=save_file_path),
]
ffmpeg_command.extend(command)
_output = subprocess.check_output(ffmpeg_command, stderr=subprocess.STDOUT)
# 取消http_proxy环境变量设置
# if proxy_addr:
# del os.environ["http_proxy"]
except subprocess.CalledProcessError as e:
# logging.warning(str(e.output))
@ -813,6 +852,7 @@ def start_record(url_tuple, count_variable=-1):
try:
command = [
"-map", "0:a",
"-c:a", "copy",
"-f", "matroska",
"{path}".format(path=save_file_path),
]
@ -836,6 +876,7 @@ def start_record(url_tuple, count_variable=-1):
try:
command = [
"-map", "0:a",
"-c:a", "copy",
"-f", "mpegts",
"{path}".format(path=save_file_path),
]
@ -851,50 +892,48 @@ def start_record(url_tuple, count_variable=-1):
warning_count += 1
no_error = False
else:
if split_video_by_time:
now = time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime())
filename = anchor_name + '_' + now + ".ts"
print(f'{rec_info}/{filename}')
if split_video_by_size: # 这里默认是启用/不启用视频分割功能
while True:
now = time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime(time.time()))
filename = anchor_name + '_' + now + ".ts"
print(f'{rec_info}/{filename}')
save_file_path = full_path + '/' + filename
try:
if tsconvert_to_mp4:
save_path_name = f"{full_path}/{anchor_name}_{now}_%03d.mp4"
audio_code = 'aac'
segment_format = 'mp4'
else:
save_path_name = f"{full_path}/{anchor_name}_{now}_%03d.ts"
audio_code = 'copy'
segment_format = 'mpegts'
if create_time_file:
filename_gruop = [anchor_name, filename_short]
create_var[str(filename_short)] = threading.Thread(
target=create_ass_file,
args=(filename_gruop,))
create_var[str(filename_short)].daemon = True
create_var[str(filename_short)].start()
command = [
"-c:v", "copy",
"-c:a", audio_code,
"-map", "0",
"-f", "segment",
"-segment_time", split_time,
"-segment_format", segment_format,
"-reset_timestamps", "1",
save_path_name,
]
try:
command = [
"-c:v", "copy",
"-map", "0",
"-f", "mpegts",
"-fs", str(split_byte_sizes),
"{path}".format(path=save_file_path),
]
ffmpeg_command.extend(command)
_output = subprocess.check_output(ffmpeg_command,
stderr=subprocess.STDOUT)
ffmpeg_command.extend(command)
_output = subprocess.check_output(ffmpeg_command,
stderr=subprocess.STDOUT)
if tsconvert_to_mp4:
threading.Thread(target=converts_mp4, args=(file,)).start()
if tsconvert_to_m4a:
threading.Thread(target=converts_m4a, args=(file,)).start()
if tsconvert_to_mp4:
threading.Thread(target=converts_mp4, args=(file,)).start()
if tsconvert_to_m4a:
threading.Thread(target=converts_m4a, args=(file,)).start()
except subprocess.CalledProcessError as e:
logging.warning(str(e.output))
logger.warning(
f"错误信息: {e} 发生错误的行数: {e.__traceback__.tb_lineno}")
warning_count += 1
no_error = False
break
except subprocess.CalledProcessError as e:
logging.warning(str(e.output))
logger.warning(
f"错误信息: {e} 发生错误的行数: {e.__traceback__.tb_lineno}")
warning_count += 1
no_error = False
else:
filename = anchor_name + '_' + now + ".ts"
@ -912,6 +951,7 @@ def start_record(url_tuple, count_variable=-1):
try:
command = [
"-c:v", "copy",
"-c:a", "copy",
"-map", "0",
"-f", "mpegts",
"{path}".format(path=save_file_path),
@ -945,7 +985,8 @@ def start_record(url_tuple, count_variable=-1):
if no_error:
print(f"\n{anchor_name} {time.strftime('%Y-%m-%d %H:%M:%S')} 直播录制完成\n")
else:
print(f"\n{anchor_name} {time.strftime('%Y-%m-%d %H:%M:%S')} 直播录制出错,请检查网络\n")
print(
f"\n{anchor_name} {time.strftime('%Y-%m-%d %H:%M:%S')} 直播录制出错,请检查网络\n")
record_finished_2 = False
@ -1010,7 +1051,7 @@ def backup_file(file_path, backup_dir):
timestamp = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
backup_file_name = os.path.basename(file_path) + '_' + timestamp
backup_file_path = os.path.join(backup_dir, backup_file_name)
backup_file_path = os.path.join(backup_dir, backup_file_name).replace("\\", "/")
shutil.copy2(file_path, backup_file_path)
print(f'\r已备份配置文件 {file_path}{backup_file_path}')
@ -1097,7 +1138,7 @@ try:
print('系统代理已开启√ 注意:配置文件中的代理设置也要开启才会生效哦!')
except Exception as e:
print('INFO未检测到全局/规则网络代理请检查代理配置若无需录制Tiktok直播请忽略此条提示')
print('INFO未检测到全局/规则网络代理请检查代理配置若无需录制TikTok直播请忽略此条提示')
def read_config_value(config, section, option, default_value):
@ -1148,12 +1189,12 @@ while True:
proxy_addr = read_config_value(config, '录制设置', '代理地址', "")
max_request = int(read_config_value(config, '录制设置', '同一时间访问网络的线程数', 3))
semaphore = threading.Semaphore(max_request)
delay_default = int(read_config_value(config, '录制设置', '循环时间(秒)', 60))
delay_default = int(read_config_value(config, '录制设置', '循环时间(秒)', 120))
local_delay_default = int(read_config_value(config, '录制设置', '排队读取网址时间(秒)', 0))
loop_time = options.get(read_config_value(config, '录制设置', '是否显示循环秒数', ""), False)
split_video_by_size = options.get(read_config_value(config, '录制设置', 'TS格式分段录制是否开启', ""), False)
split_size = int(read_config_value(config, '录制设置', '视频分段大小(兆)', '1000'))
tsconvert_to_mp4 = options.get(read_config_value(config, '录制设置', 'TS录制完成后自动增加生成MP4格式', ""),
split_video_by_time = options.get(read_config_value(config, '录制设置', '分段录制是否开启', ""), False)
split_time = str(read_config_value(config, '录制设置', '视频分段时间(秒)', 3600))
tsconvert_to_mp4 = options.get(read_config_value(config, '录制设置', 'TS录制完成后自动转为mp4格式', ""),
False)
tsconvert_to_m4a = options.get(read_config_value(config, '录制设置', 'TS录制完成后自动增加生成m4a格式', ""),
False)
@ -1165,10 +1206,10 @@ while True:
dingtalk_phone_num = read_config_value(config, '推送配置', '钉钉通知@对象(填手机号)', "")
dy_cookie = read_config_value(config, 'Cookie', '抖音cookie(录制抖音必须要有)', '')
ks_cookie = read_config_value(config, 'Cookie', '快手cookie', '')
tiktok_cookie = read_config_value(config, 'Cookie', 'Tiktok_cookie', '')
tiktok_cookie = read_config_value(config, 'Cookie', 'tiktok_cookie', '')
hy_cookie = read_config_value(config, 'Cookie', '虎牙cookie', '')
douyu_cookie = read_config_value(config, 'Cookie', '斗鱼cookie', '')
yy_cookie = read_config_value(config, 'Cookie', 'YY_cookie', '')
yy_cookie = read_config_value(config, 'Cookie', 'yy_cookie', '')
bili_cookie = read_config_value(config, 'Cookie', 'B站cookie', '')
xhs_cookie = read_config_value(config, 'Cookie', '小红书cookie', '')
bigo_cookie = read_config_value(config, 'Cookie', 'bigo_cookie', '')
@ -1195,11 +1236,6 @@ while True:
video_save_type = "TS"
print("直播视频保存为TS格式")
# 这里是控制TS分段大小
if split_size < 5:
split_size = 5 # 分段大小最低不能小于5m
split_byte_sizes = split_size * 1024 * 1024 # 分割视频大小,转换为字节
def transform_int_to_time(seconds):
m, s = divmod(seconds, 60)
@ -1285,4 +1321,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: 2023-12-10 01:01:12
Update: 2023-12-10 22:31:12
Copyright (c) 2023 by Hmily, All Rights Reserved.
Function: Get live stream data.
"""
@ -378,7 +378,7 @@ def get_bigo_stream_url(url: str, cookies: Union[str, None] = None) -> Dict[str,
if cookies:
headers['Cookie'] = cookies
room_id = re.search('www.bigo.tv/cn/(\d+)', url).group(1)
room_id = re.search('www.bigo.tv/cn/(\w+)', url).group(1)
data = {'siteId': room_id} # roomId
url2 = 'https://ta.bigo.tv/official_website/studio/getInternalStudioInfo'
data = urllib.parse.urlencode(data).encode('utf-8')
@ -398,6 +398,12 @@ def get_bigo_stream_url(url: str, cookies: Union[str, None] = None) -> Dict[str,
result['m3u8_url'] = m3u8_url
result['is_live'] = True
result['record_url'] = m3u8_url
elif result['anchor_name'] == '':
req = urllib.request.Request(url, headers=headers)
response = opener.open(req, timeout=15)
html_str = response.read().decode('utf-8')
result['anchor_name'] = re.search('<title>(.*?)</title>',html_str,re.S).group(1)
return result
@ -564,4 +570,4 @@ if __name__ == '__main__':
# print(get_bigo_stream_url(url))
# print(get_blued_stream_url(url))
# print(get_afreecatv_cdn_url(url,proxy_addr=''))
# print(get_afreecatv_stream_url(url, proxy_addr=''))
# print(get_afreecatv_stream_url(url, proxy_addr=''))