From 25a1af42fc703dc635cbc5c86490c04e6db971b7 Mon Sep 17 00:00:00 2001 From: ihmily <961532186@qq.com> Date: Sun, 10 Dec 2023 22:55:42 +0800 Subject: [PATCH] Fix video recording file segmentation and bigo record bugs --- README.md | 25 +++-- config/config.ini | 44 ++++----- main.py | 228 +++++++++++++++++++++++++++------------------- spider.py | 12 ++- 4 files changed, 179 insertions(+), 130 deletions(-) diff --git a/README.md b/README.md index c5b3f35..799bb21 100644 --- a/README.md +++ b/README.md @@ -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端直播间分享地址和网页端长地址都能正常进行录制(抖音尽量用长链接,避免因短链接转换失效导致不能正常录制)。 +直播间分享地址和网页端长地址都能正常进行录制(抖音尽量用长链接,避免因短链接转换失效导致不能正常录制)。 @@ -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接口,上传即可用   diff --git a/config/config.ini b/config/config.ini index d317a12..67c42a1 100644 --- a/config/config.ini +++ b/config/config.ini @@ -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 = \ No newline at end of file diff --git a/main.py b/main.py index cd5ba5e..1ecfb31 100644 --- a/main.py +++ b/main.py @@ -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) \ No newline at end of file + time.sleep(3) diff --git a/spider.py b/spider.py index 481ad45..7f90430 100644 --- a/spider.py +++ b/spider.py @@ -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('(.*?)',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='')) \ No newline at end of file