I'm trying to create a Video Management System application using Python
and Django
, that displays live camera stream and do video recording. For this, I add cameras using POST request and everything works fine.
But when I am required to update a camera's details, like IP address or password, then first I delete the camera and then create a new instance with same camera name. The problem I'm facing is that the process ID of the camera (ffmpeg
instance here) is not updating, e.g. if initially the process ID was 10, then it remains 10 (in terminate() function in the code) even when I re-create the camera with new details but I do get new process ID in start() function.
Below is the code:
import subprocess
from subprocess import Popen
import os, sys
import threading
import time
from datetime import datetime
import pytz
import os, signal
"""This class is used to create camera objects to display live stream and recordings,
it is also used to manage recordings files by deleting them at the given time"""
class CameraStream:
def __init__(self, device_name, username, password, ip_address, storage_days):
self.cam_name = device_name
self.username = username
self.password = password
self.cam_ip = ip_address
self.storage_days = storage_days
self.p1 = None
self.p2 = None
self.p1_id = None
self.p2_id = None
self.recordings_list = []
folder_name = f"videos/Recordings/{self.cam_name}"
folder_name2 = f"videos/LiveStreams/{self.cam_name}"
if not os.path.exists(folder_name):
os.mkdir(folder_name)
if not os.path.exists(folder_name2):
os.mkdir(folder_name2)
self.directory = folder_name
t = threading.Thread(target=self.maintain_recordings, args=())
t.start()
self.live_stream = f"ffmpeg -fflags nobuffer -rtsp_transport tcp -i rtsp://{self.username}:{self.password}@{self.cam_ip}:554/stream1 -copyts -vcodec copy -acodec copy -hls_flags delete_segments+append_list -f hls -hls_time 6 -hls_list_size 5 -hls_segment_type mpegts -hls_segment_filename videos/LiveStreams/{self.cam_name}/%d.ts videos/LiveStreams/{self.cam_name}/index.m3u8".split(" ")
self.recording = f"ffmpeg -use_wallclock_as_timestamps 1 -rtsp_transport tcp -i rtsp://{self.username}:{self.password}@{self.cam_ip}:554/stream1 -vcodec copy -acodec copy -f segment -reset_timestamps 1 -segment_time 1800 -segment_format mp4 -segment_atclocktime 1 -strftime 1 videos/Recordings/{self.cam_name}/%Y%m%dT%H%M%S.mp4".split(" ")
self.start()
def start(self):
self.p1 = Popen(self.live_stream)
self.p2 = Popen(self.recording)
# self.p1.wait() # wait() is not letting the POST request to complete. Hence, using time.sleep() to get process id
# self.p2.wait()
time.sleep(2)
self.p1_id = self.p1.pid
self.p2_id = self.p2.pid
print("In start func: ", self.p1_id, self.p2_id) # gives new process ID here
def terminate_process(self):
print("you have awakened me!")
try:
try:
print("In terminate func: ", self.p1_id, self.p2_id) # gives older process ID here
os.kill(int(self.p1_id), signal.SIGKILL)
os.kill(int(self.p2_id), signal.SIGKILL)
print("terminated by process id!")
except:
print("could not delete by process id!")
try:
self.p1.terminate()
self.p2.terminate()
print("terminated by terminate()")
except:
print("could not delete by terminate()")
try:
self.p1.kill()
self.p2.kill()
print("terminated by kill()")
except:
print("could not delete by kill()")
except Exception as e:
print("Failed to stop ffmpeg: ", e)
I think I'm making a mistake when deleting the ffmpeg
subprocess but can't figure out what it is. Have tried many methods to stop/kill the subprocess but I'm still facing the problem.
I believe there is a problem with the terminate_process() function.
I'm deleting the object by using the del
keyword, e.g. del <obj_name>
, maybe it's keeping the object in the memory but only destroying the reference to that object.