Python Selenium Webdriver封装ffmpeg录屏函数后无法终止进程如何解决
问题原因与解决方案
你遇到的报错本质是Python变量作用域问题:proc是recorder函数内部定义的局部变量,函数执行完成后外部作用域无法访问该变量,因此调用proc.kill()时会触发「未解析的引用'proc'」报错。
1 修正现有返回实例方案
你当前使用的返回proc实例的方案存在逻辑疏漏,修正后的可运行代码如下:
import subprocess def recorder(recoder_file_name): # 把文件名作为参数传入,避免依赖外部变量,复用性更强 proc = subprocess.Popen(['ffmpeg', '-f', 'gdigrab', '-framerate', '15', '-offset_x', '0', '-offset_y', '0', '-video_size', '1920x1080','-i', 'desktop', '-c:v', 'libx264', '-vprofile', 'baseline', '-g', '15', '-crf', '1', '-pix_fmt', 'yuv420p','-threads', '4', recoder_file_name], stdin=subprocess.PIPE) # 开启标准输入,用于正常结束ffmpeg,避免文件损坏 return proc # 第一段录屏 proc = recorder('output.mkv') # 第一部分业务代码 driver.find_element(By.XPATH, "//*[@id='root']/div/div/div/form/input[1]").send_keys(username) driver.find_element(By.XPATH, "//*[@id='root']/div/div/div/form/input[2]").send_keys(password) driver.find_element(By.XPATH, "//*[@id='root']/div/div/div/form/button").click() # 正常结束录屏,比直接kill更不容易出现文件损坏 proc.stdin.write(b'q') proc.stdin.flush() proc.wait() # 第二段录屏 proc = recorder('output1.mkv') # 第二部分业务代码 # 结束录屏 proc.stdin.write(b'q') proc.stdin.flush() proc.wait()
2 更优实现:上下文管理器方案
如果希望避免手动管理进程终止逻辑,防止代码异常时进程残留、录屏文件损坏,可以用Python上下文管理器封装录屏逻辑,使用更简洁:
import subprocess from contextlib import contextmanager @contextmanager def screen_recorder(file_path, framerate=15, resolution='1920x1080'): # 支持自定义帧率、分辨率,扩展性更强 proc = subprocess.Popen( ['ffmpeg', '-f', 'gdigrab', '-framerate', str(framerate), '-offset_x', '0', '-offset_y', '0', '-video_size', resolution, '-i', 'desktop', '-c:v', 'libx264', '-vprofile', 'baseline', '-g', str(framerate), '-crf', '1', '-pix_fmt', 'yuv420p', '-threads', '4', '-y', file_path], stdin=subprocess.PIPE, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL # 屏蔽ffmpeg的日志输出,避免干扰业务日志 ) try: yield proc finally: # 无论with块内代码是否抛出异常,都会执行结束录屏的逻辑 proc.stdin.write(b'q') proc.stdin.flush() proc.wait(timeout=5) if proc.poll() is None: # 如果正常结束失败再强制kill proc.kill() # 使用方式非常简洁 with screen_recorder('output.mkv'): # 第一部分业务代码,自动录制这段代码的运行过程 driver.find_element(By.XPATH, "//*[@id='root']/div/div/div/form/input[1]").send_keys(username) driver.find_element(By.XPATH, "//*[@id='root']/div/div/div/form/input[2]").send_keys(password) driver.find_element(By.XPATH, "//*[@id='root']/div/div/div/form/button").click() with screen_recorder('output1.mkv'): # 第二部分业务代码 pass
这个方案的优势:
- 不需要手动调用启动、结束录屏的代码,上下文管理器自动处理
- 代码异常时也能正常结束录屏进程,不会出现进程残留,也能降低录屏文件损坏概率
- 录屏参数可自定义,复用性更强
内容的提问来源于stack exchange,提问作者WESTKINz
相关产品推荐
相关产品推荐

