В-нулевых, не прячь импорты, не всегда понятно что откуда берётся.
Во-первых, зачем тебе два уровня вложенности в процессах? Сначала делаешь дочерний процесс через multiprocessing.Process, а потом в нём запускаешь еще один процесс через Popen. Смысл? Собственно, результат предсказуем - ты жестко прибиваешь (kill()) первый дочерний процесс, и он не успевает ничего сделать со вторым.
Во-вторых, Popen уже имеет полезные методы типа terminate(). Но тут есть тонкость - под линуксом этот метод посылает сигнал SIGTERM, на который процесс может отреагировать и спокойно завершить свою работу. Под виндой используется функция WinAPI TerminateProcess(), которая жёстко прибивает процесс, не давая ему шанса завершить работу. Будет практичнее использовать метод signal() в сочетании с константой signal.CTRL_C_EVENT - это будет эквивалентом нажатия Ctrl-C (или Ctrl-Break) в консоли дочернего процесса. Большинство процессов реагируют на это завершением работы. Но под виндой надо будет указать дополнительный параметр для Popen(), чтобы это сработало.
Так что я бы попробовал что-то в таком духе:
import signal
import subprocess
import sys
args = [
"ffmpeg",
"-i", f"rtsp://{camera_login}:{camera_pass}@{camera_host}:554/Streaming/channels/1/",
"-err_detect", "ignore_err",
"-reorder_queue_size", "0",
"-map", "0:v", "-c:v", "copy",
"-f", "rtsp",
"-rtsp_transport", "tcp", f"rtsp://{rtsp_server}:8554/live.stream"
]
params = {'cwd': '.'}
if sys.platform == 'win32': # винда у нас особенная...
params['creationflags'] = (
# subprocess.DETACHED_PROCESS | # если хочешь, чтобы ffmpeg запускался тихо и не спамил в твой stdout
# subprocess.CREATE_NEW_CONSOLE | # если хочешь, чтобы открывалась новая консоль для ffmpeg
subprocess.CREATE_NEW_PROCESS_GROUP # по докам, это требуется для нормальной работы ctrl-c
)
my_subprocess = Popen(args, **params)
try:
pass # тут работаешь с процессом
finally:
my_subprocess.signal(signal.CTRL_C_EVENT) # сигналим процессу о завершении
try:
my_subprocess.wait(timeout=5.0) # ждём завершения
except subprocess.TimeoutExpired: # процесс "задумался"
my_subprocess.kill() # тогда прибиваем