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)

Я надеюсь, что это помогает.

Другие вопросы по тегам