局域网投屏源码

查看 12|回复 0
作者:soullesfox   
欢迎维护
[color=]import

[color=]tkinter

[color=]as

[color=]tk
[color=]from

[color=]tkinter

[color=]import

[color=]ttk
,
[color=]messagebox
[color=]import

[color=]socket
[color=]import

[color=]threading
[color=]from

[color=]flask

[color=]import

[color=]Flask
,
[color=]Response
,
[color=]request
[color=]import

[color=]mss
[color=]import

[color=]mss
.
[color=]tools
[color=]import

[color=]os
[color=]import

[color=]sys
[color=]import

[color=]time
[color=]import

[color=]subprocess
[color=]from

[color=]PIL

[color=]import

[color=]Image
[color=]import

[color=]io
[color=]import

[color=]queue
[color=]import

[color=]json
[color=]import

[color=]ctypes
[color=]import

[color=]numpy

[color=]as

[color=]np
[color=]import

[color=]cv2
  
[color=]# 添加OpenCV用于高效图像处理
[color=]class

[color=]ScreenMirrorApp
:
   
[color=]def

[color=]__init__
(
[color=]self
,
[color=]root
):
        
[color=]self
.
[color=]root

[color=]=

[color=]root
        
[color=]self
.
[color=]root
.title(
[color=]"低延迟屏幕投屏工具"
)
        
[color=]self
.
[color=]root
.geometry(
[color=]"550x550"
)
        
[color=]self
.
[color=]root
.resizable(
[color=]False
,
[color=]False
)
        
        
[color=]# 设置应用图标
        
[color=]self
.
[color=]set_icon
()
        
        
[color=]# 获取本机IP地址
        
[color=]self
.
[color=]ip_address

[color=]=

[color=]self
.
[color=]get_ip_address
()
        
        
[color=]# 创建UI
        
[color=]self
.
[color=]create_widgets
()
        
        
[color=]# 获取显示器信息
        
[color=]self
.
[color=]monitors

[color=]=

[color=]self
.
[color=]get_monitors
()
        
        
[color=]# 初始化投屏状态
        
[color=]self
.
[color=]mirroring

[color=]=

[color=]False
        
[color=]self
.
[color=]server_thread

[color=]=

[color=]None
        
[color=]self
.
[color=]flask_app

[color=]=

[color=]None
        
[color=]self
.
[color=]last_frame

[color=]=

[color=]None
        
[color=]self
.
[color=]frame_queue

[color=]=

[color=]queue
.
[color=]Queue
(
[color=]maxsize
[color=]=
[color=]1
)
        
[color=]self
.
[color=]capture_thread

[color=]=

[color=]None
        
[color=]self
.
[color=]stop_capture

[color=]=

[color=]threading
.
[color=]Event
()
        
        
[color=]# 自动添加防火墙规则
        
[color=]self
.
[color=]add_firewall_rule
()
        
        
[color=]# 性能参数默认值
        
[color=]self
.
[color=]quality

[color=]=

[color=]70
        
[color=]self
.
[color=]frame_rate

[color=]=

[color=]30
        
[color=]self
.
[color=]resolution

[color=]=

[color=]0.7
        
        
[color=]# 性能计数器
        
[color=]self
.
[color=]frame_count

[color=]=

[color=]0
        
[color=]self
.
[color=]start_time

[color=]=

[color=]time
.
[color=]time
()
        
        
[color=]# 客户端连接状态
        
[color=]self
.
[color=]active_clients

[color=]=

[color=]set
()
        
        
[color=]# 黑屏图像
        
[color=]self
.
[color=]black_image

[color=]=

[color=]self
.
[color=]create_black_image
()
        
        
[color=]# 加载上次选择的设置
        
[color=]self
.
[color=]load_config
()
   
   
[color=]def

[color=]create_black_image
(
[color=]self
):
        
[color=]"""创建黑屏图像"""
        
[color=]img

[color=]=

[color=]Image
.
[color=]new
(
[color=]'RGB'
, (
[color=]100
,
[color=]100
), (
[color=]0
,
[color=]0
,
[color=]0
))
        
[color=]img_byte_arr

[color=]=

[color=]io
.
[color=]BytesIO
()
        
[color=]img
.
[color=]save
(
[color=]img_byte_arr
,
[color=]format
[color=]=
[color=]'JPEG'
,
[color=]quality
[color=]=
[color=]1
)
        
[color=]return

[color=]img_byte_arr
.
[color=]getvalue
()
   
   
[color=]def

[color=]set_icon
(
[color=]self
):
        
[color=]"""设置应用图标"""
        
[color=]try
:
            
[color=]if

[color=]getattr
(
[color=]sys
,
[color=]'frozen'
,
[color=]False
):
               
[color=]icon_path

[color=]=

[color=]os
.
[color=]path
.
[color=]join
(
[color=]sys
._MEIPASS,
[color=]'icon.ico'
)
            
[color=]else
:
               
[color=]icon_path

[color=]=

[color=]'icon.ico'
            
[color=]self
.
[color=]root
.iconbitmap(
[color=]icon_path
)
        
[color=]except
:
            
[color=]pass
   
   
[color=]def

[color=]get_ip_address
(
[color=]self
):
        
[color=]"""获取本机IP地址"""
        
[color=]try
:
            
[color=]s

[color=]=

[color=]socket
.
[color=]socket
(
[color=]socket
.
[color=]AF_INET
,
[color=]socket
.
[color=]SOCK_DGRAM
)
            
[color=]s
.
[color=]connect
((
[color=]"8.8.8.8"
,
[color=]80
))
            
[color=]ip_address

[color=]=

[color=]s
.
[color=]getsockname
()[
[color=]0
]
            
[color=]s
.
[color=]close
()
            
[color=]return

[color=]ip_address
        
[color=]except
:
            
[color=]return

[color=]"127.0.0.1"
   
   
[color=]def

[color=]get_monitors
(
[color=]self
):
        
[color=]"""获取所有显示器信息"""
        
[color=]with

[color=]mss
.
[color=]mss
()
[color=]as

[color=]sct
:
            
[color=]return

[color=]sct
.
[color=]monitors
   
   
[color=]def

[color=]load_config
(
[color=]self
):
        
[color=]"""加载上次的设置"""
        
[color=]config_path

[color=]=

[color=]os
.
[color=]path
.
[color=]join
(
[color=]os
.
[color=]path
.
[color=]expanduser
(
[color=]"~"
),
[color=]".screen_mirror_config.json"
)
        
[color=]try
:
            
[color=]if

[color=]os
.
[color=]path
.
[color=]exists
(
[color=]config_path
):
               
[color=]with

[color=]open
(
[color=]config_path
,
[color=]"r"
)
[color=]as

[color=]f
:
                    
[color=]config

[color=]=

[color=]json
.
[color=]load
(
[color=]f
)
                    
                    
[color=]# 加载屏幕设置
                    
[color=]last_screen

[color=]=

[color=]config
.get(
[color=]"last_screen"
,
[color=]1
)
                    
[color=]if

[color=]1
  
[color=]last_screen
  
[color=]len
(
[color=]self
.
[color=]monitors
):
                        
[color=]self
.
[color=]screen_var
.
[color=]set
(
[color=]last_screen
)
                    
                    
[color=]# 加载性能设置
                    
[color=]quality

[color=]=

[color=]config
.get(
[color=]"quality"
,
[color=]70
)
                    
[color=]if

[color=]30
  
[color=]quality
  
[color=]95
:
                        
[color=]self
.
[color=]quality_var
.
[color=]set
(
[color=]quality
)
                    
                    
[color=]frame_rate

[color=]=

[color=]config
.get(
[color=]"frame_rate"
,
[color=]30
)
                    
[color=]if

[color=]5
  
[color=]frame_rate
  
[color=]60
:
                        
[color=]self
.
[color=]fps_var
.
[color=]set
(
[color=]frame_rate
)
                    
                    
[color=]resolution

[color=]=

[color=]config
.get(
[color=]"resolution"
,
[color=]0.7
)
                    
[color=]if

[color=]0.3
  
[color=]resolution
  
[color=]1.0
:
                        
[color=]self
.
[color=]res_var
.
[color=]set
(
[color=]resolution
)
                    
                    
[color=]self
.
[color=]status_var
.
[color=]set
(
[color=]"已加载上次的设置"
)
        
[color=]except

[color=]Exception

[color=]as

[color=]e
:
            
[color=]self
.
[color=]status_var
.
[color=]set
(
[color=]f
[color=]"加载配置失败:
[color=]{
[color=]str
(
[color=]e
)
[color=]}
[color=]"
)
   
   
[color=]def

[color=]save_config
(
[color=]self
):
        
[color=]"""保存当前设置到配置文件"""
        
[color=]config_path

[color=]=

[color=]os
.
[color=]path
.
[color=]join
(
[color=]os
.
[color=]path
.
[color=]expanduser
(
[color=]"~"
),
[color=]".screen_mirror_config.json"
)
        
[color=]try
:
            
[color=]config

[color=]=
{
               
[color=]"last_screen"
:
[color=]self
.
[color=]screen_var
.
[color=]get
(),
               
[color=]"quality"
:
[color=]self
.
[color=]quality_var
.
[color=]get
(),
               
[color=]"frame_rate"
:
[color=]self
.
[color=]fps_var
.
[color=]get
(),
               
[color=]"resolution"
:
[color=]self
.
[color=]res_var
.
[color=]get
()
            }
            
[color=]os
.
[color=]makedirs
(
[color=]os
.
[color=]path
.
[color=]dirname
(
[color=]config_path
),
[color=]exist_ok
[color=]=
[color=]True
)
            
[color=]with

[color=]open
(
[color=]config_path
,
[color=]"w"
)
[color=]as

[color=]f
:
               
[color=]json
.
[color=]dump
(
[color=]config
,
[color=]f
)
        
[color=]except

[color=]Exception

[color=]as

[color=]e
:
            
[color=]self
.
[color=]status_var
.
[color=]set
(
[color=]f
[color=]"保存配置失败:
[color=]{
[color=]str
(
[color=]e
)
[color=]}
[color=]"
)
   
   
[color=]def

[color=]create_widgets
(
[color=]self
):
        
[color=]"""创建UI界面"""
        
[color=]# 标题
        
[color=]title_label

[color=]=

[color=]ttk
.
[color=]Label
(
[color=]self
.
[color=]root
,
[color=]text
[color=]=
[color=]"低延迟屏幕投屏工具"
,
[color=]font
[color=]=
(
[color=]"Arial"
,
[color=]16
,
[color=]"bold"
))
        
[color=]title_label
.
[color=]pack
(
[color=]pady
[color=]=
[color=]10
)
        
        
[color=]# 屏幕选择
        
[color=]screen_frame

[color=]=

[color=]ttk
.
[color=]LabelFrame
(
[color=]self
.
[color=]root
,
[color=]text
[color=]=
[color=]"选择投屏屏幕"
)
        
[color=]screen_frame
.
[color=]pack
(
[color=]pady
[color=]=
[color=]5
,
[color=]padx
[color=]=
[color=]20
,
[color=]fill
[color=]=
[color=]"x"
)
        
        
[color=]self
.
[color=]screen_var

[color=]=

[color=]tk
.
[color=]IntVar
(
[color=]value
[color=]=
[color=]1
)
        
[color=]screens

[color=]=
[
[color=]"主屏幕"
,
[color=]"屏幕2"
,
[color=]"屏幕3"
,
[color=]"屏幕4"
]
        
        
[color=]for

[color=]i
,
[color=]screen

[color=]in

[color=]enumerate
(
[color=]screens
):
            
[color=]rb

[color=]=

[color=]ttk
.
[color=]Radiobutton
(
               
[color=]screen_frame
,
               
[color=]text
[color=]=
[color=]screen
,
               
[color=]variable
[color=]=
[color=]self
.
[color=]screen_var
,
               
[color=]value
[color=]=
[color=]i
[color=]+
[color=]1
,
               
[color=]command
[color=]=
[color=]self
.
[color=]save_config
            )
            
[color=]rb
.
[color=]grid
(
[color=]row
[color=]=
[color=]0
,
[color=]column
[color=]=
[color=]i
,
[color=]padx
[color=]=
[color=]10
,
[color=]pady
[color=]=
[color=]5
)
        
        
[color=]# 性能设置
        
[color=]perf_frame

[color=]=

[color=]ttk
.
[color=]LabelFrame
(
[color=]self
.
[color=]root
,
[color=]text
[color=]=
[color=]"性能设置"
)
        
[color=]perf_frame
.
[color=]pack
(
[color=]pady
[color=]=
[color=]5
,
[color=]padx
[color=]=
[color=]20
,
[color=]fill
[color=]=
[color=]"x"
)
        
        
[color=]# 图像质量
        
[color=]quality_frame

[color=]=

[color=]ttk
.
[color=]Frame
(
[color=]perf_frame
)
        
[color=]quality_frame
.
[color=]pack
(
[color=]fill
[color=]=
[color=]"x"
,
[color=]padx
[color=]=
[color=]10
,
[color=]pady
[color=]=
[color=]5
)
        
[color=]ttk
.
[color=]Label
(
[color=]quality_frame
,
[color=]text
[color=]=
[color=]"图像质量:"
).
[color=]pack
(
[color=]side
[color=]=
[color=]"left"
)
        
[color=]self
.
[color=]quality_var

[color=]=

[color=]tk
.
[color=]IntVar
(
[color=]value
[color=]=
[color=]70
)
        
[color=]quality_scale

[color=]=

[color=]ttk
.
[color=]Scale
(
            
[color=]quality_frame
,
            
[color=]from_
[color=]=
[color=]30
,
            
[color=]to
[color=]=
[color=]95
,
            
[color=]variable
[color=]=
[color=]self
.
[color=]quality_var
,
            
[color=]orient
[color=]=
[color=]"horizontal"
,
            
[color=]length
[color=]=
[color=]200
,
            
[color=]command
[color=]=
[color=]lambda

[color=]_
:
[color=]self
.
[color=]save_config
()
        )
        
[color=]quality_scale
.
[color=]pack
(
[color=]side
[color=]=
[color=]"left"
,
[color=]padx
[color=]=
[color=]10
)
        
[color=]ttk
.
[color=]Label
(
[color=]quality_frame
,
[color=]textvariable
[color=]=
[color=]self
.
[color=]quality_var
).
[color=]pack
(
[color=]side
[color=]=
[color=]"left"
)
        
        
[color=]# 帧率
        
[color=]fps_frame

[color=]=

[color=]ttk
.
[color=]Frame
(
[color=]perf_frame
)
        
[color=]fps_frame
.
[color=]pack
(
[color=]fill
[color=]=
[color=]"x"
,
[color=]padx
[color=]=
[color=]10
,
[color=]pady
[color=]=
[color=]5
)
        
[color=]ttk
.
[color=]Label
(
[color=]fps_frame
,
[color=]text
[color=]=
[color=]"帧率:"
).
[color=]pack
(
[color=]side
[color=]=
[color=]"left"
)
        
[color=]self
.
[color=]fps_var

[color=]=

[color=]tk
.
[color=]IntVar
(
[color=]value
[color=]=
[color=]30
)
        
[color=]fps_scale

[color=]=

[color=]ttk
.
[color=]Scale
(
            
[color=]fps_frame
,
            
[color=]from_
[color=]=
[color=]5
,
            
[color=]to
[color=]=
[color=]60
,
            
[color=]variable
[color=]=
[color=]self
.
[color=]fps_var
,
            
[color=]orient
[color=]=
[color=]"horizontal"
,
            
[color=]length
[color=]=
[color=]200
,
            
[color=]command
[color=]=
[color=]lambda

[color=]_
:
[color=]self
.
[color=]save_config
()
        )
        
[color=]fps_scale
.
[color=]pack
(
[color=]side
[color=]=
[color=]"left"
,
[color=]padx
[color=]=
[color=]10
)
        
[color=]ttk
.
[color=]Label
(
[color=]fps_frame
,
[color=]textvariable
[color=]=
[color=]self
.
[color=]fps_var
).
[color=]pack
(
[color=]side
[color=]=
[color=]"left"
)
        
        
[color=]# 分辨率
        
[color=]res_frame

[color=]=

[color=]ttk
.
[color=]Frame
(
[color=]perf_frame
)
        
[color=]res_frame
.
[color=]pack
(
[color=]fill
[color=]=
[color=]"x"
,
[color=]padx
[color=]=
[color=]10
,
[color=]pady
[color=]=
[color=]5
)
        
[color=]ttk
.
[color=]Label
(
[color=]res_frame
,
[color=]text
[color=]=
[color=]"分辨率:"
).
[color=]pack
(
[color=]side
[color=]=
[color=]"left"
)
        
[color=]self
.
[color=]res_var

[color=]=

[color=]tk
.
[color=]DoubleVar
(
[color=]value
[color=]=
[color=]0.7
)
        
[color=]res_scale

[color=]=

[color=]ttk
.
[color=]Scale
(
            
[color=]res_frame
,
            
[color=]from_
[color=]=
[color=]0.3
,
            
[color=]to
[color=]=
[color=]1.0
,
            
[color=]variable
[color=]=
[color=]self
.
[color=]res_var
,
            
[color=]orient
[color=]=
[color=]"horizontal"
,
            
[color=]length
[color=]=
[color=]200
,
            
[color=]command
[color=]=
[color=]lambda

[color=]_
:
[color=]self
.
[color=]save_config
()
        )
        
[color=]res_scale
.
[color=]pack
(
[color=]side
[color=]=
[color=]"left"
,
[color=]padx
[color=]=
[color=]10
)
        
[color=]ttk
.
[color=]Label
(
[color=]res_frame
,
[color=]textvariable
[color=]=
[color=]self
.
[color=]res_var
).
[color=]pack
(
[color=]side
[color=]=
[color=]"left"
)
        
        
[color=]# 控制按钮
        
[color=]button_frame

[color=]=

[color=]ttk
.
[color=]Frame
(
[color=]self
.
[color=]root
)
        
[color=]button_frame
.
[color=]pack
(
[color=]pady
[color=]=
[color=]10
)
        
        
[color=]self
.
[color=]start_button

[color=]=

[color=]ttk
.
[color=]Button
(
            
[color=]button_frame
,
            
[color=]text
[color=]=
[color=]"启动投屏"
,
            
[color=]command
[color=]=
[color=]self
.
[color=]start_mirroring
,
            
[color=]width
[color=]=
[color=]15
        )
        
[color=]self
.
[color=]start_button
.
[color=]grid
(
[color=]row
[color=]=
[color=]0
,
[color=]column
[color=]=
[color=]0
,
[color=]padx
[color=]=
[color=]10
)
        
        
[color=]self
.
[color=]stop_button

[color=]=

[color=]ttk
.
[color=]Button
(
            
[color=]button_frame
,
            
[color=]text
[color=]=
[color=]"停止投屏"
,
            
[color=]command
[color=]=
[color=]self
.
[color=]stop_mirroring
,
            
[color=]state
[color=]=
[color=]"disabled"
,
            
[color=]width
[color=]=
[color=]15
        )
        
[color=]self
.
[color=]stop_button
.
[color=]grid
(
[color=]row
[color=]=
[color=]0
,
[color=]column
[color=]=
[color=]1
,
[color=]padx
[color=]=
[color=]10
)
        
        
[color=]# 链接显示
        
[color=]link_frame

[color=]=

[color=]ttk
.
[color=]LabelFrame
(
[color=]self
.
[color=]root
,
[color=]text
[color=]=
[color=]"投屏链接"
)
        
[color=]link_frame
.
[color=]pack
(
[color=]pady
[color=]=
[color=]5
,
[color=]padx
[color=]=
[color=]20
,
[color=]fill
[color=]=
[color=]"x"
)
        
        
[color=]self
.
[color=]link_var

[color=]=

[color=]tk
.
[color=]StringVar
(
[color=]value
[color=]=
[color=]"请先启动投屏"
)
        
[color=]link_label

[color=]=

[color=]ttk
.
[color=]Label
(
            
[color=]link_frame
,
            
[color=]textvariable
[color=]=
[color=]self
.
[color=]link_var
,
            
[color=]font
[color=]=
(
[color=]"Arial"
,
[color=]10
),
            
[color=]anchor
[color=]=
[color=]"center"
        )
        
[color=]link_label
.
[color=]pack
(
[color=]pady
[color=]=
[color=]5
,
[color=]padx
[color=]=
[color=]10
)
        
        
[color=]# 复制链接按钮
        
[color=]copy_button

[color=]=

[color=]ttk
.
[color=]Button
(
            
[color=]link_frame
,
            
[color=]text
[color=]=
[color=]"复制链接"
,
            
[color=]command
[color=]=
[color=]self
.
[color=]copy_link
,
            
[color=]width
[color=]=
[color=]10
        )
        
[color=]copy_button
.
[color=]pack
(
[color=]pady
[color=]=
[color=]5
)
        
        
[color=]# 性能信息
        
[color=]perf_info_frame

[color=]=

[color=]ttk
.
[color=]LabelFrame
(
[color=]self
.
[color=]root
,
[color=]text
[color=]=
[color=]"性能信息"
)
        
[color=]perf_info_frame
.
[color=]pack
(
[color=]pady
[color=]=
[color=]5
,
[color=]padx
[color=]=
[color=]20
,
[color=]fill
[color=]=
[color=]"x"
)
        
        
[color=]self
.
[color=]fps_info_var

[color=]=

[color=]tk
.
[color=]StringVar
(
[color=]value
[color=]=
[color=]"FPS: --"
)
        
[color=]self
.
[color=]latency_var

[color=]=

[color=]tk
.
[color=]StringVar
(
[color=]value
[color=]=
[color=]"延迟: --"
)
        
[color=]self
.
[color=]size_var

[color=]=

[color=]tk
.
[color=]StringVar
(
[color=]value
[color=]=
[color=]"帧大小: --"
)
        
        
[color=]ttk
.
[color=]Label
(
[color=]perf_info_frame
,
[color=]textvariable
[color=]=
[color=]self
.
[color=]fps_info_var
).
[color=]pack
(
[color=]anchor
[color=]=
[color=]"w"
,
[color=]padx
[color=]=
[color=]10
,
[color=]pady
[color=]=
[color=]2
)
        
[color=]ttk
.
[color=]Label
(
[color=]perf_info_frame
,
[color=]textvariable
[color=]=
[color=]self
.
[color=]latency_var
).
[color=]pack
(
[color=]anchor
[color=]=
[color=]"w"
,
[color=]padx
[color=]=
[color=]10
,
[color=]pady
[color=]=
[color=]2
)
        
[color=]ttk
.
[color=]Label
(
[color=]perf_info_frame
,
[color=]textvariable
[color=]=
[color=]self
.
[color=]size_var
).
[color=]pack
(
[color=]anchor
[color=]=
[color=]"w"
,
[color=]padx
[color=]=
[color=]10
,
[color=]pady
[color=]=
[color=]2
)
        
        
[color=]# 联系信息
        
[color=]contact_frame

[color=]=

[color=]ttk
.
[color=]Frame
(
[color=]self
.
[color=]root
)
        
[color=]contact_frame
.
[color=]pack
(
[color=]pady
[color=]=
[color=]5
,
[color=]padx
[color=]=
[color=]20
,
[color=]fill
[color=]=
[color=]"x"
)
        
        
[color=]contact_label

[color=]=

[color=]ttk
.
[color=]Label
(
            
[color=]contact_frame
,
            
[color=]text
[color=]=
[color=]"来自吾爱破解原创 52pojie.cn 如有问题请联系开发者VX: SoullesFox"
,
            
[color=]font
[color=]=
(
[color=]"Arial"
,
[color=]10
,
[color=]"bold"
),
            
[color=]foreground
[color=]=
[color=]"red"
,
            
[color=]anchor
[color=]=
[color=]"center"
        )
        
[color=]contact_label
.
[color=]pack
(
[color=]fill
[color=]=
[color=]"x"
)
        
        
[color=]# 状态栏
        
[color=]self
.
[color=]status_var

[color=]=

[color=]tk
.
[color=]StringVar
(
[color=]value
[color=]=
[color=]"就绪"
)
        
[color=]status_bar

[color=]=

[color=]ttk
.
[color=]Label
(
            
[color=]self
.
[color=]root
,
            
[color=]textvariable
[color=]=
[color=]self
.
[color=]status_var
,
            
[color=]relief
[color=]=
[color=]"sunken"
,
            
[color=]anchor
[color=]=
[color=]"w"
        )
        
[color=]status_bar
.
[color=]pack
(
[color=]side
[color=]=
[color=]"bottom"
,
[color=]fill
[color=]=
[color=]"x"
)
   
   
[color=]def

[color=]add_firewall_rule
(
[color=]self
):
        
[color=]"""添加防火墙规则允许端口5000"""
        
[color=]try
:
            
[color=]command

[color=]=

[color=]f
[color=]'netsh advfirewall firewall show rule name="ScreenMirrorPort5000"'
            
[color=]result

[color=]=

[color=]subprocess
.
[color=]run
(
[color=]command
,
[color=]capture_output
[color=]=
[color=]True
,
[color=]text
[color=]=
[color=]True
,
[color=]shell
[color=]=
[color=]True
)
            
            
[color=]if

[color=]"没有规则"

[color=]in

[color=]result
.
[color=]stdout
:
               
[color=]command

[color=]=
(
                    
[color=]'netsh advfirewall firewall add rule name="ScreenMirrorPort5000" '
                    
[color=]'dir=in action=allow protocol=TCP localport=5000'
                )
               
[color=]subprocess
.
[color=]run
(
[color=]command
,
[color=]shell
[color=]=
[color=]True
)
               
[color=]self
.
[color=]status_var
.
[color=]set
(
[color=]"已添加防火墙规则"
)
        
[color=]except

[color=]Exception

[color=]as

[color=]e
:
            
[color=]self
.
[color=]status_var
.
[color=]set
(
[color=]f
[color=]"防火墙设置失败:
[color=]{
[color=]str
(
[color=]e
)
[color=]}
[color=]"
)
   
   
[color=]def

[color=]copy_link
(
[color=]self
):
        
[color=]"""复制链接到剪贴板"""
        
[color=]if

[color=]self
.
[color=]link_var
.
[color=]get
()
[color=]!=

[color=]"请先启动投屏"
:
            
[color=]self
.
[color=]root
.clipboard_clear()
            
[color=]self
.
[color=]root
.clipboard_append(
[color=]self
.
[color=]link_var
.
[color=]get
())
            
[color=]self
.
[color=]status_var
.
[color=]set
(
[color=]"链接已复制到剪贴板"
)
   
   
[color=]def

[color=]start_mirroring
(
[color=]self
):
        
[color=]"""启动投屏服务"""
        
[color=]if

[color=]self
.
[color=]mirroring
:
            
[color=]return
            
        
[color=]self
.
[color=]mirroring

[color=]=

[color=]True
        
[color=]self
.
[color=]start_button
.
[color=]config
(
[color=]state
[color=]=
[color=]"disabled"
)
        
[color=]self
.
[color=]stop_button
.
[color=]config
(
[color=]state
[color=]=
[color=]"enabled"
)
        
[color=]self
.
[color=]status_var
.
[color=]set
(
[color=]"loading..."
)
        
        
[color=]# 获取当前设置
        
[color=]self
.
[color=]quality

[color=]=

[color=]self
.
[color=]quality_var
.
[color=]get
()
        
[color=]self
.
[color=]frame_rate

[color=]=

[color=]self
.
[color=]fps_var
.
[color=]get
()
        
[color=]self
.
[color=]resolution

[color=]=

[color=]self
.
[color=]res_var
.
[color=]get
()
        
        
[color=]# 重置性能计数器
        
[color=]self
.
[color=]frame_count

[color=]=

[color=]0
        
[color=]self
.
[color=]start_time

[color=]=

[color=]time
.
[color=]time
()
        
        
[color=]# 创建Flask应用
        
[color=]self
.
[color=]flask_app

[color=]=

[color=]Flask
(
[color=]__name__
)
        
        
[color=]# 添加路由
        
[color=]@
[color=]self
[color=].
[color=]flask_app
[color=].
[color=]route
(
[color=]'/'
)
        
[color=]def

[color=]index
():
            
[color=]return

[color=]"""
            
               
                    
                    
                    
[color=]                        body {
[color=]                            text-align: center;
[color=]                            background-color: #000;
[color=]                            margin: 0;
[color=]                            padding: 0;
[color=]                            overflow: hidden;
[color=]                        }
[color=]                        h1 {
[color=]                            color: #333;
[color=]                            margin-top: 10px;
[color=]                        }
[color=]                        img {
[color=]                            max-width: 100%;
[color=]                            max-height: 90vh;
[color=]                            box-shadow: 0 0 10px rgba(0,0,0,0.3);
[color=]                            cursor: pointer;
[color=]                        }
[color=]                        .status {
[color=]                            margin: 10px;
[color=]                            padding: 8px;
[color=]                            background-color: #e0e0e0;
[color=]                            border-radius: 5px;
[color=]                        }
[color=]                        .stats {
[color=]                            margin: 5px;
[color=]                            padding: 5px;
[color=]                            background-color: #d0d0d0;
[color=]                            border-radius: 5px;
[color=]                            display: inline-block;
[color=]                        }
[color=]                        .controls {
[color=]                            position: fixed;
[color=]                            top: 10px;
[color=]                            right: 10px;
[color=]                            background: rgba(255, 255, 255, 0.7);
[color=]                            padding: 5px;
[color=]                            border-radius: 5px;
[color=]                        }
[color=]                        .fullscreen-btn {
[color=]                            background: #4CAF50;
[color=]                            color: white;
[color=]                            border: none;
[color=]                            padding: 5px 10px;
[color=]                            border-radius: 3px;
[color=]                            cursor: pointer;
[color=]                        }
[color=]                        .fullscreen-btn:hover {
[color=]                            background: #45a049;
[color=]                        }
                    
                    
               
               
                    
                        全屏显示
                    
                    正在连接...
                    
                        FPS: -- |
                        延迟: --
                    
                    
               

            
[color=]            """
        
        
[color=]@
[color=]self
[color=].
[color=]flask_app
[color=].
[color=]route
(
[color=]'/screen'
)
        
[color=]def

[color=]screen
():
            
[color=]# 获取客户端唯一ID
            
[color=]client_id

[color=]=

[color=]request
.
[color=]args
.
[color=]get
(
[color=]'cid'
,
[color=]''
)
            
            
[color=]# 生成实时帧
            
[color=]return

[color=]Response
(
               
[color=]self
.
[color=]generate_frames
(
[color=]client_id
),
               
[color=]mimetype
[color=]=
[color=]'multipart/x-mixed-replace; boundary=frame'
            )
        
        
[color=]# 启动屏幕捕获线程
        
[color=]self
.
[color=]start_capture_thread
()
        
        
[color=]# 在后台线程中运行Flask服务器
        
[color=]self
.
[color=]server_thread

[color=]=

[color=]threading
.
[color=]Thread
(
            
[color=]target
[color=]=
[color=]self
.
[color=]run_server
,
            
[color=]daemon
[color=]=
[color=]True
        )
        
[color=]self
.
[color=]server_thread
.
[color=]start
()
        
        
[color=]# 更新链接显示
        
[color=]port

[color=]=

[color=]5000
        
[color=]self
.
[color=]link_var
.
[color=]set
(
[color=]f
[color=]"http://
[color=]{
[color=]self
.
[color=]ip_address
[color=]}
[color=]:
[color=]{
[color=]port
[color=]}
[color=]"
)
        
[color=]self
.
[color=]status_var
.
[color=]set
(
[color=]f
[color=]"投屏已启动 - 正在监听端口
[color=]{
[color=]port
[color=]}
[color=]"
)
        
        
[color=]# 启动性能监控
        
[color=]self
.
[color=]root
.after(
[color=]1000
,
[color=]self
.
[color=]update_performance
)
   
   
[color=]def

[color=]start_capture_thread
(
[color=]self
):
        
[color=]"""启动屏幕捕获线程"""
        
[color=]if

[color=]self
.
[color=]capture_thread

[color=]and

[color=]self
.
[color=]capture_thread
.
[color=]is_alive
():
            
[color=]self
.
[color=]stop_capture
.
[color=]set
()
            
[color=]self
.
[color=]capture_thread
.
[color=]join
(
[color=]timeout
[color=]=
[color=]1.0
)
        
        
[color=]# 清空队列
        
[color=]while

[color=]not

[color=]self
.
[color=]frame_queue
.
[color=]empty
():
            
[color=]try
:
               
[color=]self
.
[color=]frame_queue
.
[color=]get_nowait
()
            
[color=]except

[color=]queue
.
[color=]Empty
:
               
[color=]break
        
        
[color=]# 重置停止标志
        
[color=]self
.
[color=]stop_capture
.
[color=]clear
()
        
        
[color=]# 创建新线程
        
[color=]self
.
[color=]capture_thread

[color=]=

[color=]threading
.
[color=]Thread
(
            
[color=]target
[color=]=
[color=]self
.
[color=]capture_screen
,
            
[color=]args
[color=]=
(
[color=]self
.
[color=]screen_var
.
[color=]get
(),
[color=]self
.
[color=]quality
,
[color=]self
.
[color=]frame_rate
,
[color=]self
.
[color=]resolution
),
            
[color=]daemon
[color=]=
[color=]True
        )
        
[color=]self
.
[color=]capture_thread
.
[color=]start
()
   
   
[color=]def

[color=]capture_screen
(
[color=]self
,
[color=]monitor_idx
,
[color=]quality
,
[color=]frame_rate
,
[color=]resolution
):
        
[color=]"""屏幕捕获线程 - 使用OpenCV优化版本"""
        
[color=]try
:
            
[color=]# 获取显示器信息
            
[color=]monitor

[color=]=

[color=]self
.
[color=]monitors
[
[color=]monitor_idx
]
            
            
[color=]# 计算目标尺寸
            
[color=]width

[color=]=

[color=]int
(
[color=]monitor
[
[color=]'width'
]
[color=]*

[color=]resolution
)
            
[color=]height

[color=]=

[color=]int
(
[color=]monitor
[
[color=]'height'
]
[color=]*

[color=]resolution
)
            
            
[color=]# 计算帧间隔
            
[color=]frame_interval

[color=]=

[color=]1.0

[color=]/

[color=]frame_rate
            
            
[color=]# 初始化性能计数器
            
[color=]last_time

[color=]=

[color=]time
.
[color=]time
()
            
[color=]frame_counter

[color=]=

[color=]0
            
            
[color=]# 使用OpenCV进行高效捕获
            
[color=]with

[color=]mss
.
[color=]mss
()
[color=]as

[color=]sct
:
               
[color=]while

[color=]not

[color=]self
.
[color=]stop_capture
.
[color=]is_set
():
                    
[color=]start_time

[color=]=

[color=]time
.
[color=]time
()
                    
                    
[color=]try
:
                        
[color=]# 捕获屏幕
                        
[color=]screenshot

[color=]=

[color=]sct
.
[color=]grab
(
[color=]monitor
)
                        
                        
[color=]# 转换为numpy数组
                        
[color=]img

[color=]=

[color=]np
.
[color=]array
(
[color=]screenshot
)
                        
                        
[color=]# 调整分辨率
                        
[color=]if

[color=]resolution
  
[color=]1.0
:
                           
[color=]# 使用OpenCV进行快速缩放
                           
[color=]img

[color=]=

[color=]cv2
.
[color=]resize
(
[color=]img
, (
[color=]width
,
[color=]height
),
[color=]interpolation
[color=]=
[color=]cv2
.
[color=]INTER_AREA
)
                        
                        
[color=]# 转换为JPEG - 使用OpenCV高效编码
                        
[color=]_
,
[color=]jpeg_data

[color=]=

[color=]cv2
.
[color=]imencode
(
[color=]'.jpg'
,
[color=]img
, [
[color=]int
(
[color=]cv2
.
[color=]IMWRITE_JPEG_QUALITY
),
[color=]quality
])
                        
                        
[color=]# 放入队列(如果队列已满则替换)
                        
[color=]try
:
                           
[color=]self
.
[color=]frame_queue
.
[color=]put
(
[color=]jpeg_data
.
[color=]tobytes
(),
[color=]block
[color=]=
[color=]False
)
                        
[color=]except

[color=]queue
.
[color=]Full
:
                           
[color=]try
:
                                
[color=]self
.
[color=]frame_queue
.
[color=]get_nowait
()
                           
[color=]except

[color=]queue
.
[color=]Empty
:
                                
[color=]pass
                           
[color=]self
.
[color=]frame_queue
.
[color=]put
(
[color=]jpeg_data
.
[color=]tobytes
(),
[color=]block
[color=]=
[color=]False
)
                        
                        
[color=]# 控制帧率 - 使用更精确的方法
                        
[color=]elapsed

[color=]=

[color=]time
.
[color=]time
()
[color=]-

[color=]start_time
                        
[color=]sleep_time

[color=]=

[color=]max
(
[color=]0
,
[color=]frame_interval

[color=]-

[color=]elapsed
)
                        
                        
[color=]# 如果处理时间超过帧间隔,跳过下一帧
                        
[color=]if

[color=]sleep_time

[color=]>

[color=]0
:
                           
[color=]time
.
[color=]sleep
(
[color=]sleep_time
)
                        
                        
[color=]# 性能计数
                        
[color=]frame_counter

[color=]+=

[color=]1
                        
[color=]current_time

[color=]=

[color=]time
.
[color=]time
()
                        
[color=]if

[color=]current_time

[color=]-

[color=]last_time

[color=]>=

[color=]1.0
:
                           
[color=]actual_fps

[color=]=

[color=]frame_counter

[color=]/
(
[color=]current_time

[color=]-

[color=]last_time
)
                           
[color=]self
.
[color=]status_var
.
[color=]set
(
[color=]f
[color=]"捕获中:
[color=]{
[color=]actual_fps
[color=]:.1f}
[color=] FPS"
)
                           
[color=]last_time

[color=]=

[color=]current_time
                           
[color=]frame_counter

[color=]=

[color=]0
                           
                    
[color=]except

[color=]Exception

[color=]as

[color=]e
:
                        
[color=]self
.
[color=]status_var
.
[color=]set
(
[color=]f
[color=]"捕获错误:
[color=]{
[color=]str
(
[color=]e
)
[color=]}
[color=]"
)
                        
[color=]time
.
[color=]sleep
(
[color=]0.1
)
        
[color=]except

[color=]Exception

[color=]as

[color=]e
:
            
[color=]self
.
[color=]status_var
.
[color=]set
(
[color=]f
[color=]"捕获初始化错误:
[color=]{
[color=]str
(
[color=]e
)
[color=]}
[color=]"
)
   
   
[color=]def

[color=]update_performance
(
[color=]self
):
        
[color=]"""更新性能信息"""
        
[color=]if

[color=]self
.
[color=]mirroring
:
            
[color=]# 计算FPS
            
[color=]elapsed

[color=]=

[color=]time
.
[color=]time
()
[color=]-

[color=]self
.
[color=]start_time
            
[color=]fps

[color=]=

[color=]self
.
[color=]frame_count

[color=]/

[color=]elapsed

[color=]if

[color=]elapsed

[color=]>

[color=]0

[color=]else

[color=]0
            
[color=]self
.
[color=]fps_info_var
.
[color=]set
(
[color=]f
[color=]"FPS:
[color=]{
[color=]fps
[color=]:.1f}
[color=]"
)
            
            
[color=]# 重置计数器
            
[color=]self
.
[color=]frame_count

[color=]=

[color=]0
            
[color=]self
.
[color=]start_time

[color=]=

[color=]time
.
[color=]time
()
            
            
[color=]# 定期检查
            
[color=]self
.
[color=]root
.after(
[color=]1000
,
[color=]self
.
[color=]update_performance
)
   
   
[color=]def

[color=]stop_mirroring
(
[color=]self
):
        
[color=]"""停止投屏服务"""
        
[color=]if

[color=]not

[color=]self
.
[color=]mirroring
:
            
[color=]return
            
        
[color=]self
.
[color=]mirroring

[color=]=

[color=]False
        
[color=]self
.
[color=]start_button
.
[color=]config
(
[color=]state
[color=]=
[color=]"enabled"
)
        
[color=]self
.
[color=]stop_button
.
[color=]config
(
[color=]state
[color=]=
[color=]"disabled"
)
        
[color=]self
.
[color=]status_var
.
[color=]set
(
[color=]"投屏已停止"
)
        
        
[color=]# 停止捕获线程
        
[color=]self
.
[color=]stop_capture
.
[color=]set
()
        
[color=]if

[color=]self
.
[color=]capture_thread

[color=]and

[color=]self
.
[color=]capture_thread
.
[color=]is_alive
():
            
[color=]self
.
[color=]capture_thread
.
[color=]join
(
[color=]timeout
[color=]=
[color=]1.0
)
   
   
[color=]def

[color=]generate_frames
(
[color=]self
,
[color=]client_id
):
        
[color=]"""生成屏幕帧(JPEG格式)"""
        
[color=]while

[color=]self
.
[color=]mirroring
:
            
[color=]try
:
               
[color=]# 从队列获取帧数据
               
[color=]jpeg_data

[color=]=

[color=]self
.
[color=]frame_queue
.
[color=]get
(
[color=]timeout
[color=]=
[color=]0.1
)  
[color=]# 缩短超时时间
               
               
[color=]# 保存最后一帧
               
[color=]self
.
[color=]last_frame

[color=]=

[color=]jpeg_data
               
               
[color=]# 更新帧计数
               
[color=]self
.
[color=]frame_count

[color=]+=

[color=]1
               
               
[color=]# 更新帧大小信息
               
[color=]self
.
[color=]size_var
.
[color=]set
(
[color=]f
[color=]"帧大小:
[color=]{
[color=]len
(
[color=]jpeg_data
)
[color=]/
[color=]1024
[color=]:.1f}
[color=] KB"
)
               
               
[color=]# 生成帧
               
[color=]yield
(
                    
[color=]b
[color=]'--frame
[color=]\r\n
[color=]'
                    
[color=]b
[color=]'Content-Type: image/jpeg
[color=]\r\n\r\n
[color=]'

[color=]+

[color=]jpeg_data

[color=]+

[color=]b
[color=]'
[color=]\r\n
[color=]'
                )
            
[color=]except

[color=]queue
.
[color=]Empty
:
               
[color=]# 队列为空,等待下一帧
               
[color=]time
.
[color=]sleep
(
[color=]0.01
)
            
[color=]except

[color=]Exception

[color=]as

[color=]e
:
               
[color=]self
.
[color=]status_var
.
[color=]set
(
[color=]f
[color=]"传输错误:
[color=]{
[color=]str
(
[color=]e
)
[color=]}
[color=]"
)
               
[color=]time
.
[color=]sleep
(
[color=]0.1
)
        
        
[color=]# 投屏停止后发送黑屏图像
        
[color=]while

[color=]True
:
            
[color=]yield
(
               
[color=]b
[color=]'--frame
[color=]\r\n
[color=]'
               
[color=]b
[color=]'Content-Type: image/jpeg
[color=]\r\n\r\n
[color=]'

[color=]+

[color=]self
.
[color=]black_image

[color=]+

[color=]b
[color=]'
[color=]\r\n
[color=]'
            )
            
[color=]time
.
[color=]sleep
(
[color=]0.1
)
   
   
[color=]def

[color=]run_server
(
[color=]self
):
        
[color=]"""运行Flask服务器"""
        
[color=]try
:
            
[color=]self
.
[color=]flask_app
.
[color=]run
(
               
[color=]host
[color=]=
[color=]'0.0.0.0'
,
               
[color=]port
[color=]=
[color=]5000
,
               
[color=]threaded
[color=]=
[color=]True
,
               
[color=]use_reloader
[color=]=
[color=]False
            )
        
[color=]except

[color=]Exception

[color=]as

[color=]e
:
            
[color=]self
.
[color=]status_var
.
[color=]set
(
[color=]f
[color=]"服务器错误:
[color=]{
[color=]str
(
[color=]e
)
[color=]}
[color=]"
)
            
[color=]self
.
[color=]mirroring

[color=]=

[color=]False
            
[color=]self
.
[color=]start_button
.
[color=]config
(
[color=]state
[color=]=
[color=]"enabled"
)
            
[color=]self
.
[color=]stop_button
.
[color=]config
(
[color=]state
[color=]=
[color=]"disabled"
)
[color=]def

[color=]is_admin
():
   
[color=]"""检查是否以管理员权限运行"""
   
[color=]try
:
        
[color=]return

[color=]ctypes
.
[color=]windll
.shell32.IsUserAnAdmin()
   
[color=]except
:
        
[color=]return

[color=]False
[color=]if

[color=]__name__

[color=]==

[color=]"__main__"
:
   
[color=]# 检查是否以管理员权限运行
   
[color=]if

[color=]os
.
[color=]name

[color=]==

[color=]'nt'

[color=]and

[color=]not

[color=]is_admin
():
        
[color=]# 重新以管理员权限运行
        
[color=]ctypes
.
[color=]windll
.shell32.ShellExecuteW(
[color=]None
,
[color=]"runas"
,
[color=]sys
.
[color=]executable
,
[color=]" "
.
[color=]join
(
[color=]sys
.
[color=]argv
),
[color=]None
,
[color=]1
)
        
[color=]sys
.
[color=]exit
(
[color=]0
)
   
   
[color=]root

[color=]=

[color=]tk
.
[color=]Tk
()
   
[color=]app

[color=]=

[color=]ScreenMirrorApp
(
[color=]root
)
   
[color=]root
.
[color=]protocol
(
[color=]"WM_DELETE_WINDOW"
,
[color=]lambda
: (
[color=]app
.
[color=]stop_mirroring
(),
[color=]root
.
[color=]destroy
()))
   
[color=]root
.
[color=]mainloop
()

屏幕, 性能

您需要登录后才可以回帖 登录 | 立即注册

返回顶部