I need to be able to stop it on demand. I tried to gracefully terminate the process with taskkill /im ffmpeg.exe
but it doesn't work. If I force it with /f
then the video file gets corrupted.
I think the alternatives could be:
q
keystroke to the stdin of that process running in background.This is the code (rec.pyw
) I used to create the ffmpeg.exe process, hidden:
import subprocess
import sys
import os
# Creation flags
DETACHED_PROCESS = 0x00000008
CREATE_NO_WINDOW = 0x08000000
CREATE_NEW_PROCESS_GROUP = 0x00000200
cmd = sys._MEIPASS + os.sep + 'ffmpeg.exe -f dshow -i video=screen-capture-recorder -vcodec libx264 -qp 0 -crf 0 -vf scale=1280x720 -preset ultrafast -an -y out.mp4'
r = subprocess.call(cmd.split(), shell=True) #creationflags=
Then I used pyinstaller to create an exe
file with ffmpeg
bundled:
pyinstaller --onefile --noconsole --add-binary ffmpeg.exe;. rec.pyw
I used the creationflags
parameters because I've read that with a detached process I could create the window again. But I haven't found how.
I've found that if I use .mkv
instead of .mp4
the file doesn't get corrupted when killing the ffmpeg process from the task manager.
In your python script you'll need to catch the signal with an except statement. I'm not a windows person, so I don't know how unix signals translate exactly to what you're sending, taskkill
, but do a quick google on how to handle that in python and then in the except block you'll want to call a function that can finish writing the current frame and know to end after that frame is written and then do cleanup which may or may not involve writing more header/metadata to your file and then closing the file handle.
ffmpeg won't shut down cleanly because ffmpeg doesn't run with a window handle on windows, and only programs with a window handle can catch the WM_CLOSE
event that the taskkill
command sends. In fact, ffmpeg isn't even designed to catch a WM_CLOSE
event at all, so even if you create a window handle for ffmpeg with the start
command, it's not going to shut down gracefully when you send the taskkill
The only real solution is to modify ffmpeg itself, or create a wrapper program that has a window handle and can catch the WM_CLOSE
event.
I ran into the same issues and created a wrapper program to handle the WM_CLOSE
event and shut down ffmpeg gracefully. It's written in nim
so you'll have to compile it or you can grab a release from the releases page:
https://github.com/Wykleph/ffmpeg_wrapper
You can launch ffmpeg with the wrapper and kill the wrapper's PID with taskkill
. When the wrapper gets the WM_CLOSE
event it shuts down the ffmpeg process gracefully. You can use mp4
or whatever encoding you need.
ffmpeg_wrap.exe ffmpeg.exe -rtbufsize 150M -f gdigrab -framerate 30 -offset_x 448 -offset_y 240 -video_size 1024x600 -draw_mouse 1 -show_region 1 -i desktop -r 30 -preset ultrafast -tune zerolatency -movflags +faststart screen-recording.mp4
Run that and open up task manager, get the pid
for the ffmpeg_wrap.exe
process and send the taskkill
To use it in python
, just start the ffmpeg_wrap
process and get the PID, then run taskkill
on the PID (you can do this in the same script) when you want it to shut down ffmpeg gracefully.
This program relies on a python dll file. I'm new to nim
and the only way I know how to keep an ffmpeg process open without hanging is with the python subprocess
module. Any of the python dll files that have the subprocess
module should work. I use python3.8.dll
, so that should definitely work. This file should be located at:
C:/Users/username/AppData/Local/Microsoft/WindowsApps
The following linked post taught me to cleanly stop ffmpeg from python by simulating a keypress of 'q':
You create an empty file that you write 'q' to when you are ready to stop it.
To start the ffmpeg stream with python code, do this:
os.system("<stop /usr/bin/ffmpeg ...")
When ready to stop ffmpeg in your python code, do this:
os.system("echo 'q' >stop")
User contributions licensed under CC BY-SA 3.0