rtsp-сервер ffmpeg не останавливается при отключении однорангового узла
Существует экземпляр ffmpeg, работающий в качестве сервера на VPS, который преобразует видео RTSP в HLS и передает его в Интернет (с использованием Apache). Видео RTSP поступает с компьютера где-то в другом месте (в данном случае в другом городе), к которому у меня подключена IP-камера. Компьютер берет данные RTSP ИЗ IP-камеры и ретранслирует их НА VPS.
Это команда ffmpeg, которую я использую на этом компьютере (можно сказать, рестример):
ffmpeg \
-rtsp_transport tcp \
-i rtsp://[IP address of the camera]:554/live \
-c:v copy \
-f rtsp \
-rtsp_transport tcp \
rtsp://[IP address of the VPS]:4445/live.sdp
И это команда, которую я использую на VPS:
ffmpeg \
-rtsp_flags listen \
-listen_timeout 5 \
-timeout 5000000 \
-rtsp_transport tcp \
-i rtsp://[ip address of the VPS]:4445/live.sdp \
-map 0 \
-flags +global_header \
-fflags +igndts \
-c:v copy \
-g 0 \
-b:v 125k \
-maxrate 250k \
-bufsize 500k \
-hls_time 1 \
-hls_list_size 15 \
-hls_wrap 15 \
-y /dev/shm/hls/video.m3u8
Пока все работает нормально: я могу читать поток HLS в браузере, он довольно стабильный и быстрый. Проблема возникает, когда соединение между рестримером и VPS обрывается: мне приходится подключаться к VPS по SSH и перезапускать экземпляр ffmpeg вручную. Можно ли сказать ffmpeg о «сбое» (или просто остановить его процесс), когда на него не поступает никакой ввод?-i
адрес (на стороне VPS)? Я использую сценарий bash, который автоматически перезапускает процесс, так что об этом позаботятся.
Просто чтобы избежать путаницы: согласно официальной документации ffmpeg,timeout
флаг принимает МИКРОСЕКОНДЫ в качестве значения иlisten_timeout
занимает СЕКУНДЫ. Я видел много постов, где люди спорили по этому поводу :)
1 ответ
Надеюсь, я не опоздал на вечеринку. Я решил аналогичную проблему, отслеживая загрузку процессора. В моем случае, когда камеры перезапускаются или теряется соединение, FFMPEG продолжает работать, но загрузка ЦП падает до 0,0%. Я использую Python для мониторинга этого. Вот важный момент:
import subprocess, psutil
import time, os
# Run ffmpeg command
base_process = subprocess.Popen([
'ffmpeg',
'-rtsp_transport', 'tcp',
'-i', LINK_RTSP,
'-map', '0:v', '-map', '0:a', '-vcodec', 'copy', '-acodec', 'aac', '-t', 60,
os.path.expanduser(f'~/Desktop/{date}.mp4')
])
#Check process by CPU usage
control_process = psutil.Process(base_process.pid)
attempts = 5 #Sleep is 1 second, so if ffmpeg is not using cpu for 5 seconds, kill the process
while base_process.poll() is None:
cpu_percent = control_process.cpu_percent()
if cpu_percent == 0.0:
attempts -= 1
if attempts == 0:
logger.info("ffmpeg is hanging (CPU usage is 0%). Killing the process!")
while base_process.poll() is None:
base_process.terminate()
time.sleep(1)
logger.info(f"Files to be recoved: {date}.mp4")
try:
for camera in connected_cameras.keys():
os.rename(os.path.expanduser(f'{BASE_FOLDER}{camera}/{date}.mp4'), os.path.expanduser(f'{BASE_FOLDER}{camera}/{date}_recovery-needed.mp4'))
except:
pass
break
time.sleep(1)
Я надеюсь, что это помогает.