从 Node 杀死一个 Python 进程不会杀死 Python 的子进程(子进程是 ffmpeg.exe)



我正在开发一个Electron应用程序。在这个应用程序中,我生成了一个以文件路径为参数的Python进程,然后文件本身被传递给ffmpeg(通过ffmpeg-Python模块(,然后通过一些Tensorflow函数。

我正在尝试处理用户在整个后台过程中关闭Electron应用程序的情况。不过,从我的测试来看,不管怎样,ffmpeg的进程似乎都会保持不变。我在Windows上,正在查看任务管理器,不确定发生了什么:当关闭Electron应用程序的窗口时,有时ffmpeg.exe将是一个进程,有时它将保留在Electron进程组中。

我注意到,如果我通过关闭窗口来杀死Electron的进程,那么一旦ffmpeg完成了它的工作,python进程也会关闭,所以我想这是成功的一半。问题是,ffmpeg正在做密集的工作,如果用户需要关闭窗口,那么ffmpeg进程也需要终止。但我无论如何都无法做到这一点。

我已经尝试了一些东西,所以我会粘贴一些代码:

main.js

// retrieve video data
ipcMain.handle('get-games', async (event, arg) => {
const spawn = require('child_process').spawn;
const pythonProcess = spawn('python', ["./backend/predict_games.py", arg]);
// sets pythonProcess as a global variable to be accessed when quitting the app
global.childProcess = pythonProcess;
return new Promise((resolve, reject) => {
let result = "";
pythonProcess.stdout.on('data', async (data) => {
data = String(data);
if (data.startsWith("{"))
result = JSON.parse(data);
});
pythonProcess.on('close', () => {
resolve(result);
})
pythonProcess.on('error', (err) => {
reject(err);
});
})
});
app.on('before-quit', function () {
global.childProcess.kill('SIGINT');
});

predict_games.py(ffmpeg部分(

def convert_video_to_frames(fps, input_file):
# a few useful directories
local_dir = os.path.dirname(os.path.abspath(__file__))
snapshots_dir = fr"{local_dir}/snapshots/{input_file.stem}"
# creates snapshots folder if it doesn't exist
Path(snapshots_dir).mkdir(parents=True, exist_ok=True)
print(f"Processing: {Path(fr'{input_file}')}")
try:
(
ffmpeg.input(Path(input_file))
.filter("fps", fps=fps)
.output(f"{snapshots_dir}/%d.jpg", s="426x240", start_number=0)
.run(capture_stdout=True, capture_stderr=True)
)
except ffmpeg.Error as e:
print("stdout:", e.stdout.decode("utf8"))
print("stderr:", e.stderr.decode("utf8"))

有人知道吗?

好吧,我终于能够解决这个问题了!由于ffmpeg-python只是好的旧ffmpeg的绑定集合,因此可执行文件本身仍然是模块的核心。这也意味着,当ffmpeg运行时,会出现类似于以下内容的屏幕:

... 
Metadata:
handler_name    : VideoHandler
vendor_id       : [0][0][0][0]
Stream #0:1[0x2](und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 159 kb/s (default)
Metadata:
handler_name    : SoundHandler
vendor_id       : [0][0][0][0]
Stream mapping:
Stream #0:0 (h264) -> fps:default
fps:default -> Stream #0:0 (mjpeg)
...
Press [q] to stop, [?] for help

是幕后发生的事情。一旦我意识到这一点,我所要做的就是找到一种方法,将"q"发送到ffmpeg的stdin。我在window-all-closed事件上添加了这个片段:

app.on('window-all-closed', () => {
// writes a 'q' in ffmpeg's terminal to quit ffmpeg's process
// reminder: python gets closed when the Electron app is closed
global.childProcess.stdin.write("qn");
if (process.platform !== 'darwin') app.quit()
})

与问题中的片段相比,Python脚本本身没有受到影响,这是我最终修改的唯一内容。现在,每次我退出Electron应用程序时,ffmpeg都会收到一个"q"。Python进程不需要手动终止,因为Electron已经为您完成了这项工作。

所以问题解决了。:(

最新更新