You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python调用ffmpeg录屏:跨进程发送输入停止录屏失败求助

问题:跨脚本向FFmpeg进程发送输入停止录屏失败

我用FFmpeg实现自定义录屏功能,分为两个脚本:

  • 脚本A:启动录屏,创建FFmpeg子进程录制屏幕,将进程PID写入文件
  • 脚本B:读取PID文件,向对应进程发送'q'输入以停止录屏

脚本A代码

import shlex
import subprocess
import time
import datetime

# Variables
success = True
flowName = "workflow1"

# Get current date and time
now = datetime.datetime.now()

formatted_date = now.strftime("%Y-%m-%d %H:%M:%S")

folderDestination = f"C:\\Users\\MadPe\\Desktop\\pipRec\\workFlows\\{flowName}\\"

formatted_date = formatted_date.replace(":",".").replace(" ","_")

fileName = folderDestination + formatted_date + ".mp4"

ffmpegPath = r"C:\Users\MadPe\Desktop\pipRec\ffmpeg\bin\ffmpeg.exe"

command = shlex.split(f'"{ffmpegPath}" -f gdigrab -framerate 30 -offset_x 0 -offset_y 0 -video_size 1920x1080 -i desktop -y "{fileName}"')
process = subprocess.Popen(command, stdin=subprocess.PIPE)

pid = process.pid
startTime = time.time()

with open("filename.txt", "w") as file:
    file.write(str(pid))

#process.stdin.write(b'q\n') #-- 直接在本脚本执行可以正常停止
#process.stdin.flush()

脚本B代码

import psutil

# Stop recording and kill Process
with open("filename.txt", "r") as f:
    pid = int(f.read().strip())

if psutil.pid_exists(pid):
    process = psutil.Process(pid)
    process.stdin.write(b'q\n')
    process.stdin.flush()
else:
    print(f"Process with PID {pid} is not running.")

问题原因

运行脚本B报错的核心原因是:psutil的Process对象并没有stdin属性。跨进程无法直接访问另一个Python脚本创建的subprocess的标准输入管道——每个进程的文件句柄是独立隔离的,不能跨进程直接调用。


解决方法

方法1:使用命名管道(推荐,优雅停止)

通过Windows命名管道给FFmpeg提供标准输入,让脚本B可以往管道写入停止命令。

修改脚本A:

import shlex
import subprocess
import datetime
import win32pipe
import win32file

# Variables
success = True
flowName = "workflow1"
pipe_name = r'\\.\pipe\ffmpeg_rec_pipe'

# 创建命名管道
pipe = win32pipe.CreateNamedPipe(
    pipe_name,
    win32pipe.PIPE_ACCESS_OUTBOUND,
    win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_WAIT,
    1, 65536, 65536,
    0,
    None
)
# 等待FFmpeg连接管道
win32pipe.ConnectNamedPipe(pipe, None)

# 生成文件名
now = datetime.datetime.now()
formatted_date = now.strftime("%Y-%m-%d %H:%M:%S").replace(":",".").replace(" ","_")
folderDestination = f"C:\\Users\\MadPe\\Desktop\\pipRec\\workFlows\\{flowName}\\"
fileName = folderDestination + formatted_date + ".mp4"
ffmpegPath = r"C:\Users\MadPe\Desktop\pipRec\ffmpeg\bin\ffmpeg.exe"

# 启动FFmpeg,将标准输入绑定到命名管道
command = shlex.split(f'"{ffmpegPath}" -f gdigrab -framerate 30 -offset_x 0 -offset_y 0 -video_size 1920x1080 -i desktop -y "{fileName}"')
process = subprocess.Popen(command, stdin=pipe)

# 将PID和管道名写入文件
with open("filename.txt", "w") as file:
    file.write(f"{process.pid}\n{pipe_name}")

修改脚本B:

import win32file

# 读取PID和管道名
with open("filename.txt", "r") as f:
    lines = f.read().splitlines()
    pipe_name = lines[1]

# 打开命名管道并发送停止命令
try:
    pipe = win32file.CreateFile(
        pipe_name,
        win32file.GENERIC_WRITE,
        0,
        None,
        win32file.OPEN_EXISTING,
        0,
        None
    )
    win32file.WriteFile(pipe, b'q\n')
    win32file.CloseHandle(pipe)
    print("已发送停止命令")
except Exception as e:
    print(f"发送失败:{str(e)}")

方法2:向FFmpeg窗口发送键盘事件

如果不想用命名管道,可以通过窗口句柄找到FFmpeg的控制台窗口,发送'q'按键事件。

修改脚本B:

import psutil
import win32gui
import win32api
import win32con

def get_process_window(pid):
    # 枚举所有窗口,找到对应PID的窗口
    hwnd_list = []
    def enum_callback(hwnd, extra):
        if win32gui.GetWindowThreadProcessId(hwnd)[1] == pid:
            extra.append(hwnd)
        return True
    win32gui.EnumWindows(enum_callback, hwnd_list)
    return hwnd_list[0] if hwnd_list else None

with open("filename.txt", "r") as f:
    pid = int(f.read().strip())

if psutil.pid_exists(pid):
    hwnd = get_process_window(pid)
    if hwnd:
        # 激活窗口并发送q键
        win32gui.SetForegroundWindow(hwnd)
        win32api.keybd_event(ord('Q'), 0, 0, 0)
        win32api.keybd_event(ord('Q'), 0, win32con.KEYEVENTF_KEYUP, 0)
        print("已发送停止按键")
    else:
        print("未找到FFmpeg对应的控制台窗口")
else:
    print(f"PID {pid}的进程不存在")

内容的提问来源于stack exchange,提问作者Noddy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 13:05:03