diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..72e515e --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# Build and Release Folders +bin-debug/ +bin-release/ +[Oo]bj/ +[Bb]in/ + +# Other files and folders +.settings/ + +# Executables +*.swf +*.air +*.ipa +*.apk + +# Project files, i.e. `.project`, `.actionScriptProperties` and `.flexProperties` +# should NOT be excluded as they contain compiler settings and other important +# information for Eclipse / Flash Builder. + + +.venv/ +.logs/ +dist/ +build/ + + +*.png +*.mp4 +*.mp3 +*.spec \ No newline at end of file diff --git a/.release/app.py b/.release/app.py new file mode 100644 index 0000000..8cbc3bb --- /dev/null +++ b/.release/app.py @@ -0,0 +1,2 @@ +import os +print(12) \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..4b4de49 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,9 @@ +{ + "editor.fontSize": 12, + "editor.formatOnSave": true, + "files.autoSave": "onFocusChange", + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.wordWrap": "on", + "workbench.colorTheme": "VS Code Dark", + "editor.formatOnPaste": true +} diff --git a/aiortcToJs.py b/aiortcToJs.py new file mode 100644 index 0000000..03860a7 --- /dev/null +++ b/aiortcToJs.py @@ -0,0 +1,89 @@ +""" +尝试通过aiortc获取屏幕传递到前端js +""" + +import webview +import threading +import time,os + +CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) + +from module.record_screen_to_mp4 import ScreenVideoTrack,SystemAudioTrack + +# ---------------------- 1. 定义供 JS 调用的 Python 函数 ---------------------- +class Api: + """暴露给 JS 的 Python 接口类(所有方法都会被 JS 访问)""" + def __init__(self): + self.video_track = None + self.audio_track = None + + def set_window(self, window): + """初始化时绑定窗口实例""" + self.window = window + + async def fetch_media(self): + self.video_track = ScreenVideoTrack(fps=30, scale_factor=0.8) + self.audio_track = SystemAudioTrack(sample_rate=48000) + return self.video_track,self.audio_track + + def python_hello(self, name): + """JS 调用的同步函数:接收参数,返回结果""" + print(f"[Python] 收到 JS 调用,参数:{name}") + return f"Hello {name}! 这是 Python 返回的消息" + + def python_async_task(self, duration): + """JS 调用的异步函数:模拟耗时任务(不阻塞前端)""" + def async_task(): + print(f"[Python] 开始异步任务,耗时 {duration} 秒") + time.sleep(duration) + # 异步任务完成后,主动调用 JS 函数通知结果 + self.window.evaluate_js(f'js_receive_python_msg("异步任务完成!耗时 {duration} 秒")') + print(f"[Python] 异步任务结束") + + # 启动子线程执行异步任务,避免阻塞 UI + threading.Thread(target=async_task, daemon=True).start() + return "异步任务已启动,请等待结果通知" + + def python_close_window(self): + """JS 调用关闭窗口""" + print("[Python] 收到关闭窗口请求") + self.window.destroy() + +# ---------------------- 2. Python 主动调用 JS 函数 ---------------------- +def python_call_js_periodically(window): + """Python 定时调用 JS 函数(模拟主动推送数据)""" + count = 0 + while window: + count += 1 + # 执行 JS 函数,传递参数 + window.evaluate_js(f'js_receive_python_msg("Python 主动推送:第 {count} 条消息")') + time.sleep(3) # 每 3 秒推送一次 + if count >= 5: + break + +# ---------------------- 3. 启动窗口 ---------------------- +if __name__ == "__main__": + # 创建 API 实例 + api = Api() + + # 加载本地 HTML 文件(也可加载远程 URL:url="https://xxx.com") + window = webview.create_window( + title="PyWebView 双向通信示例", + # url="app_JsToPy.html", # 前端页面路径 + url=f"file:///{CURRENT_DIR}/app.html", + resizable=True, + js_api=api # 关键:暴露 Python API 给 JS + ) + + # 绑定窗口实例到 API(供异步任务调用 JS) + api.set_window(window) + + # 启动 Python 主动调用 JS 的线程(非阻塞) + threading.Thread(target=python_call_js_periodically, args=(window,), daemon=True).start() + + # 运行窗口(阻塞主线程) + webview.start( + private_mode=False, # WebRTC必需关闭私有模式 + debug=True, # 开发环境开启调试,生产环境关闭 + http_server=True # 启用内置 HTTP 服务器(加载本地 HTML 必需) + ) \ No newline at end of file diff --git a/app.html b/app.html new file mode 100644 index 0000000..4e0be12 --- /dev/null +++ b/app.html @@ -0,0 +1,52 @@ + + + + + 测试应用 + + + + +
+

1111111111111

+
+ +
+ + + + + diff --git a/app.py b/app.py new file mode 100644 index 0000000..21cd946 --- /dev/null +++ b/app.py @@ -0,0 +1,61 @@ + + +# 关键:确保Windows安装了WebView2运行时(pywebview2必需) +# 下载地址:https://developer.microsoft.com/zh-CN/microsoft-edge/webview2/#download-section + + +import sys,os,time +import threading + +CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) + + +'''定义供 JS 调用的 Python 函数''' +class Api: + """暴露给 JS 的 Python 接口类(所有方法都会被 JS 访问)""" + def __init__(self): + self.window = None # 保存窗口实例,用于 Python 主动调用 JS + + def set_window(self, window): + """初始化时绑定窗口实例""" + self.window = window + + def python_close_window(self): + """JS 调用关闭窗口""" + print("[Python] 收到关闭窗口请求") + self.window.destroy() + +'''Python 主动调用 JS 函数''' +def python_call_js_periodically(window): + """Python 定时调用 JS 函数(模拟主动推送数据)""" + count = 0 + while window: + count += 1 + # 执行 JS 函数,传递参数 + window.evaluate_js(f'js_receive_python_msg("Python主动推送:第{count}条消息")') + time.sleep(3) # 每 3 秒推送一次 + if count >= 5:break + +import webview +if __name__ == '__main__': + api = Api() + + window = webview.create_window( + title='PyWebView', # 窗口标题 + url=f"file:///{CURRENT_DIR}/app.html", + resizable=True, # 是否允许调整窗口大小(默认 True) + transparent=True, + # frameless=True, + # easy_drag=True, # 窗口无边框 + js_api=api + ) + # 绑定窗口实例到 API(供异步任务调用 JS) + api.set_window(window) + + threading.Thread(target=python_call_js_periodically, args=(window,), daemon=True).start() + + webview.start( + private_mode=False, # WebRTC必需关闭私有模式 + # debug=True, + http_server=True + ) \ No newline at end of file diff --git a/assets/alpine.min.js b/assets/alpine.min.js new file mode 100644 index 0000000..10193aa --- /dev/null +++ b/assets/alpine.min.js @@ -0,0 +1,8 @@ +/** + * Minified by jsDelivr using Terser v5.37.0. + * Original file: /gh/alpinejs/alpine@2.8.2/dist/alpine.js + * + * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files + */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).Alpine=t()}(this,(function(){"use strict";function e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function t(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function n(n){for(var i=1;i tags. See https://github.com/alpinejs/alpine#${t}`):1!==e.content.childElementCount&&console.warn(`Alpine: