From 7c051481c7a62c7628a6b48f4c54dae66dd8e46f Mon Sep 17 00:00:00 2001 From: NB-XX <53631369+NB-XX@users.noreply.github.com> Date: Sun, 5 Jun 2022 17:52:23 +0800 Subject: [PATCH] updated Toggle Button --- y2qq.py | 27 +++++++++++++--- y2qq_GUI.py | 92 ++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 85 insertions(+), 34 deletions(-) diff --git a/y2qq.py b/y2qq.py index 34133e6..d904f75 100644 --- a/y2qq.py +++ b/y2qq.py @@ -70,6 +70,7 @@ def restream(m3u8, video_id, selected_format, in_ffmpeg, in_server_url, in_key): # 取代远端 m3u8, 本地读取 m3u8 合并多个Seq video_id = video_id + video_url = f'https://www.youtube.com/watch?v={video_id}' m3u8_cache.setup_m3u8_src(video_id, m3u8) local_m3u8_url = m3u8_cache.server_produce_m3u8(video_id, m3u8) sg.cprint(f"本地 m3u8 url:\n{local_m3u8_url}") @@ -77,7 +78,8 @@ def restream(m3u8, video_id, selected_format, in_ffmpeg, in_server_url, in_key): using_m3u8 = local_m3u8_url ffmpeg_path = in_ffmpeg - server_url = in_server_url if in_server_url.endswith("/") else in_server_url + "/" + server_url = in_server_url if in_server_url.endswith( + "/") else in_server_url + "/" key = in_key # FFMPEG 命令 @@ -114,7 +116,8 @@ def restream(m3u8, video_id, selected_format, in_ffmpeg, in_server_url, in_key): if float(speed) < 0.8: trigger_time += 1 if trigger_time > 3: - __refresh_remote_m3u8(video_id, video_url, selected_format) + __refresh_remote_m3u8( + video_id, video_url, selected_format) trigger_time = 0 except Exception as e: pass @@ -133,6 +136,20 @@ def restream(m3u8, video_id, selected_format, in_ffmpeg, in_server_url, in_key): stop_restream() +def restream_direct(m3u8, in_ffmpeg, in_key): + global g_process + ffmpeg_path = in_ffmpeg + key = in_key + try: + g_process = sp.Popen( + [ffmpeg_path, '-i', m3u8, '-vcodec', 'copy', '-acodec', 'aac', '-f', 'flv', f"rtmp://6721.livepush.myqcloud.com/live/{key}"], stdout=sp.PIPE, stderr=sp.STDOUT, universal_newlines=True) + for line in g_process.stdout: + if 'speed' in line: + sg.cprint(line.rstrip("\n")) + except: + sg.cprint('推流失败') + + def stop_restream(): global g_process if g_process is not None: @@ -199,7 +216,8 @@ def check_live(url): def check_update_info(): - response = requests.get("https://api.github.com/repos/NB-XX/y2qq/releases/latest") + response = requests.get( + "https://api.github.com/repos/NB-XX/y2qq/releases/latest") info_dict = response.json() return info_dict @@ -236,7 +254,8 @@ def check_update(window: sg.Window): def update_exe(assets, window: sg.Window): - thread = threading.Thread(target=__update_exe, args=(assets, window), daemon=True) + thread = threading.Thread( + target=__update_exe, args=(assets, window), daemon=True) thread.start() diff --git a/y2qq_GUI.py b/y2qq_GUI.py index 116457f..4b77897 100644 --- a/y2qq_GUI.py +++ b/y2qq_GUI.py @@ -1,7 +1,7 @@ import threading import time import PySimpleGUI as sg - +import textwrap import y2qq from m3u8_cache import server @@ -9,14 +9,19 @@ # start a local server server.start_server() +graphic_off = True format_list = [] g_current_selected_format = 0 g_current_m3u8_url = "" +toggle_btn_off = b'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABmJLR0QA/wD/AP+gvaeTAAAED0lEQVRYCe1WTWwbRRR+M/vnv9hO7BjHpElMKSlpqBp6gRNHxAFVcKM3qgohQSqoqhQ45YAILUUVDRxAor2VAweohMSBG5ciodJUSVqa/iikaePEP4nj2Ovdnd1l3qqJksZGXscVPaylt7Oe/d6bb9/svO8BeD8vA14GvAx4GXiiM0DqsXv3xBcJU5IO+RXpLQvs5yzTijBmhurh3cyLorBGBVokQG9qVe0HgwiXLowdy9aKsY3g8PA5xYiQEUrsk93JTtjd1x3siIZBkSWQudUK4nZO1w3QuOWXV+HuP/fL85klAJuMCUX7zPj4MW1zvC0Ej4yMp/w++K2rM9b70sHBYCjo34x9bPelsgp/XJksZ7KFuwZjr3732YcL64ttEDw6cq5bVuCvgy/sje7rT0sI8PtkSHSEIRIKgCQKOAUGM6G4VoGlwiqoVd2Za9Vl8u87bGJqpqBqZOj86eEHGNch+M7otwHJNq4NDexJD+59RiCEQG8qzslFgN8ibpvZNsBifgXmFvJg459tiOYmOElzYvr2bbmkD509e1ylGEZk1Y+Ssfan18n1p7vgqVh9cuiDxJPxKPT3dfGXcN4Tp3dsg/27hUQs0qMGpRMYjLz38dcxS7Dm3nztlUAb38p0d4JnLozPGrbFfBFm79c8hA3H2AxcXSvDz7/+XtZE1kMN23hjV7LTRnKBh9/cZnAj94mOCOD32gi2EUw4FIRUMm6LGhyiik86nO5NBdGRpxYH14bbjYfJteN/OKR7UiFZVg5T27QHYu0RBxoONV9W8KQ7QVp0iXdE8fANUGZa0QAvfhhXlkQcmjJZbt631oIBnwKmacYoEJvwiuFgWncWnXAtuVBBEAoVVXWCaQZzxmYuut68b631KmoVBEHMUUrJjQLXRAQVSxUcmrKVHfjWWjC3XOT1FW5QrWpc5IJdQhDKVzOigEqS5dKHMVplnNOqrmsXqUSkn+YzWaHE9RW1FeXL7SKZXBFUrXW6jIV6YTEvMAUu0W/G3kcxPXP5ylQZs4fa6marcWvvZfJu36kuHjlc/nMSuXz+/ejxgqPFpuQ/xVude9eu39Jxu27OLvBGoMjrUN04zrNMbgVmOBZ96iPdPZmYntH5Ls76KuxL9NyoLA/brav7n382emDfHqeooXyhQmARVhSnAwNNMx5bu3V1+habun5nWdXhwJZ2C5mirTesyUR738sv7g88UQ0rEkTDlp+1wwe8Pf0klegUenYlgyg7bby75jUTITs2rhCAXXQ2vwxz84vlB0tZ0wL4NEcLX/04OrrltG1s8aOrHhk51SaK0us+n/K2xexBxljcsm1n6x/Fuv1PCWGiKOaoQCY1Vb9gWPov50+fdEqd21ge3suAlwEvA14G/ucM/AuppqNllLGPKwAAAABJRU5ErkJggg==' +toggle_btn_on = b'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABmJLR0QA/wD/AP+gvaeTAAAD+UlEQVRYCe1XzW8bVRCffbvrtbP+2NhOD7GzLm1VoZaPhvwDnKBUKlVyqAQ3/gAkDlWgPeVQEUCtEOIP4AaHSI0CqBWCQyXOdQuRaEFOk3g3IMWO46+tvZ+PeZs6apq4ipON1MNafrvreTPzfvub92bGAOEnZCBkIGQgZOClZoDrh25y5pdjruleEiX+A+rCaQo05bpuvJ/+IHJCSJtwpAHA/e269g8W5RbuzF6o7OVjF8D3Pr4tSSkyjcqfptPDMDKSleW4DKIggIAD5Yf+Oo4DNg6jbUBlvWLUNutAwZu1GnDjzrcXzGcX2AHw/emFUV6Sfk0pqcKpEydkKSo9q3tkz91uF5aWlo1Gs/mYc+i7tz4//19vsW2AU9O381TiioVCQcnlRsWeQhD3bJyH1/MiFLICyBHiuzQsD1arDvypW7DR9nzZmq47q2W95prm+I9fXfqXCX2AF2d+GhI98Y8xVX0lnxvl2UQQg0csb78ag3NjEeD8lXZ7pRTgftmCu4864OGzrq+5ZU0rCa3m+NzXlzvoAoB3+M+SyWQuaHBTEzKMq/3BMbgM+FuFCDBd9kK5XI5PJBKqLSev+POTV29lKB8rT0yMD0WjUSYLZLxzNgZvIHODOHuATP72Vwc6nQ4Uiw8MUeBU4nHS5HA6TYMEl02wPRcZBJuv+ya+UCZOIBaLwfCwQi1Mc4QXhA+PjWRkXyOgC1uIhW5Qd8yG2TK7kSweLcRGKKVnMNExWWBDTQsH9qVmtmzjiThQDs4Qz/OUSGTwcLwIQTLW58i+yOjpXDLqn1tgmDzXzRCk9eDenjo9yhvBmlizrB3V5dDrNTuY0A7opdndStqmaQLPC1WCGfShYRgHdLe32UrV3ntiH9LliuNrsToNlD4kruN8v75eafnSgC6Luo2+B3fGKskilj5muV6pNhk2Qqg5v7lZ51nBZhNBjGrbxfI1+La5t2JCzfD8RF1HTBGJXyDzs1MblONulEqPDVYXgwDIfNx91IUVbAbY837GMur+/k/XZ75UWmJ77ou5mfM1/0x7vP1ls9XQdF2z9uNsPzosXPNFA5m0/EX72TBSiqsWzN8z/GZB08pWq9VeEZ+0bjKb7RTD2i1P4u6r+bwypo5tZUumEcDAmuC3W8ezIqSGfE6g/sTd1W5p5bKjaWubrmWd29Fu9TD0GlYlmTx+8tTJoZeqYe2BZC1/JEU+wQR5TVEUPptJy3Fs+Vkzgf8lemqHumP1AnYoMZSwsVEz6o26i/G9Lgitb+ZmLu/YZtshfn5FZDPBCcJFQRQ+8ih9DctOFvdLIKHH6uUQnq9yhFu0bec7znZ+xpAGmuqef5/wd8hAyEDIQMjAETHwP7nQl2WnYk4yAAAAAElFTkSuQmCC' sg.theme("DarkAmber") + + # 设置控件属性 update_button = sg.Button("更新版本", key="check_update", size=10) -auto_live_check = sg.Button("挂机模式", key="-isLiveNow-") +auto_live_check = sg.Button("挂机模式", key="-isLiveNow-", size=14) ff_text = sg.Text("设置ffmpeg路径") ff_input = sg.Input("", key="ff", size=4) port_text = sg.Text("输入代理端口") @@ -26,11 +31,13 @@ ) save_button = sg.Button("保存配置", key="save_yaml", size=14) read_button = sg.Button("使用配置", key="read_yaml", size=14) - +switch_button = sg.Button('', image_data=toggle_btn_off, key='-TOGGLE-GRAPHIC-', + button_color=(sg.theme_background_color(), sg.theme_background_color()), border_width=0) +switch_text = sg.Text('本地m3u8中转: ') url_text = sg.Text("输入youtube链接") -url_input = sg.InputText(key="url", size=6) +url_input = sg.InputText(key="url", size=25) -m3u8_button = sg.Button("获取直播信息", size=9) +m3u8_button = sg.Button("获取直播信息", size=14) key_text = sg.Text("输入直播密钥") key_input = sg.InputText(key="key", size=20) @@ -41,7 +48,7 @@ output_Ml = sg.Multiline( key="Output", disabled=True, size=(50, 17), autoscroll=True, reroute_cprint=True ) -start_button = sg.Button("开始直播", size=14) +start_button = sg.Button("开始直播", key='-start_button-', size=14) stop_button = sg.Button("停止推流", visible=False, size=14) format_list_text = sg.Text("选择分辨率") format_list_selector = sg.Combo( @@ -49,7 +56,8 @@ ) tilte_text = sg.Text("", key="-title-") main_tab = [ - [url_text, url_input, m3u8_button], + [url_text, url_input], + [m3u8_button, switch_text, switch_button], [format_list_text, format_list_selector], [start_button, stop_button], [auto_live_check], @@ -136,12 +144,6 @@ def windows_init(window: sg.Window): call_window_event_value_with_delay(window, "获取直播信息") -def wrap(string): - cut_result = [string[i : i + 35] for i in range(0, len(string), 35)] - result = "\n".join(cut_result) - return result - - # ---windows init and event loop try: window = sg.Window("QQ频道转播", layout, finalize=True) @@ -158,6 +160,10 @@ def wrap(string): y2qq.set_proxy(values["port"]) except: sg.Popup("请输入端口数字") + elif event == '-TOGGLE-GRAPHIC-': + graphic_off = not graphic_off + window['-TOGGLE-GRAPHIC-'].update( + image_data=toggle_btn_off if graphic_off else toggle_btn_on) elif event == "获取直播信息": # 开启新进程获取直播信息 window.perform_long_operation( @@ -176,7 +182,7 @@ def wrap(string): call_window_event_value_with_delay( window, "-SELECTOR-", format_list[-1] ) - title = wrap(formats_raw["title"][:-17]) + title = textwrap.fill(formats_raw["title"][:-17], 35) window["-title-"].update(title) except: pass @@ -190,27 +196,53 @@ def wrap(string): g_current_m3u8_url = formats[index]["url"] sg.cprint(f"当前选择:{g_current_selected_format}") - elif event == "开始直播": + elif event == "-start_button-": + # 判断是否开启本地转发 + if graphic_off == False: + try: + btn_save_config_yaml(values, should_pop_up=False) + + # 开启新进程 用于持续打印推流情况 + window.perform_long_operation( + lambda: y2qq.restream( + g_current_m3u8_url, + formats_raw["id"], + g_current_selected_format, + values["ff"], + values["live_server"], + values["key"], + ), + "-restream-", + ) + window["停止推流"].update(visible=True) + except Exception as e: + sg.Popup("推流失败,检查密钥和ffmpeg是否配置正确") + else: + try: + btn_save_config_yaml(values, should_pop_up=False) + # 开启新进程 用于持续打印推流情况 + window.perform_long_operation( + lambda: y2qq.restream_direct( + g_current_m3u8_url, + values["ff"], + values["key"], + ), + "-restream-", + ) + window["停止推流"].update(visible=True) + except Exception as e: + sg.Popup("推流失败,检查密钥和ffmpeg是否配置正确") + elif event == "-start_button-": try: - btn_save_config_yaml(values, should_pop_up=False) - - # 开启新进程 用于持续打印推流情况 window.perform_long_operation( - lambda: y2qq.restream( - g_current_m3u8_url, - formats_raw["id"], - g_current_selected_format, - values["ff"], - values["live_server"], - values["key"], - ), - "-restream-", - ) + lambda: y2qq.restream_direct(g_current_m3u8_url, values['ff'], values['key']), '-restream_direct-') window["停止推流"].update(visible=True) - except Exception as e: - sg.Popup("推流失败,检查密钥和ffmpeg是否配置正确") + except: + sg.Popup('推流失败,检查m3u8、密钥和ffmpeg是否配置正确') elif event == "-restream-": pass + elif event == "-restream_direct-": + pass elif event == "-isLiveNow-": window.perform_long_operation( lambda: y2qq.check_live(values["url"]), "-check-"