I am participating in a project using RTSP and cameras footage. My objective is to create a continuous flow of videos streamed in the same address and route to update the videos according to the footage we need to display.
So, the expected behavior I have to create is to change the video streamed in the address while using ffplay to visualize the stream I am creating. This is recreated by this diagram:
But this simply does not work. Whenever I try to change the video, the original video just freeze and it is impossible to visualize anything. ffplay throws an error: rtsp://localhost:8554/sample: error while seeking
. And this is weird for me because when I shut down the transmition and I open it again, it shows the changed footage that I wanted to visualize now.
To create the RTSP server I am using this repository: https://github.com/p513817/rtsp4k. It is based on mediamtx and Python to recreate all the logic.
I have no knowledge in RTSP, so I don't know if I should do anything low-level to keep the flow without finishing the video or I should try other framework. I need help!
The logic I am doing to update the video is
def put_placeholder(self, input:str, route: str):
success = True
try:
# I change the Displayer to show my placeholder instead the original video
self.dprs[route] = Displayer(
input='./utils/placeholder.mp4',
route=str(route),
start_stream=True
)
# Same here
if route in PARAMS.CONF["streams"] :
PARAMS.CONF["streams"][route] = {
"input": './utils/placeholder.mp4'
}
write_config(PARAMS.CONF_PATH, PARAMS.CONF)
except Exception as e:
logging.exception(e)
success = False
finally:
# I update the info in the .json that summarize all the streams
self._update_info(
input='./utils/placeholder.mp4',
route=route,
url=self.dprs[route].get_url() if success else "",
status=success )
return self.info[route]
I realized that I was creating a new object instead of changing the current one. This made that ffplay was incapable of keeping track of the address and route because loses connection and then it is reconnected immediately, making the stream to crash.
The final code for updating the videos is a modification of the function put_placeholder
that I created in the Manager class in rtsp_handler.py
. It is added a new function called change_input()
in the Displayer class by creating a function that updates the file's path and not creates a new thread or class instance.
def put_placeholder(self, input:str, route: str):
success = True
try:
# NOTE: modify config
path = ""
if input == 'placeholder':
path = './utils/placeholder.mp4'
else:
path = './data/'+input+'.mp4'
self.dprs[route].change_input(path)
if route in PARAMS.CONF["streams"] :
PARAMS.CONF["streams"][route] = {
"input": path
}
write_config(PARAMS.CONF_PATH, PARAMS.CONF)
except Exception as e:
logging.exception(e)
success = False
finally:
self._update_info(
input=path,
route=route,
url=self.dprs[route].get_url() if success else "",
status=success )
return self.info[route]
def change_input(self, new_input:str):
self.input = new_input
self.src = self._create_source()